Barycentric (b0,b1,b2,b3) node order for a VTK Lagrange tetrahedron of degree o (corners, six edges, four faces via the triangle ordering, interior tet recursively).
| 159 | // Barycentric (b0,b1,b2,b3) node order for a VTK Lagrange tetrahedron of degree o |
| 160 | // (corners, six edges, four faces via the triangle ordering, interior tet recursively). |
| 161 | void LagrangeTetBary(int o, Array<B4> &bary) |
| 162 | { |
| 163 | if (o < 0) return; |
| 164 | if (o == 0) { bary.Append(B4{0,0,0,0}); return; } |
| 165 | static const int cmap[4] = {3,0,1,2}; |
| 166 | for (int i = 0; i < 4; i++) { B4 b{0,0,0,0}; b[cmap[i]] = o; bary.Append(b); } |
| 167 | if (o >= 2) |
| 168 | { |
| 169 | static const int E[6][2] = {{3,0},{0,1},{1,3},{3,2},{0,2},{1,2}}; |
| 170 | for (int e = 0; e < 6; e++) |
| 171 | for (int t = 1; t < o; t++) { B4 c{0,0,0,0}; c[E[e][0]] = o-t; c[E[e][1]] = t; bary.Append(c); } |
| 172 | } |
| 173 | if (o >= 3) |
| 174 | { |
| 175 | // for each face: {excluded coord, the 3 active coords in VTK orientation} |
| 176 | static const int faces[4][4] = {{1,0,2,3},{3,2,0,1},{0,2,1,3},{2,1,0,3}}; |
| 177 | Array<B3> tri; LagrangeTriBary(o, tri); |
| 178 | for (int fc = 0; fc < 4; fc++) |
| 179 | for (auto &t : tri) |
| 180 | if (t[0] >= 1 && t[1] >= 1 && t[2] >= 1) // interior of the face triangle |
| 181 | { |
| 182 | B4 c{0,0,0,0}; |
| 183 | c[faces[fc][1]] = t[0]; c[faces[fc][2]] = t[1]; c[faces[fc][3]] = t[2]; |
| 184 | c[faces[fc][0]] = 0; |
| 185 | bary.Append(c); |
| 186 | } |
| 187 | } |
| 188 | if (o >= 4) |
| 189 | { |
| 190 | Array<B4> inner; LagrangeTetBary(o-4, inner); |
| 191 | for (auto &b : inner) bary.Append(B4{b[0]+1,b[1]+1,b[2]+1,b[3]+1}); |
| 192 | } |
| 193 | } |
| 194 | |
| 195 | void GenLagrangeCurve(int o, const VTKLatticeFn &f, Array<int> &pi) |
| 196 | { |
no test coverage detected