TTK
Loading...
Searching...
No Matches
ImplicitTriangulation.cpp
Go to the documentation of this file.
2
3#include <numeric>
4
5using namespace std;
6using namespace ttk;
7
8#define CASE_EDGE_POSITION_L_3D \
9 case EdgePosition::L_xnn_3D: \
10 case EdgePosition::L_xn0_3D: \
11 case EdgePosition::L_xnN_3D: \
12 case EdgePosition::L_x0n_3D: \
13 case EdgePosition::L_x00_3D: \
14 case EdgePosition::L_x0N_3D: \
15 case EdgePosition::L_xNn_3D: \
16 case EdgePosition::L_xN0_3D: \
17 case EdgePosition::L_xNN_3D
18#define CASE_EDGE_POSITION_H_3D \
19 case EdgePosition::H_nyn_3D: \
20 case EdgePosition::H_ny0_3D: \
21 case EdgePosition::H_nyN_3D: \
22 case EdgePosition::H_0yn_3D: \
23 case EdgePosition::H_0y0_3D: \
24 case EdgePosition::H_0yN_3D: \
25 case EdgePosition::H_Nyn_3D: \
26 case EdgePosition::H_Ny0_3D: \
27 case EdgePosition::H_NyN_3D
28#define CASE_EDGE_POSITION_P_3D \
29 case EdgePosition::P_nnz_3D: \
30 case EdgePosition::P_n0z_3D: \
31 case EdgePosition::P_nNz_3D: \
32 case EdgePosition::P_0nz_3D: \
33 case EdgePosition::P_00z_3D: \
34 case EdgePosition::P_0Nz_3D: \
35 case EdgePosition::P_Nnz_3D: \
36 case EdgePosition::P_N0z_3D: \
37 case EdgePosition::P_NNz_3D
38#define CASE_EDGE_POSITION_D1_3D \
39 case EdgePosition::D1_xyn_3D: \
40 case EdgePosition::D1_xy0_3D: \
41 case EdgePosition::D1_xyN_3D
42#define CASE_EDGE_POSITION_D2_3D \
43 case EdgePosition::D2_nyz_3D: \
44 case EdgePosition::D2_0yz_3D: \
45 case EdgePosition::D2_Nyz_3D
46#define CASE_EDGE_POSITION_D3_3D \
47 case EdgePosition::D3_xnz_3D: \
48 case EdgePosition::D3_x0z_3D: \
49 case EdgePosition::D3_xNz_3D
50#define CASE_EDGE_POSITION_L_2D \
51 case EdgePosition::L_xn_2D: \
52 case EdgePosition::L_x0_2D: \
53 case EdgePosition::L_xN_2D
54#define CASE_EDGE_POSITION_H_2D \
55 case EdgePosition::H_ny_2D: \
56 case EdgePosition::H_0y_2D: \
57 case EdgePosition::H_Ny_2D
58
60 : cellNumber_{}, vertexNumber_{}, edgeNumber_{}, triangleNumber_{},
61 tetrahedronNumber_{}, isAccelerated_{} {
62 setDebugMsgPrefix("ImplicitTriangulation");
63#ifdef TTK_ENABLE_MPI
64 this->hasPreconditionedDistributedEdges_ = true;
65 this->hasPreconditionedDistributedTriangles_ = true;
66#endif // TTK_ENABLE_MPI
67}
68
70
71int ImplicitTriangulation::setInputGrid(const float &xOrigin,
72 const float &yOrigin,
73 const float &zOrigin,
74 const float &xSpacing,
75 const float &ySpacing,
76 const float &zSpacing,
77 const SimplexId &xDim,
78 const SimplexId &yDim,
79 const SimplexId &zDim) {
80
81 // Dimensionality //
82 if(xDim < 1 or yDim < 1 or zDim < 1)
83 dimensionality_ = -1;
84 else if(xDim > 1 and yDim > 1 and zDim > 1)
86 else if((xDim > 1 and yDim > 1) or (yDim > 1 and zDim > 1)
87 or (xDim > 1 and zDim > 1))
89 else if(xDim > 1 or yDim > 1 or zDim > 1)
91 else
93
94 // Essentials //
95 origin_[0] = xOrigin;
96 origin_[1] = yOrigin;
97 origin_[2] = zOrigin;
98 spacing_[0] = xSpacing;
99 spacing_[1] = ySpacing;
100 spacing_[2] = zSpacing;
101 dimensions_[0] = xDim;
102 dimensions_[1] = yDim;
103 dimensions_[2] = zDim;
104 nbvoxels_[0] = xDim - 1;
105 nbvoxels_[1] = yDim - 1;
106 nbvoxels_[2] = zDim - 1;
107
108 if(dimensionality_ == 3) {
109 // VertexShift
110 vshift_[0] = xDim;
111 vshift_[1] = xDim * yDim;
112 // EdgeSetDimensions
113 esetdims_[0] = (xDim - 1) * yDim * zDim;
114 esetdims_[1] = xDim * (yDim - 1) * zDim;
115 esetdims_[2] = xDim * yDim * (zDim - 1);
116 esetdims_[3] = (xDim - 1) * (yDim - 1) * zDim;
117 esetdims_[4] = xDim * (yDim - 1) * (zDim - 1);
118 esetdims_[5] = (xDim - 1) * yDim * (zDim - 1);
119 esetdims_[6] = (xDim - 1) * (yDim - 1) * (zDim - 1);
120 // EdgeSetShift
121 esetshift_[0] = esetdims_[0];
122 for(int k = 1; k < 7; ++k)
123 esetshift_[k] = esetshift_[k - 1] + esetdims_[k];
124 // EdgeShift
125 eshift_[0] = xDim - 1;
126 eshift_[1] = (xDim - 1) * yDim;
127 eshift_[2] = xDim;
128 eshift_[3] = xDim * (yDim - 1);
129 eshift_[4] = xDim;
130 eshift_[5] = xDim * yDim;
131 eshift_[6] = xDim - 1;
132 eshift_[7] = (xDim - 1) * (yDim - 1);
133 eshift_[8] = xDim;
134 eshift_[9] = xDim * (yDim - 1);
135 eshift_[10] = xDim - 1;
136 eshift_[11] = (xDim - 1) * yDim;
137 eshift_[12] = xDim - 1;
138 eshift_[13] = (xDim - 1) * (yDim - 1);
139 // TriangleSetDimensions
140 tsetdims_[0] = (xDim - 1) * (yDim - 1) * zDim * 2;
141 tsetdims_[1] = (xDim - 1) * yDim * (zDim - 1) * 2;
142 tsetdims_[2] = xDim * (yDim - 1) * (zDim - 1) * 2;
143 tsetdims_[3] = (xDim - 1) * (yDim - 1) * (zDim - 1) * 2;
144 tsetdims_[4] = (xDim - 1) * (yDim - 1) * (zDim - 1) * 2;
145 tsetdims_[5] = (xDim - 1) * (yDim - 1) * (zDim - 1) * 2;
146 // TriangleSetShift
147 tsetshift_[0] = tsetdims_[0];
148 for(int k = 1; k < 6; ++k)
149 tsetshift_[k] = tsetshift_[k - 1] + tsetdims_[k];
150 // TriangleShift
151 tshift_[0] = (xDim - 1) * 2;
152 tshift_[1] = (xDim - 1) * (yDim - 1) * 2;
153 tshift_[2] = (xDim - 1) * 2;
154 tshift_[3] = (xDim - 1) * yDim * 2;
155 tshift_[4] = xDim * 2;
156 tshift_[5] = xDim * (yDim - 1) * 2;
157 tshift_[6] = (xDim - 1) * 2;
158 tshift_[7] = (xDim - 1) * (yDim - 1) * 2;
159 tshift_[8] = (xDim - 1) * 2;
160 tshift_[9] = (xDim - 1) * (yDim - 1) * 2;
161 tshift_[10] = (xDim - 1) * 2;
162 tshift_[11] = (xDim - 1) * (yDim - 1) * 2;
163 // TetrahedronShift
164 tetshift_[0] = (xDim - 1) * 6;
165 tetshift_[1] = (xDim - 1) * (yDim - 1) * 6;
166
167 // Numbers
168 vertexNumber_ = xDim * yDim * zDim;
169 edgeNumber_ = 0;
170 for(int k = 0; k < 7; ++k)
172 triangleNumber_ = 0;
173 for(int k = 0; k < 6; ++k)
175 tetrahedronNumber_ = (xDim - 1) * (yDim - 1) * (zDim - 1) * 6;
177
179 } else if(dimensionality_ == 2) {
180 // dimensions selectors
181 if(xDim == 1) {
182 Di_ = 1;
183 Dj_ = 2;
184 } else if(yDim == 1) {
185 Di_ = 0;
186 Dj_ = 2;
187 } else {
188 Di_ = 0;
189 Dj_ = 1;
190 }
191 // VertexShift
192 vshift_[0] = dimensions_[Di_];
193 // EdgeSetDimensions
194 esetdims_[0] = (dimensions_[Di_] - 1) * dimensions_[Dj_];
195 esetdims_[1] = dimensions_[Di_] * (dimensions_[Dj_] - 1);
196 esetdims_[2] = (dimensions_[Di_] - 1) * (dimensions_[Dj_] - 1);
197 // EdgeSetShift
198 esetshift_[0] = esetdims_[0];
199 for(int k = 1; k < 3; ++k)
200 esetshift_[k] = esetshift_[k - 1] + esetdims_[k];
201 // EdgeShift
202 eshift_[0] = dimensions_[Di_] - 1;
203 eshift_[2] = dimensions_[Di_];
204 eshift_[4] = dimensions_[Di_] - 1;
205 // TriangleShift
206 tshift_[0] = (dimensions_[Di_] - 1) * 2;
207
208 // Numbers
210 edgeNumber_ = 0;
211 for(int k = 0; k < 3; ++k)
213 triangleNumber_ = (dimensions_[Di_] - 1) * (dimensions_[Dj_] - 1) * 2;
215
217 } else if(dimensionality_ == 1) {
218 // dimensions selectors
219 for(int k = 0; k < 3; ++k) {
220 if(dimensions_[k] > 1) {
221 Di_ = k;
222 break;
223 }
224 }
225
226 // Numbers
230 }
231
232 return 0;
233}
234
236 isAccelerated_ = false;
237
238 unsigned long long int msb[3];
239 if(dimensionality_ == 3) {
240 bool allDimensionsArePowerOfTwo = true;
241 for(int k = 0; k < 3; ++k)
242 if(!isPowerOfTwo(dimensions_[k], msb[k]))
243 allDimensionsArePowerOfTwo = false;
244
245 if(allDimensionsArePowerOfTwo) {
246 mod_[0] = dimensions_[0] - 1;
247 mod_[1] = dimensions_[0] * dimensions_[1] - 1;
248 div_[0] = msb[0];
249 div_[1] = msb[0] + msb[1];
250 isAccelerated_ = true;
251 }
252 } else if(dimensionality_ == 2) {
253 bool isDi = isPowerOfTwo(dimensions_[Di_], msb[Di_]);
254 bool isDj = isPowerOfTwo(dimensions_[Dj_], msb[Dj_]);
255 bool allDimensionsArePowerOfTwo = (isDi and isDj);
256
257 if(allDimensionsArePowerOfTwo) {
258 mod_[0] = dimensions_[Di_] - 1;
259 div_[0] = msb[Di_];
260 isAccelerated_ = true;
261 }
262 }
263
264 if(isAccelerated_) {
265 printMsg("Accelerated getVertex*() requests.", debug::Priority::INFO);
266 }
267
268 return 0;
269}
270
271bool ImplicitTriangulation::isPowerOfTwo(unsigned long long int v,
272 unsigned long long int &r) {
273 if(v && !(v & (v - 1))) {
274 r = 0;
275 while(v >>= 1)
276 r++;
277 return true;
278 }
279 return false;
280}
281
282template <typename Derived>
284 isVertexOnBoundary)(const SimplexId &vertexId) const {
285
286#ifdef TTK_ENABLE_MPI
287 if(this->metaGrid_ != nullptr) {
288 return this->isVertexOnGlobalBoundaryInternal(vertexId);
289 }
290#endif // TTK_ENABLE_MPI
291
292#ifndef TTK_ENABLE_KAMIKAZE
293 if(vertexId < 0 or vertexId >= vertexNumber_)
294 return false;
295#endif // !TTK_ENABLE_KAMIKAZE
296
297 switch(this->underlying().getVertexPosition(vertexId)) {
298 case VertexPosition::CENTER_3D:
299 case VertexPosition::CENTER_2D:
300 case VertexPosition::CENTER_1D:
301 return false;
302 default:
303 return true;
304 }
305}
306
307template <typename Derived>
309 isEdgeOnBoundary)(const SimplexId &edgeId) const {
310
311#ifdef TTK_ENABLE_MPI
312 if(this->metaGrid_ != nullptr) {
313 return this->isEdgeOnGlobalBoundaryInternal(edgeId);
314 }
315#endif // TTK_ENABLE_MPI
316
317#ifndef TTK_ENABLE_KAMIKAZE
318 if(edgeId < 0 or edgeId >= edgeNumber_)
319 return false;
320#endif // !TTK_ENABLE_KAMIKAZE
321
322 switch(this->underlying().getEdgePosition(edgeId)) {
323 case EdgePosition::L_xnn_3D:
324 case EdgePosition::H_nyn_3D:
325 case EdgePosition::P_nnz_3D:
326 case EdgePosition::D1_xyn_3D:
327 case EdgePosition::D2_nyz_3D:
328 case EdgePosition::D3_xnz_3D:
329 case EdgePosition::D4_3D:
330 case EdgePosition::L_xn_2D:
331 case EdgePosition::H_ny_2D:
332 case EdgePosition::D1_2D:
333 return false;
334 default:
335 break;
336 }
337 return true;
338}
339
340bool ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(isTriangleOnBoundary)(
341 const SimplexId &triangleId) const {
342
343#ifdef TTK_ENABLE_MPI
344 if(this->metaGrid_ != nullptr) {
345 return this->isTriangleOnGlobalBoundaryInternal(triangleId);
346 }
347#endif // TTK_ENABLE_MPI
348
349#ifndef TTK_ENABLE_KAMIKAZE
350 if(triangleId < 0 or triangleId >= triangleNumber_)
351 return false;
352#endif // !TTK_ENABLE_KAMIKAZE
353
354 if(dimensionality_ == 3)
355 return (TTK_TRIANGULATION_INTERNAL(getTriangleStarNumber)(triangleId) == 1);
356
357 return false;
358}
359
360template <typename Derived>
362 getVertexNeighbor)(const SimplexId &vertexId,
363 const int &localNeighborId,
364 SimplexId &neighborId) const {
365
366#ifndef TTK_ENABLE_KAMIKAZE
367 if(localNeighborId < 0
368 or localNeighborId >= getVertexNeighborNumber(vertexId))
369 return -1;
370#endif // !TTK_ENABLE_KAMIKAZE
371
372 switch(this->underlying().getVertexPosition(vertexId)) {
373 case VertexPosition::CENTER_3D:
374 neighborId = vertexId + this->vertexNeighborABCDEFGH_[localNeighborId];
375 break;
376 case VertexPosition::FRONT_FACE_3D:
377 neighborId = vertexId + this->vertexNeighborABCD_[localNeighborId];
378 break;
379 case VertexPosition::BACK_FACE_3D:
380 neighborId = vertexId + this->vertexNeighborEFGH_[localNeighborId];
381 break;
382 case VertexPosition::TOP_FACE_3D:
383 neighborId = vertexId + this->vertexNeighborAEFB_[localNeighborId];
384 break;
385 case VertexPosition::BOTTOM_FACE_3D:
386 neighborId = vertexId + this->vertexNeighborGHDC_[localNeighborId];
387 break;
388 case VertexPosition::LEFT_FACE_3D:
389 neighborId = vertexId + this->vertexNeighborAEGC_[localNeighborId];
390 break;
391 case VertexPosition::RIGHT_FACE_3D:
392 neighborId = vertexId + this->vertexNeighborBFHD_[localNeighborId];
393 break;
394 case VertexPosition::TOP_FRONT_EDGE_3D: // ab
395 neighborId = vertexId + this->vertexNeighborAB_[localNeighborId];
396 break;
397 case VertexPosition::BOTTOM_FRONT_EDGE_3D: // cd
398 neighborId = vertexId + this->vertexNeighborCD_[localNeighborId];
399 break;
400 case VertexPosition::LEFT_FRONT_EDGE_3D: // ac
401 neighborId = vertexId + this->vertexNeighborAC_[localNeighborId];
402 break;
403 case VertexPosition::RIGHT_FRONT_EDGE_3D: // bd
404 neighborId = vertexId + this->vertexNeighborBD_[localNeighborId];
405 break;
406 case VertexPosition::TOP_BACK_EDGE_3D: // ef
407 neighborId = vertexId + this->vertexNeighborEF_[localNeighborId];
408 break;
409 case VertexPosition::BOTTOM_BACK_EDGE_3D: // gh
410 neighborId = vertexId + this->vertexNeighborGH_[localNeighborId];
411 break;
412 case VertexPosition::LEFT_BACK_EDGE_3D: // eg
413 neighborId = vertexId + this->vertexNeighborEG_[localNeighborId];
414 break;
415 case VertexPosition::RIGHT_BACK_EDGE_3D: // fh
416 neighborId = vertexId + this->vertexNeighborFH_[localNeighborId];
417 break;
418 case VertexPosition::TOP_LEFT_EDGE_3D: // ae
419 neighborId = vertexId + this->vertexNeighborAE_[localNeighborId];
420 break;
421 case VertexPosition::TOP_RIGHT_EDGE_3D: // bf
422 neighborId = vertexId + this->vertexNeighborBF_[localNeighborId];
423 break;
424 case VertexPosition::BOTTOM_LEFT_EDGE_3D: // cg
425 neighborId = vertexId + this->vertexNeighborCG_[localNeighborId];
426 break;
427 case VertexPosition::BOTTOM_RIGHT_EDGE_3D: // dh
428 neighborId = vertexId + this->vertexNeighborDH_[localNeighborId];
429 break;
430 case VertexPosition::TOP_LEFT_FRONT_CORNER_3D: // a
431 neighborId = vertexId + this->vertexNeighborA_[localNeighborId];
432 break;
433 case VertexPosition::TOP_RIGHT_FRONT_CORNER_3D: // b
434 neighborId = vertexId + this->vertexNeighborB_[localNeighborId];
435 break;
436 case VertexPosition::BOTTOM_LEFT_FRONT_CORNER_3D: // c
437 neighborId = vertexId + this->vertexNeighborC_[localNeighborId];
438 break;
439 case VertexPosition::BOTTOM_RIGHT_FRONT_CORNER_3D: // d
440 neighborId = vertexId + this->vertexNeighborD_[localNeighborId];
441 break;
442 case VertexPosition::TOP_LEFT_BACK_CORNER_3D: // e
443 neighborId = vertexId + this->vertexNeighborE_[localNeighborId];
444 break;
445 case VertexPosition::TOP_RIGHT_BACK_CORNER_3D: // f
446 neighborId = vertexId + this->vertexNeighborF_[localNeighborId];
447 break;
448 case VertexPosition::BOTTOM_LEFT_BACK_CORNER_3D: // g
449 neighborId = vertexId + this->vertexNeighborG_[localNeighborId];
450 break;
451 case VertexPosition::BOTTOM_RIGHT_BACK_CORNER_3D: // h
452 neighborId = vertexId + this->vertexNeighborH_[localNeighborId];
453 break;
454 case VertexPosition::CENTER_2D:
455 neighborId = vertexId + this->vertexNeighbor2dABCD_[localNeighborId];
456 break;
457 case VertexPosition::TOP_EDGE_2D:
458 neighborId = vertexId + this->vertexNeighbor2dAB_[localNeighborId];
459 break;
460 case VertexPosition::BOTTOM_EDGE_2D:
461 neighborId = vertexId + this->vertexNeighbor2dCD_[localNeighborId];
462 break;
463 case VertexPosition::LEFT_EDGE_2D:
464 neighborId = vertexId + this->vertexNeighbor2dAC_[localNeighborId];
465 break;
466 case VertexPosition::RIGHT_EDGE_2D:
467 neighborId = vertexId + this->vertexNeighbor2dBD_[localNeighborId];
468 break;
469 case VertexPosition::TOP_LEFT_CORNER_2D: // a
470 neighborId = vertexId + this->vertexNeighbor2dA_[localNeighborId];
471 break;
472 case VertexPosition::TOP_RIGHT_CORNER_2D: // b
473 neighborId = vertexId + this->vertexNeighbor2dB_[localNeighborId];
474 break;
475 case VertexPosition::BOTTOM_LEFT_CORNER_2D: // c
476 neighborId = vertexId + this->vertexNeighbor2dC_[localNeighborId];
477 break;
478 case VertexPosition::BOTTOM_RIGHT_CORNER_2D: // d
479 neighborId = vertexId + this->vertexNeighbor2dD_[localNeighborId];
480 break;
481 case VertexPosition::CENTER_1D:
482 neighborId = (localNeighborId == 0 ? vertexId + 1 : vertexId - 1);
483 break;
484 case VertexPosition::LEFT_CORNER_1D:
485 neighborId = vertexId + 1;
486 break;
487 case VertexPosition::RIGHT_CORNER_1D:
488 neighborId = vertexId - 1;
489 break;
490 default:
491 neighborId = -1;
492 break;
493 }
494
495 return 0;
496}
497
498const vector<vector<SimplexId>> *
499 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getVertexNeighbors)() {
500 if(vertexNeighborList_.empty()) {
501 Timer t;
502 vertexNeighborList_.resize(vertexNumber_);
503 for(SimplexId i = 0; i < vertexNumber_; ++i) {
504 vertexNeighborList_[i].resize(getVertexNeighborNumber(i));
505 for(SimplexId j = 0; j < (SimplexId)vertexNeighborList_[i].size(); ++j)
506 getVertexNeighbor(i, j, vertexNeighborList_[i][j]);
507 }
508
509 printMsg("Built " + to_string(vertexNumber_) + " vertex neighbors.", 1,
510 t.getElapsedTime(), 1);
511 }
512
513 return &vertexNeighborList_;
514}
515
517 const SimplexId &vertexId) const {
519}
520
521template <typename Derived>
523 const SimplexId &vertexId, const int &localEdgeId, SimplexId &edgeId) const {
524#ifndef TTK_ENABLE_KAMIKAZE
525 if(localEdgeId < 0 or localEdgeId >= getVertexEdgeNumberInternal(vertexId))
526 return -1;
527#endif
528 // e--------f
529 // /| /|
530 // / | / |
531 // a--g-----b--h
532 // | / | /
533 // |/ |/
534 // c--------d
535 //
536 // Classement des "Edges" et dans cet ordre:
537 // L: largeur (type ab)
538 // H: hauteur (type ac)
539 // P: profondeur (type ae)
540 // D1: diagonale1 (type bc)
541 // D2: diagonale2 (type ag)
542 // D3: diagonale3 (type be)
543 // D4: diagonale4 (type bg)
544
545 const auto &p = this->underlying().getVertexCoords(vertexId);
546
547 switch(this->underlying().getVertexPosition(vertexId)) {
548 case VertexPosition::CENTER_3D:
549 edgeId = getVertexEdgeABCDEFGH(p.data(), localEdgeId);
550 break;
551 case VertexPosition::FRONT_FACE_3D:
552 edgeId = getVertexEdgeABDC(p.data(), localEdgeId);
553 break;
554 case VertexPosition::BACK_FACE_3D:
555 edgeId = getVertexEdgeEFHG(p.data(), localEdgeId);
556 break;
557 case VertexPosition::TOP_FACE_3D:
558 edgeId = getVertexEdgeAEFB(p.data(), localEdgeId);
559 break;
560 case VertexPosition::BOTTOM_FACE_3D:
561 edgeId = getVertexEdgeGHDC(p.data(), localEdgeId);
562 break;
563 case VertexPosition::LEFT_FACE_3D:
564 edgeId = getVertexEdgeAEGC(p.data(), localEdgeId);
565 break;
566 case VertexPosition::RIGHT_FACE_3D:
567 edgeId = getVertexEdgeBFHD(p.data(), localEdgeId);
568 break;
569 case VertexPosition::TOP_FRONT_EDGE_3D: // ab
570 edgeId = getVertexEdgeAB(p.data(), localEdgeId);
571 break;
572 case VertexPosition::BOTTOM_FRONT_EDGE_3D: // cd
573 edgeId = getVertexEdgeCD(p.data(), localEdgeId);
574 break;
575 case VertexPosition::LEFT_FRONT_EDGE_3D: // ac
576 edgeId = getVertexEdgeAC(p.data(), localEdgeId);
577 break;
578 case VertexPosition::RIGHT_FRONT_EDGE_3D: // bd
579 edgeId = getVertexEdgeBD(p.data(), localEdgeId);
580 break;
581 case VertexPosition::TOP_BACK_EDGE_3D: // ef
582 edgeId = getVertexEdgeEF(p.data(), localEdgeId);
583 break;
584 case VertexPosition::BOTTOM_BACK_EDGE_3D: // gh
585 edgeId = getVertexEdgeGH(p.data(), localEdgeId);
586 break;
587 case VertexPosition::LEFT_BACK_EDGE_3D: // eg
588 edgeId = getVertexEdgeEG(p.data(), localEdgeId);
589 break;
590 case VertexPosition::RIGHT_BACK_EDGE_3D: // fh
591 edgeId = getVertexEdgeFH(p.data(), localEdgeId);
592 break;
593 case VertexPosition::TOP_LEFT_EDGE_3D: // ae
594 edgeId = getVertexEdgeAE(p.data(), localEdgeId);
595 break;
596 case VertexPosition::TOP_RIGHT_EDGE_3D: // bf
597 edgeId = getVertexEdgeBF(p.data(), localEdgeId);
598 break;
599 case VertexPosition::BOTTOM_LEFT_EDGE_3D: // cg
600 edgeId = getVertexEdgeCG(p.data(), localEdgeId);
601 break;
602 case VertexPosition::BOTTOM_RIGHT_EDGE_3D: // dh
603 edgeId = getVertexEdgeDH(p.data(), localEdgeId);
604 break;
605 case VertexPosition::TOP_LEFT_FRONT_CORNER_3D: // a
606 edgeId = getVertexEdgeA(p.data(), localEdgeId);
607 break;
608 case VertexPosition::TOP_RIGHT_FRONT_CORNER_3D: // b
609 edgeId = getVertexEdgeB(p.data(), localEdgeId);
610 break;
611 case VertexPosition::BOTTOM_LEFT_FRONT_CORNER_3D: // c
612 edgeId = getVertexEdgeC(p.data(), localEdgeId);
613 break;
614 case VertexPosition::BOTTOM_RIGHT_FRONT_CORNER_3D: // d
615 edgeId = getVertexEdgeD(p.data(), localEdgeId);
616 break;
617 case VertexPosition::TOP_LEFT_BACK_CORNER_3D: // e
618 edgeId = getVertexEdgeE(p.data(), localEdgeId);
619 break;
620 case VertexPosition::TOP_RIGHT_BACK_CORNER_3D: // f
621 edgeId = getVertexEdgeF(p.data(), localEdgeId);
622 break;
623 case VertexPosition::BOTTOM_LEFT_BACK_CORNER_3D: // g
624 edgeId = getVertexEdgeG(p.data(), localEdgeId);
625 break;
626 case VertexPosition::BOTTOM_RIGHT_BACK_CORNER_3D: // h
627 edgeId = getVertexEdgeH(p.data(), localEdgeId);
628 break;
629 case VertexPosition::CENTER_2D:
630 edgeId = getVertexEdge2dABCD(p.data(), localEdgeId);
631 break;
632 case VertexPosition::TOP_EDGE_2D:
633 edgeId = getVertexEdge2dAB(p.data(), localEdgeId);
634 break;
635 case VertexPosition::BOTTOM_EDGE_2D:
636 edgeId = getVertexEdge2dCD(p.data(), localEdgeId);
637 break;
638 case VertexPosition::LEFT_EDGE_2D:
639 edgeId = getVertexEdge2dAC(p.data(), localEdgeId);
640 break;
641 case VertexPosition::RIGHT_EDGE_2D:
642 edgeId = getVertexEdge2dBD(p.data(), localEdgeId);
643 break;
644 case VertexPosition::TOP_LEFT_CORNER_2D: // a
645 edgeId = getVertexEdge2dA(p.data(), localEdgeId);
646 break;
647 case VertexPosition::TOP_RIGHT_CORNER_2D: // b
648 edgeId = getVertexEdge2dB(p.data(), localEdgeId);
649 break;
650 case VertexPosition::BOTTOM_LEFT_CORNER_2D: // c
651 edgeId = getVertexEdge2dC(p.data(), localEdgeId);
652 break;
653 case VertexPosition::BOTTOM_RIGHT_CORNER_2D: // d
654 edgeId = getVertexEdge2dD(p.data(), localEdgeId);
655 break;
656 case VertexPosition::CENTER_1D:
657 edgeId = (localEdgeId == 0 ? vertexId : vertexId - 1);
658 break;
659 case VertexPosition::LEFT_CORNER_1D:
660 edgeId = vertexId;
661 break;
662 case VertexPosition::RIGHT_CORNER_1D:
663 edgeId = vertexId - 1;
664 break;
665 default:
666 edgeId = -1;
667 }
668
669 return 0;
670}
671
672const vector<vector<SimplexId>> *
674 if(vertexEdgeList_.empty()) {
675 Timer t;
676
678 for(SimplexId i = 0; i < vertexNumber_; ++i) {
680 for(SimplexId j = 0; j < (SimplexId)vertexEdgeList_[i].size(); ++j)
682 }
683
684 printMsg("Built " + to_string(vertexNumber_) + " vertex edges.", 1,
685 t.getElapsedTime(), 1);
686 }
687
688 return &vertexEdgeList_;
689}
690
691template <typename Derived>
693 const SimplexId &vertexId) const {
694#ifndef TTK_ENABLE_KAMIKAZE
695 if(vertexId < 0 or vertexId >= vertexNumber_)
696 return -1;
697#endif
698
699 switch(this->underlying().getVertexPosition(vertexId)) {
700 case VertexPosition::CENTER_3D:
701 return 36;
702 case VertexPosition::FRONT_FACE_3D:
703 case VertexPosition::BACK_FACE_3D:
704 case VertexPosition::TOP_FACE_3D:
705 case VertexPosition::BOTTOM_FACE_3D:
706 case VertexPosition::LEFT_FACE_3D:
707 case VertexPosition::RIGHT_FACE_3D:
708 return 21;
709 case VertexPosition::TOP_FRONT_EDGE_3D: // ab
710 case VertexPosition::RIGHT_FRONT_EDGE_3D: // bd
711 case VertexPosition::BOTTOM_BACK_EDGE_3D: // gh
712 case VertexPosition::LEFT_BACK_EDGE_3D: // eg
713 case VertexPosition::BOTTOM_LEFT_EDGE_3D: // cg
714 case VertexPosition::TOP_RIGHT_EDGE_3D: // bf
715 return 15;
716 case VertexPosition::TOP_RIGHT_FRONT_CORNER_3D: // b
717 case VertexPosition::BOTTOM_LEFT_BACK_CORNER_3D: // g
718 return 12;
719 case VertexPosition::TOP_BACK_EDGE_3D: // ef
720 case VertexPosition::BOTTOM_FRONT_EDGE_3D: // cd
721 case VertexPosition::LEFT_FRONT_EDGE_3D: // ac
722 case VertexPosition::TOP_LEFT_EDGE_3D: // ae
723 case VertexPosition::RIGHT_BACK_EDGE_3D: // fh
724 case VertexPosition::BOTTOM_RIGHT_EDGE_3D: // dh
725 return 9;
726 case VertexPosition::TOP_LEFT_FRONT_CORNER_3D: // a
727 case VertexPosition::BOTTOM_LEFT_FRONT_CORNER_3D: // c
728 case VertexPosition::BOTTOM_RIGHT_FRONT_CORNER_3D: // d
729 case VertexPosition::TOP_LEFT_BACK_CORNER_3D: // e
730 case VertexPosition::TOP_RIGHT_BACK_CORNER_3D: // f
731 case VertexPosition::BOTTOM_RIGHT_BACK_CORNER_3D: // h
732 return 5;
733 default: // 1D + 2D
734 break;
735 }
736
737 return 0;
738}
739
740template <typename Derived>
742 const SimplexId &vertexId,
743 const int &localTriangleId,
744 SimplexId &triangleId) const {
745#ifndef TTK_ENABLE_KAMIKAZE
746 if(localTriangleId < 0
747 or localTriangleId >= getVertexTriangleNumberInternal(vertexId))
748 return -1;
749#endif
750
751 const auto &p = this->underlying().getVertexCoords(vertexId);
752
753 switch(this->underlying().getVertexPosition(vertexId)) {
754 case VertexPosition::CENTER_3D:
755 triangleId = getVertexTriangleABCDEFGH(p.data(), localTriangleId);
756 break;
757 case VertexPosition::FRONT_FACE_3D:
758 triangleId = getVertexTriangleABDC(p.data(), localTriangleId);
759 break;
760 case VertexPosition::BACK_FACE_3D:
761 triangleId = getVertexTriangleEFHG(p.data(), localTriangleId);
762 break;
763 case VertexPosition::TOP_FACE_3D:
764 triangleId = getVertexTriangleAEFB(p.data(), localTriangleId);
765 break;
766 case VertexPosition::BOTTOM_FACE_3D:
767 triangleId = getVertexTriangleGHDC(p.data(), localTriangleId);
768 break;
769 case VertexPosition::LEFT_FACE_3D:
770 triangleId = getVertexTriangleAEGC(p.data(), localTriangleId);
771 break;
772 case VertexPosition::RIGHT_FACE_3D:
773 triangleId = getVertexTriangleBFHD(p.data(), localTriangleId);
774 break;
775 case VertexPosition::TOP_FRONT_EDGE_3D: // ab
776 triangleId = getVertexTriangleAB(p.data(), localTriangleId);
777 break;
778 case VertexPosition::BOTTOM_FRONT_EDGE_3D: // cd
779 triangleId = getVertexTriangleCD(p.data(), localTriangleId);
780 break;
781 case VertexPosition::LEFT_FRONT_EDGE_3D: // ac
782 triangleId = getVertexTriangleAC(p.data(), localTriangleId);
783 break;
784 case VertexPosition::RIGHT_FRONT_EDGE_3D: // bd
785 triangleId = getVertexTriangleBD(p.data(), localTriangleId);
786 break;
787 case VertexPosition::TOP_BACK_EDGE_3D: // ef
788 triangleId = getVertexTriangleEF(p.data(), localTriangleId);
789 break;
790 case VertexPosition::BOTTOM_BACK_EDGE_3D: // gh
791 triangleId = getVertexTriangleGH(p.data(), localTriangleId);
792 break;
793 case VertexPosition::LEFT_BACK_EDGE_3D: // eg
794 triangleId = getVertexTriangleEG(p.data(), localTriangleId);
795 break;
796 case VertexPosition::RIGHT_BACK_EDGE_3D: // fh
797 triangleId = getVertexTriangleFH(p.data(), localTriangleId);
798 break;
799 case VertexPosition::TOP_LEFT_EDGE_3D: // ae
800 triangleId = getVertexTriangleAE(p.data(), localTriangleId);
801 break;
802 case VertexPosition::TOP_RIGHT_EDGE_3D: // bf
803 triangleId = getVertexTriangleBF(p.data(), localTriangleId);
804 break;
805 case VertexPosition::BOTTOM_LEFT_EDGE_3D: // cg
806 triangleId = getVertexTriangleCG(p.data(), localTriangleId);
807 break;
808 case VertexPosition::BOTTOM_RIGHT_EDGE_3D: // dh
809 triangleId = getVertexTriangleDH(p.data(), localTriangleId);
810 break;
811 case VertexPosition::TOP_LEFT_FRONT_CORNER_3D: // a
812 triangleId = getVertexTriangleA(p.data(), localTriangleId);
813 break;
814 case VertexPosition::TOP_RIGHT_FRONT_CORNER_3D: // b
815 triangleId = getVertexTriangleB(p.data(), localTriangleId);
816 break;
817 case VertexPosition::BOTTOM_LEFT_FRONT_CORNER_3D: // c
818 triangleId = getVertexTriangleC(p.data(), localTriangleId);
819 break;
820 case VertexPosition::BOTTOM_RIGHT_FRONT_CORNER_3D: // d
821 triangleId = getVertexTriangleD(p.data(), localTriangleId);
822 break;
823 case VertexPosition::TOP_LEFT_BACK_CORNER_3D: // e
824 triangleId = getVertexTriangleE(p.data(), localTriangleId);
825 break;
826 case VertexPosition::TOP_RIGHT_BACK_CORNER_3D: // f
827 triangleId = getVertexTriangleF(p.data(), localTriangleId);
828 break;
829 case VertexPosition::BOTTOM_LEFT_BACK_CORNER_3D: // g
830 triangleId = getVertexTriangleG(p.data(), localTriangleId);
831 break;
832 case VertexPosition::BOTTOM_RIGHT_BACK_CORNER_3D: // h
833 triangleId = getVertexTriangleH(p.data(), localTriangleId);
834 break;
835 default: // 1D + 2D
836 triangleId = -1;
837 break;
838 }
839
840 return 0;
841}
842
843const vector<vector<SimplexId>> *
845 if(vertexTriangleList_.empty()) {
846 Timer t;
847
849 for(SimplexId i = 0; i < vertexNumber_; ++i) {
851 for(SimplexId j = 0; j < (SimplexId)vertexTriangleList_[i].size(); ++j)
853 }
854
855 printMsg("Built " + to_string(vertexNumber_) + " vertex triangles.", 1,
856 t.getElapsedTime(), 1);
857 }
858
859 return &vertexTriangleList_;
860}
861
862SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
863 getVertexLinkNumber)(const SimplexId &vertexId) const {
865}
866
867template <typename Derived>
869 getVertexLink)(const SimplexId &vertexId,
870 const int &localLinkId,
871 SimplexId &linkId) const {
872
873#ifndef TTK_ENABLE_KAMIKAZE
874 if(localLinkId < 0 or localLinkId >= getVertexLinkNumber(vertexId))
875 return -1;
876#endif // !TTK_ENABLE_KAMIKAZE
877
878 const auto &p = this->underlying().getVertexCoords(vertexId);
879
880 switch(this->underlying().getVertexPosition(vertexId)) {
881 case VertexPosition::CENTER_3D:
882 linkId = getVertexLinkABCDEFGH(p.data(), localLinkId);
883 break;
884 case VertexPosition::FRONT_FACE_3D:
885 linkId = getVertexLinkABDC(p.data(), localLinkId);
886 break;
887 case VertexPosition::BACK_FACE_3D:
888 linkId = getVertexLinkEFHG(p.data(), localLinkId);
889 break;
890 case VertexPosition::TOP_FACE_3D:
891 linkId = getVertexLinkAEFB(p.data(), localLinkId);
892 break;
893 case VertexPosition::BOTTOM_FACE_3D:
894 linkId = getVertexLinkGHDC(p.data(), localLinkId);
895 break;
896 case VertexPosition::LEFT_FACE_3D:
897 linkId = getVertexLinkAEGC(p.data(), localLinkId);
898 break;
899 case VertexPosition::RIGHT_FACE_3D:
900 linkId = getVertexLinkBFHD(p.data(), localLinkId);
901 break;
902 case VertexPosition::TOP_FRONT_EDGE_3D: // ab
903 linkId = getVertexLinkAB(p.data(), localLinkId);
904 break;
905 case VertexPosition::BOTTOM_FRONT_EDGE_3D: // cd
906 linkId = getVertexLinkCD(p.data(), localLinkId);
907 break;
908 case VertexPosition::LEFT_FRONT_EDGE_3D: // ac
909 linkId = getVertexLinkAC(p.data(), localLinkId);
910 break;
911 case VertexPosition::RIGHT_FRONT_EDGE_3D: // bd
912 linkId = getVertexLinkBD(p.data(), localLinkId);
913 break;
914 case VertexPosition::TOP_BACK_EDGE_3D: // ef
915 linkId = getVertexLinkEF(p.data(), localLinkId);
916 break;
917 case VertexPosition::BOTTOM_BACK_EDGE_3D: // gh
918 linkId = getVertexLinkGH(p.data(), localLinkId);
919 break;
920 case VertexPosition::LEFT_BACK_EDGE_3D: // eg
921 linkId = getVertexLinkEG(p.data(), localLinkId);
922 break;
923 case VertexPosition::RIGHT_BACK_EDGE_3D: // fh
924 linkId = getVertexLinkFH(p.data(), localLinkId);
925 break;
926 case VertexPosition::TOP_LEFT_EDGE_3D: // ae
927 linkId = getVertexLinkAE(p.data(), localLinkId);
928 break;
929 case VertexPosition::TOP_RIGHT_EDGE_3D: // bf
930 linkId = getVertexLinkBF(p.data(), localLinkId);
931 break;
932 case VertexPosition::BOTTOM_LEFT_EDGE_3D: // cg
933 linkId = getVertexLinkCG(p.data(), localLinkId);
934 break;
935 case VertexPosition::BOTTOM_RIGHT_EDGE_3D: // dh
936 linkId = getVertexLinkDH(p.data(), localLinkId);
937 break;
938 case VertexPosition::TOP_LEFT_FRONT_CORNER_3D: // a
939 linkId = getVertexLinkA(p.data(), localLinkId);
940 break;
941 case VertexPosition::TOP_RIGHT_FRONT_CORNER_3D: // b
942 linkId = getVertexLinkB(p.data(), localLinkId);
943 break;
944 case VertexPosition::BOTTOM_LEFT_FRONT_CORNER_3D: // c
945 linkId = getVertexLinkC(p.data(), localLinkId);
946 break;
947 case VertexPosition::BOTTOM_RIGHT_FRONT_CORNER_3D: // d
948 linkId = getVertexLinkD(p.data(), localLinkId);
949 break;
950 case VertexPosition::TOP_LEFT_BACK_CORNER_3D: // e
951 linkId = getVertexLinkE(p.data(), localLinkId);
952 break;
953 case VertexPosition::TOP_RIGHT_BACK_CORNER_3D: // f
954 linkId = getVertexLinkF(p.data(), localLinkId);
955 break;
956 case VertexPosition::BOTTOM_LEFT_BACK_CORNER_3D: // g
957 linkId = getVertexLinkG(p.data(), localLinkId);
958 break;
959 case VertexPosition::BOTTOM_RIGHT_BACK_CORNER_3D: // h
960 linkId = getVertexLinkH(p.data(), localLinkId);
961 break;
962 case VertexPosition::CENTER_2D:
963 linkId = getVertexLink2dABCD(p.data(), localLinkId);
964 break;
965 case VertexPosition::TOP_EDGE_2D:
966 linkId = getVertexLink2dAB(p.data(), localLinkId);
967 break;
968 case VertexPosition::BOTTOM_EDGE_2D:
969 linkId = getVertexLink2dCD(p.data(), localLinkId);
970 break;
971 case VertexPosition::LEFT_EDGE_2D:
972 linkId = getVertexLink2dAC(p.data(), localLinkId);
973 break;
974 case VertexPosition::RIGHT_EDGE_2D:
975 linkId = getVertexLink2dBD(p.data(), localLinkId);
976 break;
977 case VertexPosition::TOP_LEFT_CORNER_2D: // a
978 linkId = getVertexLink2dA(p.data(), localLinkId);
979 break;
980 case VertexPosition::TOP_RIGHT_CORNER_2D: // b
981 linkId = getVertexLink2dB(p.data(), localLinkId);
982 break;
983 case VertexPosition::BOTTOM_LEFT_CORNER_2D: // c
984 linkId = getVertexLink2dC(p.data(), localLinkId);
985 break;
986 case VertexPosition::BOTTOM_RIGHT_CORNER_2D: // d
987 linkId = getVertexLink2dD(p.data(), localLinkId);
988 break;
989 default: // 1D
990 linkId = -1;
991 break;
992 };
993
994 return 0;
995}
996
997const vector<vector<SimplexId>> *
998 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getVertexLinks)() {
999 if(vertexLinkList_.empty()) {
1001
1002 vertexLinkList_.resize(vertexNumber_);
1003 for(SimplexId i = 0; i < vertexNumber_; ++i) {
1004 vertexLinkList_[i].resize(getVertexLinkNumber(i));
1005 for(SimplexId j = 0; j < (SimplexId)vertexLinkList_[i].size(); ++j)
1006 getVertexLink(i, j, vertexLinkList_[i][j]);
1008
1009 printMsg("Built " + to_string(vertexNumber_) + " vertex links.", 1,
1010 t.getElapsedTime(), 1);
1012
1013 return &vertexLinkList_;
1014}
1016template <typename Derived>
1018 getVertexStarNumber)(const SimplexId &vertexId) const {
1019
1020#ifndef TTK_ENABLE_KAMIKAZE
1021 if(vertexId < 0 or vertexId >= vertexNumber_)
1022 return -1;
1023#endif // !TTK_ENABLE_KAMIKAZE
1024
1025 switch(this->underlying().getVertexPosition(vertexId)) {
1026 case VertexPosition::CENTER_3D:
1027 return 24;
1028 case VertexPosition::FRONT_FACE_3D:
1029 case VertexPosition::BACK_FACE_3D:
1030 case VertexPosition::TOP_FACE_3D:
1031 case VertexPosition::BOTTOM_FACE_3D:
1032 case VertexPosition::LEFT_FACE_3D:
1033 case VertexPosition::RIGHT_FACE_3D:
1034 return 12;
1035 case VertexPosition::TOP_FRONT_EDGE_3D: // ab
1036 case VertexPosition::RIGHT_FRONT_EDGE_3D: // bd
1037 case VertexPosition::BOTTOM_BACK_EDGE_3D: // gh
1038 case VertexPosition::LEFT_BACK_EDGE_3D: // eg
1039 case VertexPosition::BOTTOM_LEFT_EDGE_3D: // cg
1040 case VertexPosition::TOP_RIGHT_EDGE_3D: // bf
1041 return 8;
1042 case VertexPosition::TOP_RIGHT_FRONT_CORNER_3D: // b
1043 case VertexPosition::BOTTOM_LEFT_BACK_CORNER_3D: // g
1044 case VertexPosition::CENTER_2D:
1045 return 6;
1046 case VertexPosition::TOP_BACK_EDGE_3D: // ef
1047 case VertexPosition::BOTTOM_FRONT_EDGE_3D: // cd
1048 case VertexPosition::LEFT_FRONT_EDGE_3D: // ac
1049 case VertexPosition::TOP_LEFT_EDGE_3D: // ae
1050 case VertexPosition::RIGHT_BACK_EDGE_3D: // fh
1051 case VertexPosition::BOTTOM_RIGHT_EDGE_3D: // dh
1052 return 4;
1053 case VertexPosition::TOP_EDGE_2D: // ab
1054 case VertexPosition::BOTTOM_EDGE_2D: // cd
1055 case VertexPosition::LEFT_EDGE_2D: // ac
1056 case VertexPosition::RIGHT_EDGE_2D: // bd
1057 return 3;
1058 case VertexPosition::TOP_LEFT_FRONT_CORNER_3D: // a
1059 case VertexPosition::BOTTOM_LEFT_FRONT_CORNER_3D: // c
1060 case VertexPosition::BOTTOM_RIGHT_FRONT_CORNER_3D: // d
1061 case VertexPosition::TOP_LEFT_BACK_CORNER_3D: // e
1062 case VertexPosition::TOP_RIGHT_BACK_CORNER_3D: // f
1063 case VertexPosition::BOTTOM_RIGHT_BACK_CORNER_3D: // h
1064 case VertexPosition::TOP_RIGHT_CORNER_2D: // b
1065 case VertexPosition::BOTTOM_LEFT_CORNER_2D: // c
1066 return 2;
1067 case VertexPosition::TOP_LEFT_CORNER_2D: // a
1068 case VertexPosition::BOTTOM_RIGHT_CORNER_2D: // d
1069 return 1;
1070 default: // 1D
1071 break;
1072 }
1073
1074 return 0;
1075}
1076
1077template <typename Derived>
1079 getVertexStar)(const SimplexId &vertexId,
1080 const int &localStarId,
1081 SimplexId &starId) const {
1082
1083#ifndef TTK_ENABLE_KAMIKAZE
1084 if(localStarId < 0 or localStarId >= getVertexStarNumber(vertexId))
1085 return -1;
1086#endif // !TTK_ENABLE_KAMIKAZE
1087
1088 const auto &p = this->underlying().getVertexCoords(vertexId);
1089
1090 switch(this->underlying().getVertexPosition(vertexId)) {
1091 case VertexPosition::CENTER_3D:
1092 starId = getVertexStarABCDEFGH(p.data(), localStarId);
1093 break;
1094 case VertexPosition::FRONT_FACE_3D:
1095 starId = getVertexStarABDC(p.data(), localStarId);
1096 break;
1097 case VertexPosition::BACK_FACE_3D:
1098 starId = getVertexStarEFHG(p.data(), localStarId);
1099 break;
1100 case VertexPosition::TOP_FACE_3D:
1101 starId = getVertexStarAEFB(p.data(), localStarId);
1102 break;
1103 case VertexPosition::BOTTOM_FACE_3D:
1104 starId = getVertexStarGHDC(p.data(), localStarId);
1105 break;
1106 case VertexPosition::LEFT_FACE_3D:
1107 starId = getVertexStarAEGC(p.data(), localStarId);
1108 break;
1109 case VertexPosition::RIGHT_FACE_3D:
1110 starId = getVertexStarBFHD(p.data(), localStarId);
1111 break;
1112 case VertexPosition::TOP_FRONT_EDGE_3D: // ab
1113 starId = getVertexStarAB(p.data(), localStarId);
1114 break;
1115 case VertexPosition::BOTTOM_FRONT_EDGE_3D: // cd
1116 starId = getVertexStarCD(p.data(), localStarId);
1117 break;
1118 case VertexPosition::LEFT_FRONT_EDGE_3D: // ac
1119 starId = getVertexStarAC(p.data(), localStarId);
1120 break;
1121 case VertexPosition::RIGHT_FRONT_EDGE_3D: // bd
1122 starId = getVertexStarBD(p.data(), localStarId);
1123 break;
1124 case VertexPosition::TOP_BACK_EDGE_3D: // ef
1125 starId = getVertexStarEF(p.data(), localStarId);
1126 break;
1127 case VertexPosition::BOTTOM_BACK_EDGE_3D: // gh
1128 starId = getVertexStarGH(p.data(), localStarId);
1129 break;
1130 case VertexPosition::LEFT_BACK_EDGE_3D: // eg
1131 starId = getVertexStarEG(p.data(), localStarId);
1132 break;
1133 case VertexPosition::RIGHT_BACK_EDGE_3D: // fh
1134 starId = getVertexStarFH(p.data(), localStarId);
1135 break;
1136 case VertexPosition::TOP_LEFT_EDGE_3D: // ae
1137 starId = getVertexStarAE(p.data(), localStarId);
1138 break;
1139 case VertexPosition::TOP_RIGHT_EDGE_3D: // bf
1140 starId = getVertexStarBF(p.data(), localStarId);
1141 break;
1142 case VertexPosition::BOTTOM_LEFT_EDGE_3D: // cg
1143 starId = getVertexStarCG(p.data(), localStarId);
1144 break;
1145 case VertexPosition::BOTTOM_RIGHT_EDGE_3D: // dh
1146 starId = getVertexStarDH(p.data(), localStarId);
1147 break;
1148 case VertexPosition::TOP_LEFT_FRONT_CORNER_3D: // a
1149 starId = getVertexStarA(p.data(), localStarId);
1150 break;
1151 case VertexPosition::TOP_RIGHT_FRONT_CORNER_3D: // b
1152 starId = getVertexStarB(p.data(), localStarId);
1153 break;
1154 case VertexPosition::BOTTOM_LEFT_FRONT_CORNER_3D: // c
1155 starId = getVertexStarC(p.data(), localStarId);
1156 break;
1157 case VertexPosition::BOTTOM_RIGHT_FRONT_CORNER_3D: // d
1158 starId = getVertexStarD(p.data(), localStarId);
1159 break;
1160 case VertexPosition::TOP_LEFT_BACK_CORNER_3D: // e
1161 starId = getVertexStarE(p.data(), localStarId);
1162 break;
1163 case VertexPosition::TOP_RIGHT_BACK_CORNER_3D: // f
1164 starId = getVertexStarF(p.data(), localStarId);
1165 break;
1166 case VertexPosition::BOTTOM_LEFT_BACK_CORNER_3D: // g
1167 starId = getVertexStarG(p.data(), localStarId);
1168 break;
1169 case VertexPosition::BOTTOM_RIGHT_BACK_CORNER_3D: // h
1170 starId = getVertexStarH(p.data(), localStarId);
1171 break;
1172 case VertexPosition::CENTER_2D:
1173 starId = getVertexStar2dABCD(p.data(), localStarId);
1174 break;
1175 case VertexPosition::TOP_EDGE_2D:
1176 starId = getVertexStar2dAB(p.data(), localStarId);
1177 break;
1178 case VertexPosition::BOTTOM_EDGE_2D:
1179 starId = getVertexStar2dCD(p.data(), localStarId);
1180 break;
1181 case VertexPosition::LEFT_EDGE_2D:
1182 starId = getVertexStar2dAC(p.data(), localStarId);
1183 break;
1184 case VertexPosition::RIGHT_EDGE_2D:
1185 starId = getVertexStar2dBD(p.data(), localStarId);
1186 break;
1187 case VertexPosition::TOP_LEFT_CORNER_2D: // a
1188 starId = getVertexStar2dA(p.data(), localStarId);
1189 break;
1190 case VertexPosition::TOP_RIGHT_CORNER_2D: // b
1191 starId = getVertexStar2dB(p.data(), localStarId);
1192 break;
1193 case VertexPosition::BOTTOM_LEFT_CORNER_2D: // c
1194 starId = getVertexStar2dC(p.data(), localStarId);
1195 break;
1196 case VertexPosition::BOTTOM_RIGHT_CORNER_2D: // d
1197 starId = getVertexStar2dD(p.data(), localStarId);
1198 break;
1199 default: // 1D
1200 starId = -1;
1201 break;
1202 }
1203
1204 return 0;
1205}
1206
1207const vector<vector<SimplexId>> *
1208 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getVertexStars)() {
1209
1210 if(vertexStarList_.empty()) {
1211 Timer t;
1212 vertexStarList_.resize(vertexNumber_);
1213 for(SimplexId i = 0; i < vertexNumber_; ++i) {
1214 vertexStarList_[i].resize(getVertexStarNumber(i));
1215 for(SimplexId j = 0; j < (SimplexId)vertexStarList_[i].size(); ++j)
1216 getVertexStar(i, j, vertexStarList_[i][j]);
1217 }
1218
1219 printMsg("Built " + to_string(vertexNumber_) + " vertex stars.", 1,
1220 t.getElapsedTime(), 1);
1221 }
1222
1223 return &vertexStarList_;
1224}
1225
1226template <typename Derived>
1228 getVertexPoint)(const SimplexId &vertexId,
1229 float &x,
1230 float &y,
1231 float &z) const {
1232
1233 if(dimensionality_ == 3) {
1234 const auto &p = this->underlying().getVertexCoords(vertexId);
1235
1236 x = origin_[0] + spacing_[0] * p[0];
1237 y = origin_[1] + spacing_[1] * p[1];
1238 z = origin_[2] + spacing_[2] * p[2];
1239 } else if(dimensionality_ == 2) {
1240 const auto &p = this->underlying().getVertexCoords(vertexId);
1241
1242 if(dimensions_[0] > 1 and dimensions_[1] > 1) {
1243 x = origin_[0] + spacing_[0] * p[0];
1244 y = origin_[1] + spacing_[1] * p[1];
1245 z = origin_[2];
1246 } else if(dimensions_[1] > 1 and dimensions_[2] > 1) {
1247 x = origin_[0];
1248 y = origin_[1] + spacing_[1] * p[0];
1249 z = origin_[2] + spacing_[2] * p[1];
1250 } else if(dimensions_[0] > 1 and dimensions_[2] > 1) {
1251 x = origin_[0] + spacing_[0] * p[0];
1252 y = origin_[1];
1253 z = origin_[2] + spacing_[2] * p[1];
1254 }
1255 } else if(dimensionality_ == 1) {
1256 if(dimensions_[0] > 1) {
1257 x = origin_[0] + spacing_[0] * vertexId;
1258 y = origin_[1];
1259 z = origin_[2];
1260 } else if(dimensions_[1] > 1) {
1261 x = origin_[0];
1262 y = origin_[1] + spacing_[1] * vertexId;
1263 z = origin_[2];
1264 } else if(dimensions_[2] > 1) {
1265 x = origin_[0];
1266 y = origin_[1];
1267 z = origin_[2] + spacing_[2] * vertexId;
1268 }
1269 }
1270
1271 return 0;
1272}
1273
1274template <typename Derived>
1276 const SimplexId &edgeId,
1277 const int &localVertexId,
1278 SimplexId &vertexId) const {
1279#ifndef TTK_ENABLE_KAMIKAZE
1280 if(edgeId < 0 or edgeId >= edgeNumber_)
1281 return -1;
1282 if(localVertexId < 0 or localVertexId >= 2)
1283 return -2;
1284#endif
1285
1286 const auto &p = this->underlying().getEdgeCoords(edgeId);
1287
1288 const auto helper3d = [&](const SimplexId a, const SimplexId b) -> SimplexId {
1289 if(isAccelerated_) {
1290 const auto tmp = p[0] + (p[1] << div_[0]) + (p[2] << div_[1]);
1291 return (localVertexId == 0) ? tmp + a : tmp + b;
1292 } else {
1293 const auto tmp = p[0] + (p[1] * vshift_[0]) + (p[2] * vshift_[1]);
1294 return (localVertexId == 0) ? tmp + a : tmp + b;
1295 }
1296 };
1297
1298 const auto helper2d = [&](const SimplexId a, const SimplexId b) -> SimplexId {
1299 if(isAccelerated_) {
1300 const auto tmp = p[0] + (p[1] << div_[0]);
1301 return localVertexId == 0 ? tmp + a : tmp + b;
1302 } else {
1303 const auto tmp = p[0] + (p[1] * vshift_[0]);
1304 return localVertexId == 0 ? tmp + a : tmp + b;
1305 }
1306 };
1307
1308 switch(this->underlying().getEdgePosition(edgeId)) {
1310 vertexId = helper3d(0, 1);
1311 break;
1313 vertexId = helper3d(0, vshift_[0]);
1314 break;
1316 vertexId = helper3d(0, vshift_[1]);
1317 break;
1319 vertexId = helper3d(1, vshift_[0]);
1320 break;
1322 vertexId = helper3d(0, vshift_[0] + vshift_[1]);
1323 break;
1325 vertexId = helper3d(1, vshift_[1]);
1326 break;
1327 case EdgePosition::D4_3D:
1328 vertexId = helper3d(1, vshift_[0] + vshift_[1]);
1329 break;
1330
1332 vertexId = helper2d(0, 1);
1333 break;
1335 vertexId = helper2d(0, vshift_[0]);
1336 break;
1337 case EdgePosition::D1_2D:
1338 vertexId = helper2d(1, vshift_[0]);
1339 break;
1340
1341 case EdgePosition::FIRST_EDGE_1D:
1342 vertexId = localVertexId == 0 ? 0 : 1;
1343 break;
1344 case EdgePosition::LAST_EDGE_1D:
1345 vertexId = localVertexId == 0 ? edgeNumber_ - 1 : edgeNumber_;
1346 break;
1347 case EdgePosition::CENTER_1D:
1348 vertexId = localVertexId == 0 ? edgeId : edgeId + 1;
1349 break;
1350 }
1351
1352 return 0;
1353}
1354
1355const vector<std::array<SimplexId, 2>> *
1356 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdges)() {
1357
1358 if(edgeList_.empty()) {
1359 Timer t;
1360
1361 edgeList_.resize(edgeNumber_);
1362 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1363 SimplexId id0, id1;
1364 getEdgeVertexInternal(i, 0, id0);
1365 getEdgeVertexInternal(i, 1, id1);
1366 edgeList_[i] = {id0, id1};
1367 }
1368
1369 printMsg(
1370 "Built " + to_string(edgeNumber_) + " edges.", 1, t.getElapsedTime(), 1);
1371 }
1372
1373 return &edgeList_;
1374}
1375
1376template <typename Derived>
1378 const SimplexId &edgeId) const {
1379#ifndef TTK_ENABLE_KAMIKAZE
1380 if(edgeId < 0 or edgeId >= edgeNumber_)
1381 return -1;
1382#endif
1383
1384 switch(this->underlying().getEdgePosition(edgeId)) {
1385 case EdgePosition::L_xnn_3D:
1386 case EdgePosition::H_nyn_3D:
1387 case EdgePosition::P_nnz_3D:
1388 case EdgePosition::D4_3D:
1389 return 6;
1390 case EdgePosition::L_x0n_3D:
1391 case EdgePosition::L_xNn_3D:
1392 case EdgePosition::L_xn0_3D:
1393 case EdgePosition::L_xnN_3D:
1394 case EdgePosition::H_ny0_3D:
1395 case EdgePosition::H_nyN_3D:
1396 case EdgePosition::H_0yn_3D:
1397 case EdgePosition::H_Nyn_3D:
1398 case EdgePosition::P_n0z_3D:
1399 case EdgePosition::P_nNz_3D:
1400 case EdgePosition::P_0nz_3D:
1401 case EdgePosition::P_Nnz_3D:
1402 case EdgePosition::D1_xyn_3D:
1403 case EdgePosition::D2_nyz_3D:
1404 case EdgePosition::D3_xnz_3D:
1405 return 4;
1406 case EdgePosition::L_x00_3D:
1407 case EdgePosition::L_xNN_3D:
1408 case EdgePosition::H_0yN_3D:
1409 case EdgePosition::H_Ny0_3D:
1410 case EdgePosition::P_0Nz_3D:
1411 case EdgePosition::P_N0z_3D:
1412 case EdgePosition::D1_xy0_3D:
1413 case EdgePosition::D1_xyN_3D:
1414 case EdgePosition::D2_0yz_3D:
1415 case EdgePosition::D2_Nyz_3D:
1416 case EdgePosition::D3_x0z_3D:
1417 case EdgePosition::D3_xNz_3D:
1418 return 3;
1419 case EdgePosition::L_xN0_3D:
1420 case EdgePosition::L_x0N_3D:
1421 case EdgePosition::H_0y0_3D:
1422 case EdgePosition::H_NyN_3D:
1423 case EdgePosition::P_00z_3D:
1424 case EdgePosition::P_NNz_3D:
1425 case EdgePosition::L_xn_2D:
1426 case EdgePosition::H_ny_2D:
1427 case EdgePosition::D1_2D:
1428 return 2;
1429 case EdgePosition::L_x0_2D:
1430 case EdgePosition::L_xN_2D:
1431 case EdgePosition::H_0y_2D:
1432 case EdgePosition::H_Ny_2D:
1433 return 1;
1434
1435 default: // 1D
1436 break;
1437 }
1438
1439 return 0;
1440}
1441
1442template <typename Derived>
1444 const SimplexId &edgeId,
1445 const int &localTriangleId,
1446 SimplexId &triangleId) const {
1447#ifndef TTK_ENABLE_KAMIKAZE
1448 if(localTriangleId < 0
1449 or localTriangleId >= getEdgeTriangleNumberInternal(edgeId))
1450 return -1;
1451#endif
1452
1453 const auto &p = this->underlying().getEdgeCoords(edgeId);
1454
1455 switch(this->underlying().getEdgePosition(edgeId)) {
1456 case EdgePosition::L_xnn_3D:
1457 triangleId = getEdgeTriangleL_xnn(p.data(), localTriangleId);
1458 break;
1459 case EdgePosition::L_xn0_3D:
1460 triangleId = getEdgeTriangleL_xn0(p.data(), localTriangleId);
1461 break;
1462 case EdgePosition::L_xnN_3D:
1463 triangleId = getEdgeTriangleL_xnN(p.data(), localTriangleId);
1464 break;
1465 case EdgePosition::L_x0n_3D:
1466 triangleId = getEdgeTriangleL_x0n(p.data(), localTriangleId);
1467 break;
1468 case EdgePosition::L_x00_3D:
1469 triangleId = getEdgeTriangleL_x00(p.data(), localTriangleId);
1470 break;
1471 case EdgePosition::L_x0N_3D:
1472 triangleId = getEdgeTriangleL_x0N(p.data(), localTriangleId);
1473 break;
1474 case EdgePosition::L_xNn_3D:
1475 triangleId = getEdgeTriangleL_xNn(p.data(), localTriangleId);
1476 break;
1477 case EdgePosition::L_xN0_3D:
1478 triangleId = getEdgeTriangleL_xN0(p.data(), localTriangleId);
1479 break;
1480 case EdgePosition::L_xNN_3D:
1481 triangleId = getEdgeTriangleL_xNN(p.data(), localTriangleId);
1482 break;
1483 case EdgePosition::H_nyn_3D:
1484 triangleId = getEdgeTriangleH_nyn(p.data(), localTriangleId);
1485 break;
1486 case EdgePosition::H_ny0_3D:
1487 triangleId = getEdgeTriangleH_ny0(p.data(), localTriangleId);
1488 break;
1489 case EdgePosition::H_nyN_3D:
1490 triangleId = getEdgeTriangleH_nyN(p.data(), localTriangleId);
1491 break;
1492 case EdgePosition::H_0yn_3D:
1493 triangleId = getEdgeTriangleH_0yn(p.data(), localTriangleId);
1494 break;
1495 case EdgePosition::H_0y0_3D:
1496 triangleId = getEdgeTriangleH_0y0(p.data(), localTriangleId);
1497 break;
1498 case EdgePosition::H_0yN_3D:
1499 triangleId = getEdgeTriangleH_0yN(p.data(), localTriangleId);
1500 break;
1501 case EdgePosition::H_Nyn_3D:
1502 triangleId = getEdgeTriangleH_Nyn(p.data(), localTriangleId);
1503 break;
1504 case EdgePosition::H_Ny0_3D:
1505 triangleId = getEdgeTriangleH_Ny0(p.data(), localTriangleId);
1506 break;
1507 case EdgePosition::H_NyN_3D:
1508 triangleId = getEdgeTriangleH_NyN(p.data(), localTriangleId);
1509 break;
1510 case EdgePosition::P_nnz_3D:
1511 triangleId = getEdgeTriangleP_nnz(p.data(), localTriangleId);
1512 break;
1513 case EdgePosition::P_n0z_3D:
1514 triangleId = getEdgeTriangleP_n0z(p.data(), localTriangleId);
1515 break;
1516 case EdgePosition::P_nNz_3D:
1517 triangleId = getEdgeTriangleP_nNz(p.data(), localTriangleId);
1518 break;
1519 case EdgePosition::P_0nz_3D:
1520 triangleId = getEdgeTriangleP_0nz(p.data(), localTriangleId);
1521 break;
1522 case EdgePosition::P_00z_3D:
1523 triangleId = getEdgeTriangleP_00z(p.data(), localTriangleId);
1524 break;
1525 case EdgePosition::P_0Nz_3D:
1526 triangleId = getEdgeTriangleP_0Nz(p.data(), localTriangleId);
1527 break;
1528 case EdgePosition::P_Nnz_3D:
1529 triangleId = getEdgeTriangleP_Nnz(p.data(), localTriangleId);
1530 break;
1531 case EdgePosition::P_N0z_3D:
1532 triangleId = getEdgeTriangleP_N0z(p.data(), localTriangleId);
1533 break;
1534 case EdgePosition::P_NNz_3D:
1535 triangleId = getEdgeTriangleP_NNz(p.data(), localTriangleId);
1536 break;
1537 case EdgePosition::D1_xyn_3D:
1538 triangleId = getEdgeTriangleD1_xyn(p.data(), localTriangleId);
1539 break;
1540 case EdgePosition::D1_xy0_3D:
1541 triangleId = getEdgeTriangleD1_xy0(p.data(), localTriangleId);
1542 break;
1543 case EdgePosition::D1_xyN_3D:
1544 triangleId = getEdgeTriangleD1_xyN(p.data(), localTriangleId);
1545 break;
1546 case EdgePosition::D2_nyz_3D:
1547 triangleId = getEdgeTriangleD2_nyz(p.data(), localTriangleId);
1548 break;
1549 case EdgePosition::D2_0yz_3D:
1550 triangleId = getEdgeTriangleD2_0yz(p.data(), localTriangleId);
1551 break;
1552 case EdgePosition::D2_Nyz_3D:
1553 triangleId = getEdgeTriangleD2_Nyz(p.data(), localTriangleId);
1554 break;
1555 case EdgePosition::D3_xnz_3D:
1556 triangleId = getEdgeTriangleD3_xnz(p.data(), localTriangleId);
1557 break;
1558 case EdgePosition::D3_x0z_3D:
1559 triangleId = getEdgeTriangleD3_x0z(p.data(), localTriangleId);
1560 break;
1561 case EdgePosition::D3_xNz_3D:
1562 triangleId = getEdgeTriangleD3_xNz(p.data(), localTriangleId);
1563 break;
1564 case EdgePosition::D4_3D:
1565 triangleId = getEdgeTriangleD4_xyz(p.data(), localTriangleId);
1566 break;
1567
1568 case EdgePosition::L_xn_2D:
1569 triangleId = getEdgeTriangleL_xn(p.data(), localTriangleId);
1570 break;
1571 case EdgePosition::L_x0_2D:
1572 triangleId = getEdgeTriangleL_x0(p.data(), localTriangleId);
1573 break;
1574 case EdgePosition::L_xN_2D:
1575 triangleId = getEdgeTriangleL_xN(p.data(), localTriangleId);
1576 break;
1577 case EdgePosition::H_ny_2D:
1578 triangleId = getEdgeTriangleH_ny(p.data(), localTriangleId);
1579 break;
1580 case EdgePosition::H_0y_2D:
1581 triangleId = getEdgeTriangleH_0y(p.data(), localTriangleId);
1582 break;
1583 case EdgePosition::H_Ny_2D:
1584 triangleId = getEdgeTriangleH_Ny(p.data(), localTriangleId);
1585 break;
1586 case EdgePosition::D1_2D:
1587 triangleId = getEdgeTriangleD1_xy(p.data(), localTriangleId);
1588 break;
1589
1590 default: // 1D
1591 triangleId = -1;
1592 break;
1593 }
1594
1595 return 0;
1596}
1597
1598const vector<vector<SimplexId>> *
1600 if(edgeTriangleList_.empty()) {
1601 Timer t;
1602
1604 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1606 for(SimplexId j = 0; j < (SimplexId)edgeTriangleList_[i].size(); ++j)
1608 }
1609
1610 printMsg("Built " + to_string(edgeNumber_) + " edge triangles.", 1,
1611 t.getElapsedTime(), 1);
1612 }
1613
1614 return &edgeTriangleList_;
1615}
1616
1617SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdgeLinkNumber)(
1618 const SimplexId &edgeId) const {
1620}
1621
1622template <typename Derived>
1624 const SimplexId &edgeId, const int &localLinkId, SimplexId &linkId) const {
1625
1626#ifndef TTK_ENABLE_KAMIKAZE
1627 if(localLinkId < 0 or localLinkId >= getEdgeLinkNumber(edgeId))
1628 return -1;
1629#endif
1630
1631 const auto &p = this->underlying().getEdgeCoords(edgeId);
1632
1633 switch(this->underlying().getEdgePosition(edgeId)) {
1635 linkId = getEdgeLinkL(p.data(), localLinkId);
1636 break;
1638 linkId = getEdgeLinkH(p.data(), localLinkId);
1639 break;
1641 linkId = getEdgeLinkP(p.data(), localLinkId);
1642 break;
1644 linkId = getEdgeLinkD1(p.data(), localLinkId);
1645 break;
1647 linkId = getEdgeLinkD2(p.data(), localLinkId);
1648 break;
1650 linkId = getEdgeLinkD3(p.data(), localLinkId);
1651 break;
1652 case EdgePosition::D4_3D:
1653 linkId = getEdgeLinkD4(p.data(), localLinkId);
1654 break;
1655
1657 linkId = getEdgeLink2dL(p.data(), localLinkId);
1658 break;
1660 linkId = getEdgeLink2dH(p.data(), localLinkId);
1661 break;
1662 case EdgePosition::D1_2D:
1663 linkId = getEdgeLink2dD1(p.data(), localLinkId);
1664 break;
1665
1666 default: // 1D
1667 linkId = -1;
1668 break;
1669 }
1670
1671 return 0;
1672}
1673
1674const vector<vector<SimplexId>> *
1675 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdgeLinks)() {
1676
1677 if(edgeLinkList_.empty()) {
1678 Timer t;
1679
1680 edgeLinkList_.resize(edgeNumber_);
1681 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1682 edgeLinkList_[i].resize(getEdgeLinkNumber(i));
1683 for(SimplexId j = 0; j < (SimplexId)edgeLinkList_[i].size(); ++j)
1684 getEdgeLink(i, j, edgeLinkList_[i][j]);
1685 }
1686
1687 printMsg("Built " + to_string(edgeNumber_) + " edge links.", 1,
1688 t.getElapsedTime(), 1);
1689 }
1690
1691 return &edgeLinkList_;
1692}
1693
1694template <typename Derived>
1696 getEdgeStarNumber)(const SimplexId &edgeId) const {
1697
1698#ifndef TTK_ENABLE_KAMIKAZE
1699 if(edgeId < 0 or edgeId >= edgeNumber_)
1700 return -1;
1701#endif
1702
1703 switch(this->underlying().getEdgePosition(edgeId)) {
1704 case EdgePosition::L_xnn_3D:
1705 case EdgePosition::H_nyn_3D:
1706 case EdgePosition::P_nnz_3D:
1707 case EdgePosition::D4_3D:
1708 return 6;
1709 case EdgePosition::D1_xyn_3D:
1710 case EdgePosition::D2_nyz_3D:
1711 case EdgePosition::D3_xnz_3D:
1712 return 4;
1713 case EdgePosition::L_x0n_3D:
1714 case EdgePosition::L_xNn_3D:
1715 case EdgePosition::L_xn0_3D:
1716 case EdgePosition::L_xnN_3D:
1717 case EdgePosition::H_ny0_3D:
1718 case EdgePosition::H_nyN_3D:
1719 case EdgePosition::H_0yn_3D:
1720 case EdgePosition::H_Nyn_3D:
1721 case EdgePosition::P_n0z_3D:
1722 case EdgePosition::P_nNz_3D:
1723 case EdgePosition::P_0nz_3D:
1724 case EdgePosition::P_Nnz_3D:
1725 return 3;
1726 case EdgePosition::L_x00_3D:
1727 case EdgePosition::L_xNN_3D:
1728 case EdgePosition::H_0yN_3D:
1729 case EdgePosition::H_Ny0_3D:
1730 case EdgePosition::P_0Nz_3D:
1731 case EdgePosition::P_N0z_3D:
1732 case EdgePosition::D1_xy0_3D:
1733 case EdgePosition::D1_xyN_3D:
1734 case EdgePosition::D2_0yz_3D:
1735 case EdgePosition::D2_Nyz_3D:
1736 case EdgePosition::D3_x0z_3D:
1737 case EdgePosition::D3_xNz_3D:
1738 case EdgePosition::L_xn_2D:
1739 case EdgePosition::H_ny_2D:
1740 case EdgePosition::D1_2D:
1741 return 2;
1742 case EdgePosition::L_xN0_3D:
1743 case EdgePosition::L_x0N_3D:
1744 case EdgePosition::H_0y0_3D:
1745 case EdgePosition::H_NyN_3D:
1746 case EdgePosition::P_00z_3D:
1747 case EdgePosition::P_NNz_3D:
1748 case EdgePosition::L_x0_2D:
1749 case EdgePosition::L_xN_2D:
1750 case EdgePosition::H_0y_2D:
1751 case EdgePosition::H_Ny_2D:
1752 return 1;
1753
1754 default: // 1D
1755 break;
1756 }
1757
1758 return 0;
1759}
1760
1761template <typename Derived>
1763 const SimplexId &edgeId, const int &localStarId, SimplexId &starId) const {
1764
1765#ifndef TTK_ENABLE_KAMIKAZE
1766 if(localStarId < 0 or localStarId >= getEdgeStarNumber(edgeId))
1767 return -1;
1768#endif
1769
1770 const auto &p = this->underlying().getEdgeCoords(edgeId);
1771
1772 switch(this->underlying().getEdgePosition(edgeId)) {
1774 starId = getEdgeStarL(p.data(), localStarId);
1775 break;
1777 starId = getEdgeStarH(p.data(), localStarId);
1778 break;
1780 starId = getEdgeStarP(p.data(), localStarId);
1781 break;
1783 starId = getEdgeStarD1(p.data(), localStarId);
1784 break;
1786 starId = getEdgeStarD2(p.data(), localStarId);
1787 break;
1789 starId = getEdgeStarD3(p.data(), localStarId);
1790 break;
1791 case EdgePosition::D4_3D:
1792 starId
1793 = p[2] * tetshift_[1] + p[1] * tetshift_[0] + p[0] * 6 + localStarId;
1794 break;
1795
1797 starId = getEdgeStar2dL(p.data(), localStarId);
1798 break;
1800 starId = getEdgeStar2dH(p.data(), localStarId);
1801 break;
1802 case EdgePosition::D1_2D:
1803 starId = p[0] * 2 + p[1] * tshift_[0] + localStarId;
1804 break;
1805
1806 default: // 1D
1807 starId = -1;
1808 break;
1809 }
1810
1811 return 0;
1812}
1813
1814const vector<vector<SimplexId>> *
1815 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getEdgeStars)() {
1816
1817 if(edgeStarList_.empty()) {
1818 Timer t;
1819
1820 edgeStarList_.resize(edgeNumber_);
1821 for(SimplexId i = 0; i < edgeNumber_; ++i) {
1822 edgeStarList_[i].resize(getEdgeStarNumber(i));
1823 for(SimplexId j = 0; j < (SimplexId)edgeStarList_[i].size(); ++j)
1824 getEdgeStar(i, j, edgeStarList_[i][j]);
1825 }
1826
1827 printMsg("Built " + to_string(edgeNumber_) + " edge stars.", 1,
1828 t.getElapsedTime(), 1);
1829 }
1830
1831 return &edgeStarList_;
1832}
1833
1834template <typename Derived>
1836 const SimplexId &triangleId,
1837 const int &localVertexId,
1838 SimplexId &vertexId) const {
1839#ifndef TTK_ENABLE_KAMIKAZE
1840 if(triangleId < 0 or triangleId >= triangleNumber_)
1841 return -1;
1842 if(localVertexId < 0 or localVertexId >= 3)
1843 return -2;
1844#endif
1845
1846 // e--------f
1847 // /| /|
1848 // / | / |
1849 // a--g-----b--h
1850 // | / | /
1851 // |/ |/
1852 // c--------d
1853 //
1854 // Classement des "Triangles" et dans cet ordre:
1855 // F: face (type abc/bcd)
1856 // C: cote (type abe/bef)
1857 // H: haut (type acg/aeg)
1858 // D1: diagonale1 (type bdg/beg)
1859 // D2: diagonale2 (type abg/bgh)
1860 // D3: diagonale3 (type bcg/bfg)
1861
1862 const auto &p = this->underlying().getTriangleCoords(triangleId);
1863 vertexId = -1;
1864
1865 switch(this->underlying().getTrianglePosition(triangleId)) {
1866 case TrianglePosition::F_3D:
1867 vertexId = getTriangleVertexF(p.data(), localVertexId);
1868 break;
1869 case TrianglePosition::H_3D:
1870 vertexId = getTriangleVertexH(p.data(), localVertexId);
1871 break;
1872 case TrianglePosition::C_3D:
1873 vertexId = getTriangleVertexC(p.data(), localVertexId);
1874 break;
1875 case TrianglePosition::D1_3D:
1876 vertexId = getTriangleVertexD1(p.data(), localVertexId);
1877 break;
1878 case TrianglePosition::D2_3D:
1879 vertexId = getTriangleVertexD2(p.data(), localVertexId);
1880 break;
1881 case TrianglePosition::D3_3D:
1882 vertexId = getTriangleVertexD3(p.data(), localVertexId);
1883 break;
1884 case TrianglePosition::TOP_2D:
1885 switch(localVertexId) {
1886 break;
1887 case 0:
1888 vertexId = p[0] / 2 + p[1] * vshift_[0];
1889 break;
1890 case 1:
1891 vertexId = p[0] / 2 + p[1] * vshift_[0] + 1;
1892 break;
1893 case 2:
1894 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0];
1895 break;
1896 }
1897 break;
1898 case TrianglePosition::BOTTOM_2D:
1899 switch(localVertexId) {
1900 break;
1901 case 0:
1902 vertexId = p[0] / 2 + p[1] * vshift_[0] + 1;
1903 break;
1904 case 1:
1905 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0] + 1;
1906 break;
1907 case 2:
1908 vertexId = p[0] / 2 + p[1] * vshift_[0] + vshift_[0];
1909 break;
1910 }
1911 }
1912
1913 return 0;
1914}
1915
1916template <typename Derived>
1918 const SimplexId &triangleId,
1919 const int &localEdgeId,
1920 SimplexId &edgeId) const {
1921#ifndef TTK_ENABLE_KAMIKAZE
1922 if(triangleId < 0 or triangleId >= triangleNumber_)
1923 return -1;
1924 if(localEdgeId < 0 or localEdgeId >= 3)
1925 return -2;
1926#endif
1927
1928 const auto &p = this->underlying().getTriangleCoords(triangleId);
1929 const auto par = triangleId % 2;
1930 edgeId = -1;
1931
1932 switch(this->underlying().getTrianglePosition(triangleId)) {
1933 case TrianglePosition::F_3D:
1934 edgeId = (par == 1) ? getTriangleEdgeF_1(p.data(), localEdgeId)
1935 : getTriangleEdgeF_0(p.data(), localEdgeId);
1936 break;
1937 case TrianglePosition::H_3D:
1938 edgeId = (par == 1) ? getTriangleEdgeH_1(p.data(), localEdgeId)
1939 : getTriangleEdgeH_0(p.data(), localEdgeId);
1940 break;
1941 case TrianglePosition::C_3D:
1942 edgeId = (par == 1) ? getTriangleEdgeC_1(p.data(), localEdgeId)
1943 : getTriangleEdgeC_0(p.data(), localEdgeId);
1944 break;
1945 case TrianglePosition::D1_3D:
1946 edgeId = (par == 1) ? getTriangleEdgeD1_1(p.data(), localEdgeId)
1947 : getTriangleEdgeD1_0(p.data(), localEdgeId);
1948 break;
1949 case TrianglePosition::D2_3D:
1950 edgeId = (par == 1) ? getTriangleEdgeD2_1(p.data(), localEdgeId)
1951 : getTriangleEdgeD2_0(p.data(), localEdgeId);
1952 break;
1953 case TrianglePosition::D3_3D:
1954 edgeId = (par == 1) ? getTriangleEdgeD3_1(p.data(), localEdgeId)
1955 : getTriangleEdgeD3_0(p.data(), localEdgeId);
1956 break;
1957 case TrianglePosition::TOP_2D:
1958 switch(localEdgeId) {
1959 break;
1960 case 0:
1961 edgeId = p[0] / 2 + p[1] * eshift_[0];
1962 break;
1963 case 1:
1964 edgeId = esetshift_[0] + p[0] / 2 + p[1] * eshift_[2];
1965 break;
1966 case 2:
1967 edgeId = esetshift_[1] + p[0] / 2 + p[1] * eshift_[4];
1968 break;
1969 }
1970 break;
1971 case TrianglePosition::BOTTOM_2D:
1972 switch(localEdgeId) {
1973 break;
1974 case 0:
1975 edgeId = p[0] / 2 + (p[1] + 1) * eshift_[0];
1976 break;
1977 case 1:
1978 edgeId = esetshift_[0] + (p[0] + 1) / 2 + p[1] * eshift_[2];
1979 break;
1980 case 2:
1981 edgeId = esetshift_[1] + p[0] / 2 + p[1] * eshift_[4];
1982 break;
1983 }
1984 }
1985
1986 return 0;
1987}
1988
1990 vector<vector<SimplexId>> &edges) const {
1991 edges.resize(triangleNumber_);
1992 for(SimplexId i = 0; i < triangleNumber_; ++i) {
1993 edges[i].resize(3);
1994 for(int j = 0; j < 3; ++j)
1995 getTriangleEdgeInternal(i, j, edges[i][j]);
1996 }
1997 return 0;
1998}
1999
2000const vector<vector<SimplexId>> *
2002 if(triangleEdgeVector_.empty()) {
2003 Timer t;
2004
2006
2007 printMsg("Built " + to_string(triangleNumber_) + " triangle edges.", 1,
2008 t.getElapsedTime(), 1);
2009 }
2010
2011 return &triangleEdgeVector_;
2012}
2013
2014const vector<std::array<SimplexId, 3>> *
2015 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getTriangles)() {
2016
2017 if(triangleList_.empty()) {
2018 Timer t;
2019
2020 triangleList_.resize(triangleNumber_);
2021 for(SimplexId i = 0; i < triangleNumber_; ++i) {
2022 for(int j = 0; j < 3; ++j)
2023 getTriangleVertexInternal(i, j, triangleList_[i][j]);
2024 }
2025
2026 printMsg("Built " + to_string(triangleNumber_) + " triangles.", 1,
2027 t.getElapsedTime(), 1);
2028 }
2029
2030 return &triangleList_;
2031}
2032
2033template <typename Derived>
2035 getTriangleLink)(const SimplexId &triangleId,
2036 const int &localLinkId,
2037 SimplexId &linkId) const {
2038
2039#ifndef TTK_ENABLE_KAMIKAZE
2040 if(localLinkId < 0 or localLinkId >= getTriangleLinkNumber(triangleId))
2041 return -1;
2042#endif
2043
2044 const auto &p = this->underlying().getTriangleCoords(triangleId);
2045
2046 switch(this->underlying().getTrianglePosition(triangleId)) {
2047 case TrianglePosition::F_3D:
2048 linkId = getTriangleLinkF(p.data(), localLinkId);
2049 break;
2050 case TrianglePosition::H_3D:
2051 linkId = getTriangleLinkH(p.data(), localLinkId);
2052 break;
2053 case TrianglePosition::C_3D:
2054 linkId = getTriangleLinkC(p.data(), localLinkId);
2055 break;
2056 case TrianglePosition::D1_3D:
2057 linkId = getTriangleLinkD1(p.data(), localLinkId);
2058 break;
2059 case TrianglePosition::D2_3D:
2060 linkId = getTriangleLinkD2(p.data(), localLinkId);
2061 break;
2062 case TrianglePosition::D3_3D:
2063 linkId = getTriangleLinkD3(p.data(), localLinkId);
2064 break;
2065 default: // 2D
2066 linkId = -1;
2067 break;
2068 }
2069
2070 return 0;
2071}
2072
2073SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
2074 getTriangleLinkNumber)(const SimplexId &triangleId) const {
2076}
2077
2078const vector<vector<SimplexId>> *
2079 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getTriangleLinks)() {
2080 if(triangleLinkList_.empty()) {
2081 Timer t;
2082
2083 triangleLinkList_.resize(triangleNumber_);
2084 for(SimplexId i = 0; i < triangleNumber_; ++i) {
2085 triangleLinkList_[i].resize(getTriangleLinkNumber(i));
2086 for(SimplexId j = 0; j < (SimplexId)triangleLinkList_[i].size(); ++j)
2087 getTriangleLink(i, j, triangleLinkList_[i][j]);
2088 }
2089
2090 printMsg("Built " + to_string(triangleNumber_) + " triangle links.", 1,
2091 t.getElapsedTime(), 1);
2092 }
2093 return &triangleLinkList_;
2094}
2095
2096template <typename Derived>
2098 getTriangleStarNumber)(const SimplexId &triangleId) const {
2099
2100#ifndef TTK_ENABLE_KAMIKAZE
2101 if(triangleId < 0 or triangleId >= triangleNumber_)
2102 return -1;
2103#endif
2104
2105 const auto &p = this->underlying().getTriangleCoords(triangleId);
2106
2107 switch(this->underlying().getTrianglePosition(triangleId)) {
2108 case TrianglePosition::F_3D:
2109 return (p[2] > 0 and p[2] < nbvoxels_[2]) ? 2 : 1;
2110 case TrianglePosition::H_3D:
2111 return (p[1] > 0 and p[1] < nbvoxels_[1]) ? 2 : 1;
2112 case TrianglePosition::C_3D:
2113 return (p[0] < 2 or p[0] >= (dimensions_[0] * 2 - 2)) ? 1 : 2;
2114
2115 case TrianglePosition::D1_3D:
2116 case TrianglePosition::D2_3D:
2117 case TrianglePosition::D3_3D:
2118 return 2;
2119 default: // 2D
2120 break;
2121 }
2122 return 0;
2123}
2124
2125template <typename Derived>
2127 getTriangleStar)(const SimplexId &triangleId,
2128 const int &localStarId,
2129 SimplexId &starId) const {
2130
2131#ifndef TTK_ENABLE_KAMIKAZE
2132 if(localStarId < 0 or localStarId >= getTriangleStarNumber(triangleId))
2133 return -1;
2134#endif
2135
2136 const auto &p = this->underlying().getTriangleCoords(triangleId);
2137
2138 switch(this->underlying().getTrianglePosition(triangleId)) {
2139 case TrianglePosition::F_3D:
2140 starId = getTriangleStarF(p.data(), localStarId);
2141 break;
2142 case TrianglePosition::H_3D:
2143 starId = getTriangleStarH(p.data(), localStarId);
2144 break;
2145 case TrianglePosition::C_3D:
2146 starId = getTriangleStarC(p.data(), localStarId);
2147 break;
2148 case TrianglePosition::D1_3D:
2149 starId = getTriangleStarD1(p.data(), localStarId);
2150 break;
2151 case TrianglePosition::D2_3D:
2152 starId = getTriangleStarD2(p.data(), localStarId);
2153 break;
2154 case TrianglePosition::D3_3D:
2155 starId = getTriangleStarD3(p.data(), localStarId);
2156 break;
2157 default: // 2D
2158 starId = -1;
2159 break;
2160 }
2161
2162 return 0;
2163}
2164
2165const vector<vector<SimplexId>> *
2166 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getTriangleStars)() {
2167
2168 if(triangleStarList_.empty()) {
2169 Timer t;
2170
2171 triangleStarList_.resize(triangleNumber_);
2172 for(SimplexId i = 0; i < triangleNumber_; ++i) {
2173 triangleStarList_[i].resize(getTriangleStarNumber(i));
2174 for(SimplexId j = 0; j < (SimplexId)triangleStarList_[i].size(); ++j)
2175 getTriangleStar(i, j, triangleStarList_[i][j]);
2176 }
2177
2178 printMsg("Built " + to_string(triangleNumber_) + " triangle stars.", 1,
2179 t.getElapsedTime(), 1);
2180 }
2181 return &triangleStarList_;
2182}
2183
2184template <typename Derived>
2186 const SimplexId &triangleId) const {
2187#ifndef TTK_ENABLE_KAMIKAZE
2188 if(triangleId < 0 or triangleId >= triangleNumber_)
2189 return -1;
2190#endif
2191
2192 if(dimensionality_ == 2) {
2193 const auto &p = this->underlying().getTriangleCoords(triangleId);
2194 const SimplexId id = triangleId % 2;
2195
2196 if(id) {
2197 if(p[0] / 2 == nbvoxels_[Di_] - 1 and p[1] == nbvoxels_[Dj_] - 1)
2198 return 1;
2199 else if(p[0] / 2 == nbvoxels_[Di_] - 1 or p[1] == nbvoxels_[Dj_] - 1)
2200 return 2;
2201 else
2202 return 3;
2203 } else {
2204 if(p[0] == 0 and p[1] == 0)
2205 return 1;
2206 else if(p[0] == 0 or p[1] == 0)
2207 return 2;
2208 else
2209 return 3;
2210 }
2211 }
2212
2213 return 0;
2214}
2215
2216template <typename Derived>
2218 const SimplexId &triangleId,
2219 const int &localNeighborId,
2220 SimplexId &neighborId) const {
2221#ifndef TTK_ENABLE_KAMIKAZE
2222 if(localNeighborId < 0
2223 or localNeighborId >= getTriangleNeighborNumber(triangleId))
2224 return -1;
2225#endif
2226
2227 neighborId = -1;
2228
2229 if(dimensionality_ == 2) {
2230 const auto &p = this->underlying().getTriangleCoords(triangleId);
2231 const SimplexId id = triangleId % 2;
2232
2233 if(id) {
2234 if(p[0] / 2 == nbvoxels_[Di_] - 1 and p[1] == nbvoxels_[Dj_] - 1)
2235 neighborId = triangleId - 1;
2236 else if(p[0] / 2 == nbvoxels_[Di_] - 1) {
2237 switch(localNeighborId) {
2238 case 0:
2239 neighborId = triangleId - 1;
2240 break;
2241 case 1:
2242 neighborId = triangleId + tshift_[0] - 1;
2243 break;
2244 }
2245 } else if(p[1] == nbvoxels_[Dj_] - 1) {
2246 switch(localNeighborId) {
2247 case 0:
2248 neighborId = triangleId - 1;
2249 break;
2250 case 1:
2251 neighborId = triangleId + 1;
2252 break;
2253 }
2254 } else {
2255 switch(localNeighborId) {
2256 case 0:
2257 neighborId = triangleId - 1;
2258 break;
2259 case 1:
2260 neighborId = triangleId + 1;
2261 break;
2262 case 2:
2263 neighborId = triangleId + tshift_[0] - 1;
2264 break;
2265 }
2266 }
2267 } else {
2268 if(p[0] == 0 and p[1] == 0)
2269 neighborId = triangleId + 1;
2270 else if(p[0] == 0) {
2271 switch(localNeighborId) {
2272 case 0:
2273 neighborId = triangleId + 1;
2274 break;
2275 case 1:
2276 neighborId = triangleId - tshift_[0] + 1;
2277 break;
2278 }
2279 } else if(p[1] == 0) {
2280 switch(localNeighborId) {
2281 case 0:
2282 neighborId = triangleId + 1;
2283 break;
2284 case 1:
2285 neighborId = triangleId - 1;
2286 break;
2287 }
2288 } else {
2289 switch(localNeighborId) {
2290 case 0:
2291 neighborId = triangleId + 1;
2292 break;
2293 case 1:
2294 neighborId = triangleId - 1;
2295 break;
2296 case 2:
2297 neighborId = triangleId - tshift_[0] + 1;
2298 break;
2299 }
2300 }
2301 }
2302 }
2303
2304 return 0;
2305}
2306
2308 vector<vector<SimplexId>> &neighbors) {
2309 neighbors.resize(triangleNumber_);
2310 for(SimplexId i = 0; i < triangleNumber_; ++i) {
2311 neighbors[i].resize(getTriangleNeighborNumber(i));
2312 for(SimplexId j = 0; j < (SimplexId)neighbors[i].size(); ++j)
2313 getTriangleNeighbor(i, j, neighbors[i][j]);
2314 }
2315 return 0;
2316}
2317
2318template <typename Derived>
2320 const SimplexId &tetId, const int &localVertexId, SimplexId &vertexId) const {
2321#ifndef TTK_ENABLE_KAMIKAZE
2322 if(tetId < 0 or tetId >= tetrahedronNumber_)
2323 return -1;
2324 if(localVertexId < 0 or localVertexId >= 4)
2325 return -2;
2326#endif
2327
2328 vertexId = -1;
2329
2330 if(dimensionality_ == 3) {
2331 const SimplexId id = tetId % 6;
2332 const auto &c = this->underlying().getTetrahedronCoords(tetId);
2333 const auto p{c.data()};
2334
2335 switch(id) {
2336 case 0:
2337 vertexId = getTetrahedronVertexABCG(p, localVertexId);
2338 break;
2339 case 1:
2340 vertexId = getTetrahedronVertexBCDG(p, localVertexId);
2341 break;
2342 case 2:
2343 vertexId = getTetrahedronVertexABEG(p, localVertexId);
2344 break;
2345 case 3:
2346 vertexId = getTetrahedronVertexBEFG(p, localVertexId);
2347 break;
2348 case 4:
2349 vertexId = getTetrahedronVertexBFGH(p, localVertexId);
2350 break;
2351 case 5:
2352 vertexId = getTetrahedronVertexBDGH(p, localVertexId);
2353 break;
2354 }
2355 }
2356 return 0;
2357}
2358
2359template <typename Derived>
2361 const SimplexId &tetId, const int &localEdgeId, SimplexId &edgeId) const {
2362#ifndef TTK_ENABLE_KAMIKAZE
2363 if(tetId < 0 or tetId >= tetrahedronNumber_)
2364 return -1;
2365 if(localEdgeId < 0 or localEdgeId >= 6)
2366 return -2;
2367#endif
2368
2369 edgeId = -1;
2370
2371 if(dimensionality_ == 3) {
2372 const SimplexId id = tetId % 6;
2373 const auto &c = this->underlying().getTetrahedronCoords(tetId);
2374 const auto p{c.data()};
2375
2376 switch(id) {
2377 case 0:
2378 edgeId = getTetrahedronEdgeABCG(p, localEdgeId);
2379 break;
2380 case 1:
2381 edgeId = getTetrahedronEdgeBCDG(p, localEdgeId);
2382 break;
2383 case 2:
2384 edgeId = getTetrahedronEdgeABEG(p, localEdgeId);
2385 break;
2386 case 3:
2387 edgeId = getTetrahedronEdgeBEFG(p, localEdgeId);
2388 break;
2389 case 4:
2390 edgeId = getTetrahedronEdgeBFGH(p, localEdgeId);
2391 break;
2392 case 5:
2393 edgeId = getTetrahedronEdgeBDGH(p, localEdgeId);
2394 break;
2395 }
2396 }
2397
2398 return 0;
2399}
2400
2402 vector<vector<SimplexId>> &edges) const {
2403 edges.resize(tetrahedronNumber_);
2404 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
2405 edges[i].resize(6);
2406 for(int j = 0; j < 6; ++j)
2407 getTetrahedronEdge(i, j, edges[i][j]);
2408 }
2409
2410 return 0;
2411}
2412
2413template <typename Derived>
2415 const SimplexId &tetId,
2416 const int &localTriangleId,
2417 SimplexId &triangleId) const {
2418#ifndef TTK_ENABLE_KAMIKAZE
2419 if(tetId < 0 or tetId >= tetrahedronNumber_)
2420 return -1;
2421 if(localTriangleId < 0 or localTriangleId >= 4)
2422 return -2;
2423#endif
2424
2425 triangleId = -1;
2426
2427 if(dimensionality_ == 3) {
2428 const SimplexId id = tetId % 6;
2429 const auto &c = this->underlying().getTetrahedronCoords(tetId);
2430 const auto p{c.data()};
2431
2432 switch(id) {
2433 case 0:
2434 triangleId = getTetrahedronTriangleABCG(p, localTriangleId);
2435 break;
2436 case 1:
2437 triangleId = getTetrahedronTriangleBCDG(p, localTriangleId);
2438 break;
2439 case 2:
2440 triangleId = getTetrahedronTriangleABEG(p, localTriangleId);
2441 break;
2442 case 3:
2443 triangleId = getTetrahedronTriangleBEFG(p, localTriangleId);
2444 break;
2445 case 4:
2446 triangleId = getTetrahedronTriangleBFGH(p, localTriangleId);
2447 break;
2448 case 5:
2449 triangleId = getTetrahedronTriangleBDGH(p, localTriangleId);
2450 break;
2451 }
2452 }
2453
2454 return 0;
2455}
2456
2458 vector<vector<SimplexId>> &triangles) const {
2459 triangles.resize(tetrahedronNumber_);
2460 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
2461 triangles[i].resize(4);
2462 for(int j = 0; j < 4; ++j)
2463 getTetrahedronTriangle(i, j, triangles[i][j]);
2464 }
2465
2466 return 0;
2467}
2468
2469template <typename Derived>
2471 const SimplexId &tetId) const {
2472#ifndef TTK_ENABLE_KAMIKAZE
2473 if(tetId < 0 or tetId >= tetrahedronNumber_)
2474 return -1;
2475#endif
2476
2477 if(dimensionality_ == 3) {
2478 const SimplexId id = tetId % 6;
2479 const auto &c = this->underlying().getTetrahedronCoords(tetId);
2480 const auto p{c.data()};
2481
2482 switch(id) {
2483 case 0: // ABCG
2484 if(p[0] == 0 and p[2] == 0)
2485 return 2;
2486 else if(p[0] == 0 or p[2] == 0)
2487 return 3;
2488 else
2489 return 4;
2490 break;
2491 case 1: // BCDG
2492 if(p[1] == nbvoxels_[1] - 1 and p[2] == 0)
2493 return 2;
2494 else if(p[1] == nbvoxels_[1] - 1 or p[2] == 0)
2495 return 3;
2496 else
2497 return 4;
2498 break;
2499 case 2: // ABEG
2500 if(p[0] == 0 and p[1] == 0)
2501 return 2;
2502 else if(p[0] == 0 or p[1] == 0)
2503 return 3;
2504 else
2505 return 4;
2506 break;
2507 case 3: // BEFG
2508 if(p[1] == 0 and p[2] == nbvoxels_[2] - 1)
2509 return 2;
2510 else if(p[1] == 0 or p[2] == nbvoxels_[2] - 1)
2511 return 3;
2512 else
2513 return 4;
2514 break;
2515 case 4: // BFGH
2516 if(p[0] == nbvoxels_[0] - 1 and p[2] == nbvoxels_[2] - 1)
2517 return 2;
2518 else if(p[0] == nbvoxels_[0] - 1 or p[2] == nbvoxels_[2] - 1)
2519 return 3;
2520 else
2521 return 4;
2522 break;
2523 case 5: // BDGH
2524 if(p[0] == nbvoxels_[0] - 1 and p[1] == nbvoxels_[1] - 1)
2525 return 2;
2526 else if(p[0] == nbvoxels_[0] - 1 or p[1] == nbvoxels_[1] - 1)
2527 return 3;
2528 else
2529 return 4;
2530 break;
2531 }
2532 }
2533
2534 return 0;
2535}
2536
2537template <typename Derived>
2539 const SimplexId &tetId,
2540 const int &localNeighborId,
2541 SimplexId &neighborId) const {
2542#ifndef TTK_ENABLE_KAMIKAZE
2543 if(localNeighborId < 0
2544 or localNeighborId >= getTetrahedronNeighborNumber(tetId))
2545 return -1;
2546#endif
2547
2548 neighborId = -1;
2549
2550 if(dimensionality_ == 3) {
2551 const SimplexId id = tetId % 6;
2552 const auto &c = this->underlying().getTetrahedronCoords(tetId);
2553 const auto p{c.data()};
2554
2555 switch(id) {
2556 case 0:
2557 neighborId = getTetrahedronNeighborABCG(tetId, p, localNeighborId);
2558 break;
2559 case 1:
2560 neighborId = getTetrahedronNeighborBCDG(tetId, p, localNeighborId);
2561 break;
2562 case 2:
2563 neighborId = getTetrahedronNeighborABEG(tetId, p, localNeighborId);
2564 break;
2565 case 3:
2566 neighborId = getTetrahedronNeighborBEFG(tetId, p, localNeighborId);
2567 break;
2568 case 4:
2569 neighborId = getTetrahedronNeighborBFGH(tetId, p, localNeighborId);
2570 break;
2571 case 5:
2572 neighborId = getTetrahedronNeighborBDGH(tetId, p, localNeighborId);
2573 break;
2574 }
2575 }
2576
2577 return 0;
2578}
2579
2581 vector<vector<SimplexId>> &neighbors) {
2582 neighbors.resize(tetrahedronNumber_);
2583 for(SimplexId i = 0; i < tetrahedronNumber_; ++i) {
2584 neighbors[i].resize(getTetrahedronNeighborNumber(i));
2585 for(SimplexId j = 0; j < (SimplexId)neighbors[i].size(); ++j)
2586 getTetrahedronNeighbor(i, j, neighbors[i][j]);
2587 }
2588
2589 return 0;
2590}
2591
2592SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
2593 getCellVertexNumber)(const SimplexId & /*cellId*/) const {
2594 return dimensionality_ + 1;
2595}
2596
2597int ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getCellVertex)(
2598 const SimplexId &cellId,
2599 const int &localVertexId,
2600 SimplexId &vertexId) const {
2601
2602 if(dimensionality_ == 3)
2603 getTetrahedronVertex(cellId, localVertexId, vertexId);
2604 else if(dimensionality_ == 2)
2605 getTriangleVertexInternal(cellId, localVertexId, vertexId);
2606 else if(dimensionality_ == 1)
2607 getEdgeVertexInternal(cellId, localVertexId, vertexId);
2608
2609 return 0;
2610}
2611
2613 const SimplexId & /*cellId*/) const {
2614 if(dimensionality_ == 3)
2615 return 6;
2616 else if(dimensionality_ == 2)
2617 return 3;
2618
2619 return 0;
2620}
2621
2623 const int &localEdgeId,
2624 SimplexId &edgeId) const {
2625 if(dimensionality_ == 3)
2626 getTetrahedronEdge(cellId, localEdgeId, edgeId);
2627 else if(dimensionality_ == 2)
2628 getTriangleEdgeInternal(cellId, localEdgeId, edgeId);
2629 else if(dimensionality_ == 1)
2630 getCellNeighbor(cellId, localEdgeId, edgeId);
2631
2632 return 0;
2633}
2634
2635const vector<vector<SimplexId>> *ImplicitTriangulation::getCellEdgesInternal() {
2636 if(cellEdgeVector_.empty()) {
2637 Timer t;
2638
2639 if(dimensionality_ == 3)
2641 else if(dimensionality_ == 2)
2643
2644 printMsg("Built " + to_string(cellNumber_) + " cell edges.", 1,
2645 t.getElapsedTime(), 1);
2646 }
2647
2648 return &cellEdgeVector_;
2649}
2650
2652 const SimplexId &cellId,
2653 const int &localTriangleId,
2654 SimplexId &triangleId) const {
2655 if(dimensionality_ == 3)
2656 getTetrahedronTriangle(cellId, localTriangleId, triangleId);
2657
2658 return 0;
2659}
2660
2661const vector<vector<SimplexId>> *
2663 if(cellTriangleVector_.empty()) {
2664 Timer t;
2665
2666 if(dimensionality_ == 3)
2668
2669 printMsg("Built " + to_string(cellNumber_) + " cell triangles.", 1,
2670 t.getElapsedTime(), 1);
2671 }
2672
2673 return &cellTriangleVector_;
2674}
2675
2676SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(
2677 getCellNeighborNumber)(const SimplexId &cellId) const {
2678 if(dimensionality_ == 3)
2679 return getTetrahedronNeighborNumber(cellId);
2680 else if(dimensionality_ == 2)
2681 return getTriangleNeighborNumber(cellId);
2682 else if(dimensionality_ == 1) {
2683 printErr("getCellNeighborNumber() not implemented in 1D! (TODO)");
2684 return -1;
2685 }
2686
2687 return 0;
2688}
2689
2690int ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getCellNeighbor)(
2691 const SimplexId &cellId,
2692 const int &localNeighborId,
2693 SimplexId &neighborId) const {
2694 if(dimensionality_ == 3)
2695 getTetrahedronNeighbor(cellId, localNeighborId, neighborId);
2696 else if(dimensionality_ == 2)
2697 getTriangleNeighbor(cellId, localNeighborId, neighborId);
2698 else if(dimensionality_ == 1) {
2699 printErr("getCellNeighbor() not implemented in 1D! (TODO)");
2700 return -1;
2701 }
2702
2703 return 0;
2704}
2705
2706const vector<vector<SimplexId>> *
2707 ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL(getCellNeighbors)() {
2708 if(cellNeighborList_.empty()) {
2709 Timer t;
2710
2711 if(dimensionality_ == 3)
2712 getTetrahedronNeighbors(cellNeighborList_);
2713 else if(dimensionality_ == 2)
2714 getTriangleNeighbors(cellNeighborList_);
2715 else if(dimensionality_ == 1) {
2716 printErr("getCellNeighbors() not implemented in 1D! (TODO)");
2717 return nullptr;
2718 }
2719
2720 printMsg("Built " + to_string(cellNumber_) + " cell neighbors.", 1,
2721 t.getElapsedTime(), 1);
2722 }
2723
2724 return &cellNeighborList_;
2725}
2726
2728 // V(abcdefgh)=V(g)+V(d)::{g,h}+V(h)::{g}+V(b)::{c,d,g,h}
2729 this->vertexNeighborABCDEFGH_ = {
2730 -vshift_[0] - vshift_[1], // a
2731 1 - vshift_[0] - vshift_[1], // b
2732 -vshift_[1], // c
2733 1 - vshift_[1], // d
2734 -vshift_[0], // e
2735 1 - vshift_[0], // f
2736 1, // h
2737 -1 + vshift_[1], // V(d)::{g}
2738 vshift_[1], // V(d)::{h}
2739 -1, // V(h)::{g}
2740 -1 + vshift_[0], // V(b)::{c}
2741 vshift_[0], // V(b)::{d}
2742 -1 + vshift_[0] + vshift_[1], // V(b)::{g}
2743 vshift_[0] + vshift_[1] // V(b)::{h}
2744 };
2745
2746 // V(abdc)=V(b)+V(d)::{b}+V(c)::{b}+V(a)::{b}
2747 this->vertexNeighborABCD_ = {
2748 -1, // a
2749 -1 + vshift_[0], // c
2750 vshift_[0], // d
2751 -1 + vshift_[1], // e
2752 vshift_[1], // f
2753 -1 + vshift_[0] + vshift_[1], // g
2754 vshift_[0] + vshift_[1], // h
2755 -vshift_[0], // V(d)::{b}
2756 1 - vshift_[0], // V(c)::{b}
2757 1, // V(a)::{b}
2758 };
2759 // V(efhg)=V(g)+V(h)::{g}+V(f)::{g,h}
2760 this->vertexNeighborEFGH_ = {
2761 -vshift_[0] - vshift_[1], // a
2762 1 - vshift_[0] - vshift_[1], // b
2763 -vshift_[1], // c
2764 1 - vshift_[1], // d
2765 -vshift_[0], // e
2766 1 - vshift_[0], // f
2767 1, // h
2768 -1, // V(h)::{g}
2769 -1 + vshift_[0], // V(f)::{g}
2770 vshift_[0], // V(f)::{h}
2771 };
2772 // V(aefb)=V(b)+V(a)::{b}+V(e)::{b}+V(f)::{b}
2773 this->vertexNeighborAEFB_ = {
2774 -1, // a
2775 -1 + vshift_[0], // c
2776 vshift_[0], // d
2777 -1 + vshift_[1], // e
2778 vshift_[1], // f
2779 -1 + vshift_[0] + vshift_[1], // g
2780 vshift_[0] + vshift_[1], // h
2781 1, // V(a)::{b}
2782 1 - vshift_[1], // V(e)::{b}
2783 -vshift_[1], // V(f)::{b}
2784 };
2785 // V(ghdc)=V(g)+V(h)::{g}+V(d)::{g,h}
2786 this->vertexNeighborGHDC_ = {
2787 -vshift_[0] - vshift_[1], // a
2788 1 - vshift_[0] - vshift_[1], // b
2789 -vshift_[1], // c
2790 1 - vshift_[1], // d
2791 -vshift_[0], // e
2792 1 - vshift_[0], // f
2793 1, // h
2794 -1, // V(h)::{g}
2795 -1 + vshift_[1], // V(d)::{g}
2796 vshift_[1] // V(d)::{h}
2797 };
2798 // V(aegc)=V(g)+V(a)::{c,g}+V(c)::{g}
2799 this->vertexNeighborAEGC_ = {
2800 -vshift_[0] - vshift_[1], // a
2801 1 - vshift_[0] - vshift_[1], // b
2802 -vshift_[1], // c
2803 1 - vshift_[1], // d
2804 -vshift_[0], // e
2805 1 - vshift_[0], // f
2806 1, // h
2807 vshift_[0], // V(a)::{c}
2808 vshift_[0] + vshift_[1], // V(a)::{g}
2809 vshift_[1], // V(c)::{g}
2810 };
2811 // V(bfhd)=V(b)+V(f)::{b}+V(h)::{b}+V(d)::{b}
2812 this->vertexNeighborBFHD_ = {
2813 -1, // a
2814 -1 + vshift_[0], // c
2815 vshift_[0], // d
2816 -1 + vshift_[1], // e
2817 vshift_[1], // f
2818 -1 + vshift_[0] + vshift_[1], // g
2819 vshift_[0] + vshift_[1], // h
2820 -vshift_[1], // V(f)::{b}
2821 -vshift_[0] - vshift_[1], // V(h)::{b}
2822 -vshift_[0], // V(d)::{b}
2823 };
2824
2825 // V(ab)=V(b)+V(a)::{b}
2826 this->vertexNeighborAB_ = {
2827 -1, // a
2828 -1 + vshift_[0], // c
2829 vshift_[0], // d
2830 -1 + vshift_[1], // e
2831 vshift_[1], // f
2832 -1 + vshift_[0] + vshift_[1], // g
2833 vshift_[0] + vshift_[1], // h
2834 1, // V(a)::{b}
2835 };
2836 // V(bd)=V(b)+V(d)::{b}
2837 this->vertexNeighborBD_ = {
2838 -1, // a
2839 -1 + vshift_[0], // c
2840 vshift_[0], // d
2841 -1 + vshift_[1], // e
2842 vshift_[1], // f
2843 -1 + vshift_[0] + vshift_[1], // g
2844 vshift_[0] + vshift_[1], // h
2845 -vshift_[0], // V(d)::{b}
2846 };
2847 // V(gh)=V(g)+V(h)::{g}
2848 this->vertexNeighborGH_ = {
2849 -vshift_[0] - vshift_[1], // a
2850 1 - vshift_[0] - vshift_[1], // b
2851 -vshift_[1], // c
2852 1 - vshift_[1], // d
2853 -vshift_[0], // e
2854 1 - vshift_[0], // f
2855 1, // h
2856 -1, // V(h)::{g}
2857 };
2858 // V(eg)=V(g)+V(e)::{g}
2859 this->vertexNeighborEG_ = {
2860 -vshift_[0] - vshift_[1], // a
2861 1 - vshift_[0] - vshift_[1], // b
2862 -vshift_[1], // c
2863 1 - vshift_[1], // d
2864 -vshift_[0], // e
2865 1 - vshift_[0], // f
2866 1, // h
2867 vshift_[0], // V(e)::{g}
2868 };
2869 // V(cg)=V(g)+V(c)::{g}
2870 this->vertexNeighborCG_ = {
2871 -vshift_[0] - vshift_[1], // a
2872 1 - vshift_[0] - vshift_[1], // b
2873 -vshift_[1], // c
2874 1 - vshift_[1], // d
2875 -vshift_[0], // e
2876 1 - vshift_[0], // f
2877 1, // h
2878 vshift_[1], // V(c)::{g}
2879 };
2880 // V(bf)=V(b)+V(f)::{b}
2881 this->vertexNeighborBF_ = {
2882 -1, // a
2883 -1 + vshift_[0], // c
2884 vshift_[0], // d
2885 -1 + vshift_[1], // e
2886 vshift_[1], // f
2887 -1 + vshift_[0] + vshift_[1], // g
2888 vshift_[0] + vshift_[1], // h
2889 -vshift_[1], // V(f)::{b}
2890 };
2891
2892 // V(b)={a,c,d,e,f,g,h}
2893 this->vertexNeighborB_ = {
2894 -1, // a
2895 -1 + vshift_[0], // c
2896 vshift_[0], // d
2897 -1 + vshift_[1], // e
2898 vshift_[1], // f
2899 -1 + vshift_[0] + vshift_[1], // g
2900 vshift_[0] + vshift_[1], // h
2901 };
2902 // V(g)={a,b,c,d,e,f,h}
2903 this->vertexNeighborG_ = {
2904 -vshift_[0] - vshift_[1], // a
2905 1 - vshift_[0] - vshift_[1], // b
2906 -vshift_[1], // c
2907 1 - vshift_[1], // d
2908 -vshift_[0], // e
2909 1 - vshift_[0], // f
2910 1, // h
2911 };
2912
2913 // V(ef)=V(f)+V(e)::{b,f}
2914 this->vertexNeighborEF_ = {
2915 -vshift_[1], // b
2916 -1, // e
2917 -1 + vshift_[0], // g
2918 vshift_[0], // h
2919 1 - vshift_[1], // V(e)::{b}
2920 1, // V(e)::{f}
2921 };
2922 // V(cd)=V(d)+V(c)::{b,d}
2923 this->vertexNeighborCD_ = {
2924 -vshift_[0], // b
2925 -1, // c
2926 -1 + vshift_[1], // g
2927 vshift_[1], // h
2928 1 - vshift_[0], // V(c)::{b}
2929 1, // V(c)::{d}
2930 };
2931 // V(ac)=V(c)+V(a)::{c,g}
2932 this->vertexNeighborAC_ = {
2933 -vshift_[0], // a
2934 1 - vshift_[0], // b
2935 1, // d
2936 vshift_[1], // g
2937 vshift_[0], // V(a)::{c}
2938 vshift_[0] + vshift_[1], // V(a)::{c}
2939 };
2940 // V(ae)=V(a)+V(e)::{a,b}
2941 this->vertexNeighborAE_ = {
2942 1, // b
2943 vshift_[0], // c
2944 vshift_[1], // e
2945 vshift_[0] + vshift_[1], // g
2946 -vshift_[1], // V(e)::{a}
2947 1 - vshift_[1], // V(e)::{b}
2948 };
2949 // V(fh)=V(f)+V(h)::{b,f}
2950 this->vertexNeighborFH_ = {
2951 -vshift_[1], // b
2952 -1, // e
2953 -1 + vshift_[0], // g
2954 vshift_[0], // h
2955 -vshift_[0] - vshift_[1], // V(h)::{b}
2956 -vshift_[0], // V(h)::{f}
2957 };
2958 // V(dh)=V(d)+V(h)::{b,d}
2959 this->vertexNeighborDH_ = {
2960 -vshift_[0], // b
2961 -1, // c
2962 -1 + vshift_[1], // g
2963 vshift_[1], // h
2964 -vshift_[0] - vshift_[1], // V(h)::{b}
2965 -vshift_[1], // V(h)::{d}
2966 };
2967
2968 // V(a)={b,c,e,g}
2969 this->vertexNeighborA_ = {
2970 1, // b
2971 vshift_[0], // c
2972 vshift_[1], // e
2973 vshift_[0] + vshift_[1], // g
2974 };
2975 // V(c)={a,b,d,g}
2976 this->vertexNeighborC_ = {
2977 -vshift_[0], // a
2978 1 - vshift_[0], // b
2979 1, // d
2980 +vshift_[1], // g
2981 };
2982 // V(d)={b,c,g,h}
2983 this->vertexNeighborD_ = {
2984 -vshift_[0], // b
2985 -1, // c
2986 -1 + vshift_[1], // g
2987 vshift_[1], // h
2988 };
2989 // V(e)={a,b,f,g}
2990 this->vertexNeighborE_ = {
2991 -vshift_[1], // a
2992 1 - vshift_[1], // b
2993 1, // f
2994 +vshift_[0], // g
2995 };
2996 // V(f)={b,e,g,h}
2997 this->vertexNeighborF_ = {
2998 -vshift_[1], // b
2999 -1, // e
3000 -1 + vshift_[0], // g
3001 vshift_[0], // h
3002 };
3003 // V(h)={b,d,f,g}
3004 this->vertexNeighborH_ = {
3005 -vshift_[0] - vshift_[1], // b
3006 -vshift_[1], // d
3007 -vshift_[0], // f
3008 -1, // g
3009 };
3010
3011 // V(abcd)=V(d)::{b,c}+V(c)::{b,d}+V(a)::{b}+V(b)::{c}
3012 this->vertexNeighbor2dABCD_ = {
3013 -1, -vshift_[0], -vshift_[0] + 1, 1, vshift_[0], vshift_[0] - 1,
3014 };
3015 // V(ab)=V(b)::{a,c,d}+V(a)::{b}
3016 this->vertexNeighbor2dAB_ = {
3017 -1, // V(b)::a
3018 vshift_[0] - 1, // V(b)::c
3019 vshift_[0], // V(b)::d
3020 +1, // V(a)::b
3021 };
3022 // V(cd)=V(c)::{a,b,d}+V(d)::{c}
3023 this->vertexNeighbor2dCD_ = {
3024 -1, // V(d)::c
3025 -vshift_[0], // V(c)::a
3026 -vshift_[0] + 1, // V(c)::b
3027 1, // V(c)::d
3028 };
3029 // V(ac)=V(c)::{a,b,d}+V(a)::{c}
3030 this->vertexNeighbor2dAC_ = {
3031 -vshift_[0], // V(c)::{a}
3032 -vshift_[0] + 1, // V(c)::{b}
3033 1, // V(c)::{d}
3034 vshift_[0], // V(a)::{c}
3035 };
3036 // V(bd)=V(b)::{c,d}+V(d)::{b,c}
3037 this->vertexNeighbor2dBD_ = {
3038 vshift_[0] - 1, // V(b)::{c}
3039 vshift_[0], // V(b)::{d}
3040 -vshift_[0], // V(d)::{b}
3041 -1, // V(d)::{c}
3042 };
3043 // V(b)={a,c,d}
3044 this->vertexNeighbor2dB_ = {
3045 -1, // a
3046 vshift_[0], // d
3047 vshift_[0] - 1, // c
3048 };
3049 // V(c)={a,b,d}
3050 this->vertexNeighbor2dC_ = {
3051 1, // d
3052 -vshift_[0], // a
3053 -vshift_[0] + 1, // b
3054 };
3055 this->vertexNeighbor2dA_ = {};
3056 // V(a)={b,c}
3057 this->vertexNeighbor2dA_ = {
3058 1, // b
3059 vshift_[0] // c
3060 };
3061 // V(d)={c,b}
3062 this->vertexNeighbor2dD_ = {
3063 -1, // c
3064 -vshift_[0], // b
3065
3066 };
3067
3068 return 0;
3069}
3070
3071#ifdef TTK_ENABLE_MPI
3072
3073int ttk::ImplicitTriangulation::preconditionDistributedCells() {
3074 if(this->hasPreconditionedDistributedCells_) {
3075 return 0;
3076 }
3077 if(!ttk::hasInitializedMPI()) {
3078 return -1;
3079 }
3080 if(this->cellGhost_ == nullptr) {
3081 if(ttk::isRunningWithMPI()) {
3082 this->printErr("Missing cell ghost array!");
3083 }
3084 return -3;
3085 }
3086
3087 Timer tm{};
3088
3089 // number of local cells (with ghost cells...)
3090 const auto nLocCells{this->getNumberOfCells()};
3091
3092 // there are 6 tetrahedra per cubic cell (and 2 triangles per square)
3093 const int nTetraPerCube{this->dimensionality_ == 3 ? 6 : 2};
3094 std::vector<unsigned char> fillCells(nLocCells / nTetraPerCube);
3095
3096 this->ghostCellsPerOwner_.resize(ttk::MPIsize_);
3097
3098 this->neighborCellBBoxes_.resize(ttk::MPIsize_);
3099 auto &localBBox{this->neighborCellBBoxes_[ttk::MPIrank_]};
3100 // "good" starting values?
3101 localBBox = {
3102 this->localGridOffset_[0] + this->dimensions_[0], this->localGridOffset_[0],
3103 this->localGridOffset_[1] + this->dimensions_[1], this->localGridOffset_[1],
3104 this->localGridOffset_[2] + this->dimensions_[2], this->localGridOffset_[2],
3105 };
3106
3107 for(SimplexId lcid = 0; lcid < nLocCells; ++lcid) {
3108 // only keep non-ghost cells
3109 if(this->cellGhost_[lcid / nTetraPerCube] == 1) {
3110 continue;
3111 }
3112 // local vertex coordinates
3113 std::array<SimplexId, 3> p{};
3114 if(this->dimensionality_ == 3) {
3115 this->tetrahedronToPosition(lcid, p.data());
3116 } else if(this->dimensionality_ == 2) {
3117 this->triangleToPosition2d(lcid, p.data());
3118 // compatibility with tetrahedronToPosition; fix a bounding box
3119 // error in the first axis
3120 p[0] /= 2;
3121 }
3122
3123 // global vertex coordinates
3124 p[0] += this->localGridOffset_[0];
3125 p[1] += this->localGridOffset_[1];
3126 p[2] += this->localGridOffset_[2];
3127
3128 if(p[0] < localBBox[0]) {
3129 localBBox[0] = p[0];
3130 }
3131 if(p[0] > localBBox[1]) {
3132 localBBox[1] = p[0];
3133 }
3134 if(p[1] < localBBox[2]) {
3135 localBBox[2] = p[1];
3136 }
3137 if(p[1] > localBBox[3]) {
3138 localBBox[3] = p[1];
3139 }
3140 if(p[2] < localBBox[4]) {
3141 localBBox[4] = p[2];
3142 }
3143 if(p[2] > localBBox[5]) {
3144 localBBox[5] = p[2];
3145 }
3146 }
3147 localBBox[1]++;
3148 localBBox[3]++;
3149 localBBox[5]++;
3150
3151 for(size_t i = 0; i < this->neighborRanks_.size(); ++i) {
3152 const auto neigh{this->neighborRanks_[i]};
3153 MPI_Sendrecv(this->neighborCellBBoxes_[ttk::MPIrank_].data(), 6,
3154 ttk::getMPIType(SimplexId{}), neigh, ttk::MPIrank_,
3155 this->neighborCellBBoxes_[neigh].data(), 6,
3156 ttk::getMPIType(SimplexId{}), neigh, neigh, ttk::MPIcomm_,
3157 MPI_STATUS_IGNORE);
3158 }
3159
3160 this->hasPreconditionedDistributedCells_ = true;
3161
3162 return 0;
3163}
3164
3165void ttk::ImplicitTriangulation::createMetaGrid(const double *const bounds) {
3166
3167 // only works with 2 processes or more
3168 if(!ttk::isRunningWithMPI()) {
3169 return;
3170 }
3171
3172 // no need to create it anew?
3173 if(this->metaGrid_ != nullptr) {
3174 return;
3175 }
3176
3177 // Reorganize bounds to only execute Allreduce twice
3178 std::array<double, 6> tempBounds = {
3179 bounds[0], bounds[2], bounds[4], bounds[1], bounds[3], bounds[5],
3180 };
3181 std::array<double, 6> tempGlobalBounds{};
3182
3183 // Compute and send to all processes the lower bounds of the data set
3184 MPI_Allreduce(tempBounds.data(), tempGlobalBounds.data(), 3, MPI_DOUBLE,
3185 MPI_MIN, ttk::MPIcomm_);
3186 // Compute and send to all processes the higher bounds of the data set
3187 MPI_Allreduce(&tempBounds[3], &tempGlobalBounds[3], 3, MPI_DOUBLE, MPI_MAX,
3188 ttk::MPIcomm_);
3189
3190 // re-order tempGlobalBounds
3191 std::array<double, 6> globalBounds{
3192 tempGlobalBounds[0], tempGlobalBounds[3], tempGlobalBounds[1],
3193 tempGlobalBounds[4], tempGlobalBounds[2], tempGlobalBounds[5],
3194 };
3195
3196 const std::array<int, 3> dimensions = {
3197 static_cast<int>(
3198 std::round((globalBounds[1] - globalBounds[0]) / this->spacing_[0]))
3199 + 1,
3200 static_cast<int>(
3201 std::round((globalBounds[3] - globalBounds[2]) / this->spacing_[1]))
3202 + 1,
3203 static_cast<int>(
3204 std::round((globalBounds[5] - globalBounds[4]) / this->spacing_[2]))
3205 + 1,
3206 };
3207
3208 this->localGridOffset_ = {
3209 static_cast<SimplexId>(
3210 std::round((this->origin_[0] - globalBounds[0]) / this->spacing_[0])),
3211 static_cast<SimplexId>(
3212 std::round((this->origin_[1] - globalBounds[2]) / this->spacing_[1])),
3213 static_cast<SimplexId>(
3214 std::round((this->origin_[2] - globalBounds[4]) / this->spacing_[2])),
3215 };
3216
3217 this->metaGrid_ = std::make_shared<ImplicitNoPreconditions>();
3218 this->metaGrid_->setInputGrid(globalBounds[0], globalBounds[1],
3219 globalBounds[2], this->spacing_[0],
3220 this->spacing_[1], this->spacing_[2],
3221 dimensions[0], dimensions[1], dimensions[2]);
3222 this->metaGrid_->preconditionBoundaryVertices();
3223 this->metaGrid_->preconditionBoundaryEdges();
3224 this->metaGrid_->preconditionBoundaryTriangles();
3225}
3226
3227std::array<SimplexId, 3>
3228 ttk::ImplicitTriangulation::getVertGlobalCoords(const SimplexId lvid) const {
3229
3230 // local vertex coordinates
3231 std::array<SimplexId, 3> p{};
3232 if(this->dimensionality_ == 3) {
3233 this->vertexToPosition(lvid, p.data());
3234 } else if(this->dimensionality_ == 2) {
3235 this->vertexToPosition2d(lvid, p.data());
3236 }
3237
3238 // global vertex coordinates
3239 p[0] += this->localGridOffset_[0];
3240 p[1] += this->localGridOffset_[1];
3241 p[2] += this->localGridOffset_[2];
3242
3243 return p;
3244}
3245
3246std::array<SimplexId, 3>
3247 ttk::ImplicitTriangulation::getVertLocalCoords(const SimplexId gvid) const {
3248
3249 // global vertex coordinates
3250 std::array<SimplexId, 3> p{};
3251 if(this->dimensionality_ == 3) {
3252 this->metaGrid_->vertexToPosition(gvid, p.data());
3253 } else if(this->dimensionality_ == 2) {
3254 this->metaGrid_->vertexToPosition2d(gvid, p.data());
3255 }
3256
3257 // local vertex coordinates
3258 p[0] -= this->localGridOffset_[0];
3259 p[1] -= this->localGridOffset_[1];
3260 p[2] -= this->localGridOffset_[2];
3261
3262 return p;
3263}
3264
3265bool ImplicitTriangulation::isVertexOnGlobalBoundaryInternal(
3266 const SimplexId lvid) const {
3267
3268 if(!ttk::isRunningWithMPI()) {
3269 return this->isVertexOnBoundary(lvid);
3270 }
3271
3272#ifndef TTK_ENABLE_KAMIKAZE
3273 if(lvid > this->TTK_TRIANGULATION_INTERNAL(getNumberOfVertices)() - 1
3274 || lvid < 0) {
3275 return false;
3276 }
3277 if(this->metaGrid_ == nullptr) {
3278 return false;
3279 }
3280#endif // TTK_ENABLE_KAMIKAZE
3281
3282 const auto gvid{this->getVertexGlobalIdInternal(lvid)};
3283 if(gvid == -1) {
3284 return false;
3285 }
3286 return this->metaGrid_->isVertexOnBoundary(gvid);
3287}
3288
3289bool ImplicitTriangulation::isEdgeOnGlobalBoundaryInternal(
3290 const SimplexId leid) const {
3291
3292 if(!ttk::isRunningWithMPI()) {
3293 return this->isEdgeOnBoundary(leid);
3294 }
3295
3296#ifndef TTK_ENABLE_KAMIKAZE
3297 if(leid > this->getNumberOfEdgesInternal() - 1 || leid < 0) {
3298 return false;
3299 }
3300 if(this->metaGrid_ == nullptr) {
3301 return false;
3302 }
3303#endif // TTK_ENABLE_KAMIKAZE
3304
3305 const auto geid{this->getEdgeGlobalIdInternal(leid)};
3306 if(geid == -1) {
3307 return false;
3308 }
3309 return this->metaGrid_->isEdgeOnBoundary(geid);
3310}
3311
3312bool ImplicitTriangulation::isTriangleOnGlobalBoundaryInternal(
3313 const SimplexId ltid) const {
3314
3315 if(!ttk::isRunningWithMPI()) {
3316 return this->isTriangleOnBoundary(ltid);
3317 }
3318
3319#ifndef TTK_ENABLE_KAMIKAZE
3320 if(ltid > this->getNumberOfTrianglesInternal() - 1 || ltid < 0) {
3321 return false;
3322 }
3323 if(this->metaGrid_ == nullptr) {
3324 return false;
3325 }
3326#endif // TTK_ENABLE_KAMIKAZE
3327
3328 const auto gtid{this->getTriangleGlobalIdInternal(ltid)};
3329 if(gtid == -1) {
3330 return false;
3331 }
3332 return this->metaGrid_->isTriangleOnBoundary(gtid);
3333}
3334
3335int ttk::ImplicitTriangulation::getCellRankInternal(
3336 const SimplexId lcid) const {
3337
3338 const int nTetraPerCube{this->dimensionality_ == 3 ? 6 : 2};
3339 const auto locCubeId{lcid / nTetraPerCube};
3340
3341 if(this->cellGhost_[locCubeId] == 0) {
3342 return ttk::MPIrank_;
3343 }
3344
3345#ifndef TTK_ENABLE_KAMIKAZE
3346 if(this->neighborRanks_.empty() && ttk::MPIsize_ > 1) {
3347 this->printErr("Empty neighborsRanks_!");
3348 return -1;
3349 }
3350#endif // TTK_ENABLE_KAMIKAZE
3351
3352 const auto nVertsCell{this->getCellVertexNumber(lcid)};
3353 std::vector<bool> inRank(nVertsCell);
3354 for(const auto neigh : this->neighborRanks_) {
3355 std::fill(inRank.begin(), inRank.end(), false);
3356 const auto &bbox{this->neighborCellBBoxes_[neigh]};
3357 for(SimplexId i = 0; i < nVertsCell; ++i) {
3358 SimplexId v{};
3359 this->getCellVertex(lcid, i, v);
3360 if(this->vertexGhost_[v] == 0) {
3361 inRank[i] = true;
3362 } else {
3363 const auto p{this->getVertGlobalCoords(v)};
3364 if(p[0] >= bbox[0] && p[0] <= bbox[1] && p[1] >= bbox[2]
3365 && p[1] <= bbox[3] && p[2] >= bbox[4] && p[2] <= bbox[5]) {
3366 inRank[i] = true;
3367 }
3368 }
3369 }
3370 if(std::all_of(
3371 inRank.begin(), inRank.end(), [](const bool v) { return v; })) {
3372 return neigh;
3373 }
3374 }
3375
3376 return -1;
3377}
3378
3379#endif // TTK_ENABLE_MPI
3380
3381// explicit instantiations
#define TTK_TRIANGULATION_INTERNAL(NAME)
bool ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() isTriangleOnBoundary(const SimplexId &triangleId) const
#define CASE_EDGE_POSITION_P_3D
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getEdgeStar(const SimplexId &edgeId, const int &localStarId, SimplexId &starId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellNeighbors()
SimplexId ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getTriangleStarNumber(const SimplexId &triangleId) const
int ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellNeighbor(const SimplexId &cellId, const int &localNeighborId, SimplexId &neighborId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexStar(const SimplexId &vertexId, const int &localStarId, SimplexId &starId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangleLinkNumber(const SimplexId &triangleId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getEdgeLink(const SimplexId &edgeId, const int &localLinkId, SimplexId &linkId) const
#define CASE_EDGE_POSITION_D2_3D
#define CASE_EDGE_POSITION_D1_3D
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getTriangleLink(const SimplexId &triangleId, const int &localLinkId, SimplexId &linkId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellVertexNumber(const SimplexId &) const
SimplexId ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getEdgeStarNumber(const SimplexId &edgeId) const
#define CASE_EDGE_POSITION_L_2D
#define CASE_EDGE_POSITION_H_2D
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexNeighbor(const SimplexId &vertexId, const int &localNeighborId, SimplexId &neighborId) const
#define CASE_EDGE_POSITION_H_3D
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangleLinks()
#define CASE_EDGE_POSITION_L_3D
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangleStars()
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexLinkNumber(const SimplexId &vertexId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellNeighborNumber(const SimplexId &cellId) const
SimplexId ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexStarNumber(const SimplexId &vertexId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexLinks()
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdgeStars()
#define CASE_EDGE_POSITION_D3_3D
bool ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() isEdgeOnBoundary(const SimplexId &edgeId) const
int ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getCellVertex(const SimplexId &cellId, const int &localVertexId, SimplexId &vertexId) const
SimplexId ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdgeLinkNumber(const SimplexId &edgeId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexNeighbors()
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getTriangleStar(const SimplexId &triangleId, const int &localStarId, SimplexId &starId) const
const vector< std::array< SimplexId, 3 > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getTriangles()
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexStars()
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexPoint(const SimplexId &vertexId, float &x, float &y, float &z) const
const vector< std::array< SimplexId, 2 > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdges()
bool ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() isVertexOnBoundary(const SimplexId &vertexId) const
int ImplicitTriangulationCRTP< Derived >::TTK_TRIANGULATION_INTERNAL() getVertexLink(const SimplexId &vertexId, const int &localLinkId, SimplexId &linkId) const
const vector< vector< SimplexId > > *ImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getEdgeLinks()
SimplexId PeriodicImplicitTriangulation::TTK_TRIANGULATION_INTERNAL() getVertexNeighborNumber(const SimplexId &vertexId) const
virtual SimplexId getVertexTriangleNumberInternal(const SimplexId &ttkNotUsed(vertexId)) const
virtual SimplexId getVertexNeighborNumber(const SimplexId &vertexId) const
virtual bool isVertexOnBoundary(const SimplexId &vertexId) const
virtual int getVertexTriangleInternal(const SimplexId &ttkNotUsed(vertexId), const int &ttkNotUsed(localTriangleId), SimplexId &ttkNotUsed(triangleId)) const
virtual bool isEdgeOnBoundary(const SimplexId &edgeId) const
std::vector< std::vector< SimplexId > > vertexEdgeList_
std::vector< std::vector< SimplexId > > triangleEdgeVector_
virtual int getTriangleEdgeInternal(const SimplexId &ttkNotUsed(triangleId), const int &ttkNotUsed(localEdgeId), SimplexId &ttkNotUsed(edgeId)) const
virtual SimplexId getEdgeTriangleNumberInternal(const SimplexId &ttkNotUsed(edgeId)) const
virtual int getEdgeTriangleInternal(const SimplexId &ttkNotUsed(edgeId), const int &ttkNotUsed(localTriangleId), SimplexId &ttkNotUsed(triangleId)) const
virtual int getVertexEdgeInternal(const SimplexId &ttkNotUsed(vertexId), const int &ttkNotUsed(localEdgeId), SimplexId &ttkNotUsed(edgeId)) const
std::vector< std::vector< SimplexId > > vertexTriangleList_
std::vector< std::vector< SimplexId > > cellEdgeVector_
std::vector< std::vector< SimplexId > > cellTriangleVector_
std::vector< std::vector< SimplexId > > edgeTriangleList_
void setDebugMsgPrefix(const std::string &prefix)
Definition: Debug.h:364
int printMsg(const std::string &msg, const debug::Priority &priority=debug::Priority::INFO, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cout) const
Definition: Debug.h:118
int getTriangleVertexInternal(const SimplexId &triangleId, const int &localVertexId, SimplexId &vertexId) const override
int getTetrahedronVertex(const SimplexId &tetId, const int &localVertexId, SimplexId &vertexId) const override
int getTetrahedronTriangle(const SimplexId &tetId, const int &id, SimplexId &triangleId) const override
SimplexId getEdgeTriangleNumberInternal(const SimplexId &edgeId) const override
int getVertexEdgeInternal(const SimplexId &vertexId, const int &id, SimplexId &edgeId) const override
int getEdgeVertexInternal(const SimplexId &edgeId, const int &localVertexId, SimplexId &vertexId) const override
SimplexId getVertexTriangleNumberInternal(const SimplexId &vertexId) const override
SimplexId getTriangleNeighborNumber(const SimplexId &triangleId) const override
int getEdgeTriangleInternal(const SimplexId &edgeId, const int &id, SimplexId &triangleId) const override
int getTetrahedronNeighbor(const SimplexId &tetId, const int &localNeighborId, SimplexId &neighborId) const override
int getVertexTriangleInternal(const SimplexId &vertexId, const int &id, SimplexId &triangleId) const override
SimplexId getTetrahedronNeighborNumber(const SimplexId &tetId) const override
int getTriangleNeighbor(const SimplexId &triangleId, const int &localNeighborId, SimplexId &neighborId) const override
int getTriangleEdgeInternal(const SimplexId &triangleId, const int &id, SimplexId &edgeId) const override
int getTetrahedronEdge(const SimplexId &tetId, const int &id, SimplexId &edgeId) const override
std::array< SimplexId, 8 > vertexNeighborGH_
std::array< SimplexId, 4 > vertexNeighbor2dAC_
std::array< SimplexId, 8 > vertexNeighborBF_
std::array< SimplexId, 8 > vertexNeighborBD_
std::array< SimplexId, 3 > vertexNeighbor2dB_
std::array< SimplexId, 7 > vertexNeighborB_
std::array< SimplexId, 6 > vertexNeighborEF_
std::array< SimplexId, 14 > vertexNeighborABCDEFGH_
const std::vector< std::vector< SimplexId > > * getTriangleEdgesInternal() override
SimplexId getCellEdgeNumberInternal(const SimplexId &cellId) const override
std::array< SimplexId, 8 > vertexNeighborEG_
int getCellTriangleInternal(const SimplexId &cellId, const int &id, SimplexId &triangleId) const override
std::array< SimplexId, 4 > vertexNeighborH_
std::array< SimplexId, 4 > vertexNeighborE_
std::array< SimplexId, 2 > vertexNeighbor2dD_
bool TTK_TRIANGULATION_INTERNAL() isTriangleOnBoundary(const SimplexId &triangleId) const override
const std::vector< std::vector< SimplexId > > * getVertexEdgesInternal() override
std::array< SimplexId, 10 > vertexNeighborAEFB_
virtual int getTriangleNeighbor(const SimplexId &triangleId, const int &localNeighborId, SimplexId &neighborId) const =0
std::array< SimplexId, 6 > vertexNeighbor2dABCD_
std::array< SimplexId, 6 > vertexNeighborFH_
std::array< SimplexId, 6 > vertexNeighborDH_
std::array< SimplexId, 6 > vertexNeighborCD_
const std::vector< std::vector< SimplexId > > * getCellEdgesInternal() override
std::array< SimplexId, 7 > vertexNeighborG_
int setInputGrid(const float &xOrigin, const float &yOrigin, const float &zOrigin, const float &xSpacing, const float &ySpacing, const float &zSpacing, const SimplexId &xDim, const SimplexId &yDim, const SimplexId &zDim) override
int getTetrahedronNeighbors(std::vector< std::vector< SimplexId > > &neighbors)
int TTK_TRIANGULATION_INTERNAL() getCellNeighbor(const SimplexId &cellId, const int &localNeighborId, SimplexId &neighborId) const override
const std::vector< std::vector< SimplexId > > * getVertexTrianglesInternal() override
virtual SimplexId getTetrahedronNeighborNumber(const SimplexId &tetId) const =0
virtual int getTetrahedronNeighbor(const SimplexId &tetId, const int &localNeighborId, SimplexId &neighborId) const =0
std::array< SimplexId, 10 > vertexNeighborAEGC_
virtual int getTetrahedronTriangle(const SimplexId &tetId, const int &id, SimplexId &triangleId) const =0
std::array< SimplexId, 10 > vertexNeighborEFGH_
std::array< SimplexId, 2 > vertexNeighbor2dA_
bool isPowerOfTwo(unsigned long long int v, unsigned long long int &r)
SimplexId TTK_TRIANGULATION_INTERNAL() getNumberOfVertices() const override
SimplexId getVertexEdgeNumberInternal(const SimplexId &vertexId) const override
std::array< SimplexId, 4 > vertexNeighbor2dBD_
std::array< SimplexId, 10 > vertexNeighborBFHD_
int getTriangleNeighbors(std::vector< std::vector< SimplexId > > &neighbors)
std::array< SimplexId, 4 > vertexNeighborD_
SimplexId getNumberOfEdgesInternal() const override
std::array< SimplexId, 4 > vertexNeighborC_
virtual int getTetrahedronEdge(const SimplexId &tetId, const int &id, SimplexId &edgeId) const =0
virtual SimplexId getTriangleNeighborNumber(const SimplexId &triangleId) const =0
int getTetrahedronEdges(std::vector< std::vector< SimplexId > > &edges) const
std::array< SimplexId, 4 > vertexNeighbor2dCD_
std::array< SimplexId, 8 > vertexNeighborCG_
std::array< SimplexId, 3 > vertexNeighbor2dC_
std::array< SimplexId, 6 > vertexNeighborAC_
const std::vector< std::vector< SimplexId > > * getEdgeTrianglesInternal() override
std::array< SimplexId, 10 > vertexNeighborABCD_
std::array< SimplexId, 10 > vertexNeighborGHDC_
std::array< SimplexId, 8 > vertexNeighborAB_
std::array< SimplexId, 6 > vertexNeighborAE_
int getCellEdgeInternal(const SimplexId &cellId, const int &id, SimplexId &edgeId) const override
std::array< SimplexId, 4 > vertexNeighborA_
SimplexId getNumberOfTrianglesInternal() const override
std::array< SimplexId, 4 > vertexNeighborF_
const std::vector< std::vector< SimplexId > > * getCellTrianglesInternal() override
std::array< SimplexId, 4 > vertexNeighbor2dAB_
int preconditionVertexNeighborsInternal() override
int getTetrahedronTriangles(std::vector< std::vector< SimplexId > > &triangles) const
std::array< SimplexId, 3 > dimensions_
double getElapsedTime()
Definition: Timer.h:15
The Topology ToolKit.
COMMON_EXPORTS int MPIsize_
Definition: BaseClass.cpp:10
COMMON_EXPORTS int MPIrank_
Definition: BaseClass.cpp:9
int SimplexId
Identifier type for simplices of any dimension.
Definition: DataTypes.h:22
printMsg(debug::output::GREEN+"                           "+debug::output::ENDCOLOR+debug::output::GREEN+"▒"+debug::output::ENDCOLOR+debug::output::GREEN+"▒▒▒▒▒▒▒▒▒▒▒▒▒░"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)