TTK
Loading...
Searching...
No Matches
CompactTriangulation.h
Go to the documentation of this file.
1
28
29#pragma once
30
31// base code includes
33#include <CellArray.h>
34#include <FlatJaggedArray.h>
35#include <algorithm>
36#include <boost/functional/hash.hpp>
37#include <boost/unordered_map.hpp>
38#include <boost/unordered_set.hpp>
39#include <list>
40
41namespace ttk {
42
44 private:
45 /* components */
46 SimplexId nid;
47 std::vector<std::array<SimplexId, 2>> internalEdgeList_;
48 std::vector<std::array<SimplexId, 3>> internalTriangleList_;
49 boost::unordered_map<std::array<SimplexId, 2>, SimplexId> internalEdgeMap_;
50 boost::unordered_map<std::array<SimplexId, 2>, SimplexId> externalEdgeMap_;
51 boost::unordered_map<std::array<SimplexId, 3>, SimplexId>
52 internalTriangleMap_;
53 boost::unordered_map<std::array<SimplexId, 3>, SimplexId>
54 externalTriangleMap_;
55 /* boundary cells */
56 std::vector<bool> boundaryVertices_;
57 std::vector<bool> boundaryEdges_;
58 std::vector<bool> boundaryTriangles_;
59 /* vertex relationships */
60 FlatJaggedArray vertexEdges_;
61 FlatJaggedArray vertexLinks_;
62 FlatJaggedArray vertexNeighbors_;
63 FlatJaggedArray vertexStars_;
64 FlatJaggedArray vertexTriangles_;
65 /* edge relationships */
66 // edgeVertex relation can be extracted from internal edge list
67 FlatJaggedArray edgeLinks_;
68 FlatJaggedArray edgeStars_;
69 FlatJaggedArray edgeTriangles_;
70 /* triangle relationships */
71 // triangleVertex relation can be extracted from internal triangle list
72 std::vector<std::array<SimplexId, 3>> triangleEdges_;
73 FlatJaggedArray triangleLinks_;
74 FlatJaggedArray triangleStars_;
75 /* cell relationships */
76 std::vector<std::array<SimplexId, 6>> tetraEdges_;
77 FlatJaggedArray cellNeighbors_;
78 std::vector<std::array<SimplexId, 4>> tetraTriangles_;
79
80 public:
81 ImplicitCluster() = default;
82 ImplicitCluster(SimplexId id) : nid(id) {
83 }
84 ~ImplicitCluster() = default;
85
87 };
88
90
91 // different id types for compact triangulation
92 enum class SIMPLEX_ID { EDGE_ID = 1, TRIANGLE_ID = 2 };
93
94 public:
101
105 inline int setInputPoints(const SimplexId &pointNumber,
106 const void *pointSet,
107 const int *indexArray,
108 const bool &doublePrecision = false) {
109
110 if(vertexNumber_)
111 clear();
112
113 vertexNumber_ = pointNumber;
114 pointSet_ = pointSet;
115 vertexIndices_ = indexArray;
116 doublePrecision_ = doublePrecision;
117
118 return 0;
119 }
120
125#ifdef TTK_CELL_ARRAY_NEW
126 // Layout with connectivity + offset array (new)
127 inline int setInputCells(const SimplexId &cellNumber,
128 const LongSimplexId *connectivity,
129 const LongSimplexId *offset) {
130
131 // Cell Check
132 {
133 if(cellNumber > 0) {
134 const auto &cellDimension = offset[1] - offset[0] - 1;
135
136 if(cellDimension < 0 || cellDimension > 3) {
137 this->printErr("Unable to create triangulation for cells of "
138 "dimension 4 or higher ("
139 + std::to_string(cellDimension) + ").");
140 return -1;
141 }
142
143 bool error = false;
144
145#ifdef TTK_ENABLE_OPENMP
146#pragma omp parallel for num_threads(this->threadNumber_)
147#endif
148 for(SimplexId i = 0; i < cellNumber; i++) {
149 if(offset[i + 1] - offset[i] - 1 != cellDimension) {
150#ifdef TTK_ENABLE_OPENMP
151#pragma omp atomic write
152#endif // TTK_ENABLE_OPENMP
153 error = true;
154 }
155 }
156
157 if(error) {
158 this->printErr("Unable to create triangulation for "
159 "inhomogeneous\ncell dimensions.");
160 return -2;
161 }
162 }
163 }
164
165 if(cellNumber_)
166 clear();
167
168 cellNumber_ = cellNumber;
169 std::vector<SimplexId> vertexMap(vertexNumber_);
170 reorderVertices(vertexMap);
171 reorderCells(vertexMap, cellNumber, connectivity, offset);
173 = std::make_shared<CellArray>(connectivity, offset, cellNumber);
174
175 // ASSUME Regular Mesh Here to compute dimension!
176 if(cellNumber) {
177 if(cellArray_->getCellVertexNumber(0) == 3) {
178 maxCellDim_ = 2;
180 } else {
181 maxCellDim_ = 3;
182 }
183 }
184
185 return 0;
186 }
187#else
188 // Flat layout with a single array (legacy & default one)
189 inline int setInputCells(const SimplexId &cellNumber,
190 const LongSimplexId *cellArray) {
191 if(cellNumber_)
192 clear();
193
194 cellNumber_ = cellNumber;
195
196 if(cellNumber) {
197 // assume regular mesh here to compute dimension
198 maxCellDim_ = cellArray[0] - 1;
199 std::vector<SimplexId> vertexMap(vertexNumber_);
200 reorderVertices(vertexMap);
201 reorderCells(vertexMap, cellArray);
202 cellArray_ = std::make_shared<CellArray>(
203 cellArray, cellNumber, cellArray[0] - 1);
204 }
205
206 return 0;
207 }
208#endif
209
213 int reorderVertices(std::vector<SimplexId> &vertexMap);
214
218 int reorderCells(const std::vector<SimplexId> &vertexMap,
219 const SimplexId &cellNumber,
220 const LongSimplexId *connectivity,
221 const LongSimplexId *offset);
222
226 int reorderCells(const std::vector<SimplexId> &vertexMap,
227 const LongSimplexId *cellArray);
228
229 inline int getCellEdgeInternal(const SimplexId &cellId,
230 const int &localEdgeId,
231 SimplexId &edgeId) const override {
232
233#ifndef TTK_ENABLE_KAMIKAZE
234 if((cellId < 0) || (cellId >= cellNumber_)) {
235 edgeId = -1;
236 return 0;
237 }
238 if(localEdgeId < 0) {
239 edgeId = -2;
240 return 0;
241 }
242#endif
243
244 const SimplexId nid
245 = vertexIndices_[cellArray_->getCellVertex(cellId, 0)];
246 const SimplexId localCellId = cellId - cellIntervals_[nid - 1] - 1;
247 ImplicitCluster *exnode = searchCache(nid);
248 if(exnode->tetraEdges_.empty()) {
249 getClusterTetraEdges(exnode);
250 }
251
252 if(localEdgeId >= (int)(exnode->tetraEdges_)[localCellId].size()) {
253 edgeId = -2;
254 } else {
255 edgeId = (exnode->tetraEdges_)[localCellId][localEdgeId];
256 }
257 return 0;
258 }
259
260 inline SimplexId
261 getCellEdgeNumberInternal(const SimplexId &cellId) const override {
262
263#ifndef TTK_ENABLE_KAMIKAZE
264 if((cellId < 0) || (cellId >= cellNumber_))
265 return -1;
266#endif
267
268 (void)cellId;
269 return (maxCellDim_ + 1) * maxCellDim_ / 2;
270 }
271
272 inline const std::vector<std::vector<SimplexId>> *
274 if(cellEdgeVector_.empty()) {
276 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
277 ImplicitCluster *exnode = searchCache(nid);
278 if(exnode->tetraEdges_.empty()) {
279 getClusterTetraEdges(exnode);
280 }
281 for(size_t i = 0; i < exnode->tetraEdges_.size(); i++) {
282 cellEdgeVector_.emplace_back(exnode->tetraEdges_.at(i).begin(),
283 exnode->tetraEdges_.at(i).end());
284 }
285 }
286 }
287 return &cellEdgeVector_;
288 }
289
291 const SimplexId &cellId,
292 const int &localNeighborId,
293 SimplexId &neighborId) const override {
294
295#ifndef TTK_ENABLE_KAMIKAZE
296 if((cellId < 0) || (cellId >= cellNumber_)) {
297 neighborId = -1;
298 return 0;
299 }
300 if(localNeighborId < 0) {
301 neighborId = -2;
302 return 0;
303 }
304#endif
305
306 const SimplexId nid
307 = vertexIndices_[cellArray_->getCellVertex(cellId, 0)];
308 const SimplexId localCellId = cellId - cellIntervals_[nid - 1] - 1;
309 ImplicitCluster *exnode = searchCache(nid);
310 if(exnode->cellNeighbors_.empty()) {
312 }
313
314 if(localNeighborId >= exnode->cellNeighbors_.size(localCellId)) {
315 neighborId = -2;
316 } else {
317 neighborId = exnode->cellNeighbors_.get(localCellId, localNeighborId);
318 }
319 return 0;
320 }
321
323 const SimplexId &cellId) const override {
324
325#ifndef TTK_ENABLE_KAMIKAZE
326 if((cellId < 0) || (cellId >= cellNumber_))
327 return -1;
328#endif
329
330 const SimplexId nid
331 = vertexIndices_[cellArray_->getCellVertex(cellId, 0)];
332 const SimplexId localCellId = cellId - cellIntervals_[nid - 1] - 1;
333 ImplicitCluster *exnode = searchCache(nid);
334 if(exnode->cellNeighbors_.empty()) {
336 }
337 return exnode->cellNeighbors_.size(localCellId);
338 }
339
340 inline const std::vector<std::vector<SimplexId>> *
343 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
344 std::vector<std::vector<SimplexId>> localCellNeighbors;
345 ImplicitCluster *exnode = searchCache(nid);
346 if(exnode->cellNeighbors_.empty()) {
348 }
349 exnode->cellNeighbors_.copyTo(localCellNeighbors);
351 localCellNeighbors.begin(),
352 localCellNeighbors.end());
353 }
354 return &cellNeighborList_;
355 }
356
357 inline int getCellTriangleInternal(const SimplexId &cellId,
358 const int &localTriangleId,
359 SimplexId &triangleId) const override {
360
361#ifndef TTK_ENABLE_KAMIKAZE
362 if((cellId < 0) || (cellId >= cellNumber_)) {
363 triangleId = -1;
364 return 0;
365 }
366 if((localTriangleId < 0)
367 || (localTriangleId >= getCellTriangleNumber(cellId))) {
368 triangleId = -2;
369 return 0;
370 }
371#endif
372
373 const SimplexId nid
374 = vertexIndices_[cellArray_->getCellVertex(cellId, 0)];
375 const SimplexId localCellId = cellId - cellIntervals_[nid - 1] - 1;
376 ImplicitCluster *exnode = searchCache(nid);
377 if(exnode->tetraTriangles_.empty()) {
379 }
380 triangleId = (exnode->tetraTriangles_)[localCellId][localTriangleId];
381 return 0;
382 }
383
384 inline SimplexId
385 getCellTriangleNumberInternal(const SimplexId &cellId) const override {
386
387#ifndef TTK_ENABLE_KAMIKAZE
388 if((cellId < 0) || (cellId >= cellNumber_))
389 return -1;
390#endif
391
392 (void)cellId;
393 return (maxCellDim_ + 1) * maxCellDim_ * (maxCellDim_ - 1) / 6;
394 }
395
396 inline const std::vector<std::vector<SimplexId>> *
398 if(cellTriangleVector_.empty()) {
400 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
401 ImplicitCluster *exnode = searchCache(nid);
402 if(exnode->tetraTriangles_.empty()) {
404 }
405 for(size_t i = 0; i < exnode->tetraTriangles_.size(); i++) {
406 cellTriangleVector_.emplace_back(
407 exnode->tetraTriangles_.at(i).begin(),
408 exnode->tetraTriangles_.at(i).end());
409 }
410 }
411 }
412 return &cellTriangleVector_;
413 }
414
416 const SimplexId &cellId,
417 const int &localVertexId,
418 SimplexId &vertexId) const override {
419
420#ifndef TTK_ENABLE_KAMIKAZE
421 if((cellId < 0) || (cellId >= cellNumber_)) {
422 vertexId = -1;
423 return 0;
424 }
425 if((localVertexId < 0)
426 || (localVertexId >= cellArray_->getCellVertexNumber(cellId))) {
427 vertexId = -2;
428 return 0;
429 }
430#endif
431
432 vertexId = cellArray_->getCellVertex(cellId, localVertexId);
433 return 0;
434 }
435
437 const SimplexId &cellId) const override {
438
439#ifndef TTK_ENABLE_KAMIKAZE
440 if((cellId < 0) || (cellId >= cellNumber_))
441 return -1;
442#endif
443
444 return cellArray_->getCellVertexNumber(cellId);
445 }
446
448 return maxCellDim_;
449 }
450
451 inline const std::vector<std::array<SimplexId, 2>> *
453 edgeList_.reserve(edgeIntervals_.back() + 1);
454 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
455 ImplicitCluster *exnode = searchCache(nid);
456 if(exnode->internalEdgeList_.empty())
457 buildInternalEdgeMap(exnode, true, false);
458 edgeList_.insert(edgeList_.end(), exnode->internalEdgeList_.begin(),
459 exnode->internalEdgeList_.end());
460 }
461 return &edgeList_;
462 }
463
465 const SimplexId &edgeId,
466 const int &localLinkId,
467 SimplexId &linkId) const override {
468
469#ifndef TTK_ENABLE_KAMIKAZE
470 if((edgeId < 0) || (edgeId > edgeIntervals_.back())) {
471 linkId = -1;
472 return 0;
473 }
474 if(localLinkId < 0) {
475 linkId = -2;
476 return 0;
477 }
478#endif
479
480 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
481 const SimplexId localEdgeId = edgeId - edgeIntervals_[nid - 1] - 1;
482 ImplicitCluster *exnode = searchCache(nid);
483 if(exnode->edgeLinks_.empty()) {
484 getClusterEdgeLinks(exnode);
485 }
486
487 if(localLinkId >= exnode->edgeLinks_.size(localEdgeId)) {
488 linkId = -2;
489 } else {
490 linkId = exnode->edgeLinks_.get(localEdgeId, localLinkId);
491 }
492 return 0;
493 }
494
496 const SimplexId &edgeId) const override {
497
498#ifndef TTK_ENABLE_KAMIKAZE
499 if((edgeId < 0) || (edgeId > edgeIntervals_.back()))
500 return -1;
501#endif
502
503 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
504 const SimplexId localEdgeId = edgeId - edgeIntervals_[nid - 1] - 1;
505 ImplicitCluster *exnode = searchCache(nid);
506 if(exnode->edgeLinks_.empty()) {
507 getClusterEdgeLinks(exnode);
508 }
509 return exnode->edgeLinks_.size(localEdgeId);
510 }
511
512 inline const std::vector<std::vector<SimplexId>> *
514 edgeLinkList_.reserve(edgeIntervals_.back() + 1);
515 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
516 std::vector<std::vector<SimplexId>> localEdgeLinks;
517 ImplicitCluster *exnode = searchCache(nid);
518 if(exnode->edgeLinks_.empty()) {
519 getClusterEdgeLinks(exnode);
520 }
521 exnode->edgeLinks_.copyTo(localEdgeLinks);
522 edgeLinkList_.insert(
523 edgeLinkList_.end(), localEdgeLinks.begin(), localEdgeLinks.end());
524 }
525 return &edgeLinkList_;
526 }
527
529 const SimplexId &edgeId,
530 const int &localStarId,
531 SimplexId &starId) const override {
532
533#ifndef TTK_ENABLE_KAMIKAZE
534 if((edgeId < 0) || (edgeId > edgeIntervals_.back())) {
535 starId = -1;
536 return 0;
537 }
538 if(localStarId < 0) {
539 starId = -2;
540 return 0;
541 }
542#endif
543
544 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
545 const SimplexId localEdgeId = edgeId - edgeIntervals_[nid - 1] - 1;
546 ImplicitCluster *exnode = searchCache(nid);
547 if(exnode->edgeStars_.empty()) {
548 getClusterEdgeStars(exnode);
549 }
550
551 if(localStarId >= exnode->edgeStars_.size(localEdgeId)) {
552 starId = -2;
553 } else {
554 starId = exnode->edgeStars_.get(localEdgeId, localStarId);
555 }
556 return 0;
557 }
558
560 const SimplexId &edgeId) const override {
561
562#ifndef TTK_ENABLE_KAMIKAZE
563 if((edgeId < 0) || (edgeId > edgeIntervals_.back()))
564 return -1;
565#endif
566 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
567 ImplicitCluster *exnode = searchCache(nid);
568 const SimplexId localEdgeId = edgeId - edgeIntervals_[nid - 1] - 1;
569 if(exnode->edgeStars_.empty()) {
570 getClusterEdgeStars(exnode);
571 }
572 return exnode->edgeStars_.size(localEdgeId);
573 }
574
575 inline const std::vector<std::vector<SimplexId>> *
577 edgeStarList_.reserve(edgeIntervals_.back() + 1);
578 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
579 std::vector<std::vector<SimplexId>> localEdgeStars;
580 ImplicitCluster *exnode = searchCache(nid);
581 if(exnode->edgeStars_.empty()) {
582 getClusterEdgeStars(exnode);
583 }
584 exnode->edgeStars_.copyTo(localEdgeStars);
585 edgeStarList_.insert(
586 edgeStarList_.end(), localEdgeStars.begin(), localEdgeStars.end());
587 }
588 return &edgeStarList_;
589 }
590
591 inline int getEdgeTriangleInternal(const SimplexId &edgeId,
592 const int &localTriangleId,
593 SimplexId &triangleId) const override {
594
595#ifndef TTK_ENABLE_KAMIKAZE
596 if((edgeId < 0) || (edgeId > (SimplexId)edgeIntervals_.back())) {
597 triangleId = -1;
598 return 0;
599 }
600 if(localTriangleId < 0) {
601 triangleId = -2;
602 return 0;
603 }
604#endif
605
606 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
607 const SimplexId localEdgeId = edgeId - edgeIntervals_[nid - 1] - 1;
608 ImplicitCluster *exnode = searchCache(nid);
609 if(exnode->edgeTriangles_.empty()) {
611 }
612
613 if(localTriangleId >= exnode->edgeTriangles_.size(localEdgeId)) {
614 triangleId = -2;
615 } else {
616 triangleId = exnode->edgeTriangles_.get(localEdgeId, localTriangleId);
617 }
618 return 0;
619 }
620
621 inline SimplexId
622 getEdgeTriangleNumberInternal(const SimplexId &edgeId) const override {
623
624#ifndef TTK_ENABLE_KAMIKAZE
625 if((edgeId < 0) || (edgeId > (SimplexId)edgeIntervals_.back()))
626 return -1;
627#endif
628
629 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
630 const SimplexId localEdgeId = edgeId - edgeIntervals_[nid - 1] - 1;
631 ImplicitCluster *exnode = searchCache(nid);
632 if(exnode->edgeTriangles_.empty()) {
634 }
635 return exnode->edgeTriangles_.size(localEdgeId);
636 }
637
638 inline const std::vector<std::vector<SimplexId>> *
640 edgeTriangleList_.reserve(edgeIntervals_.back() + 1);
641 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
642 std::vector<std::vector<SimplexId>> localEdgeTriangles;
643 ImplicitCluster *exnode = searchCache(nid);
644 if(exnode->edgeTriangles_.empty()) {
646 }
647 exnode->edgeTriangles_.copyTo(localEdgeTriangles);
649 localEdgeTriangles.begin(),
650 localEdgeTriangles.end());
651 }
652 return &edgeTriangleList_;
653 }
654
655 inline int getEdgeVertexInternal(const SimplexId &edgeId,
656 const int &localVertexId,
657 SimplexId &vertexId) const override {
658
659#ifndef TTK_ENABLE_KAMIKAZE
660 if((edgeId < 0) || (edgeId > (SimplexId)edgeIntervals_.back())) {
661 vertexId = -1;
662 return 0;
663 }
664 if((localVertexId != 0) && (localVertexId != 1)) {
665 vertexId = -2;
666 return 0;
667 }
668#endif
669
670 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
671 const SimplexId localEdgeId = edgeId - edgeIntervals_[nid - 1] - 1;
672 ImplicitCluster *exnode = searchCache(nid);
673 if(exnode->internalEdgeList_.empty()) {
674 buildInternalEdgeMap(exnode, true, false);
675 }
676
677 if(localVertexId) {
678 vertexId = exnode->internalEdgeList_.at(localEdgeId)[1];
679 } else {
680 vertexId = exnode->internalEdgeList_.at(localEdgeId)[0];
681 }
682 return 0;
683 }
684
685 inline SimplexId
687 return cellNumber_;
688 }
689
690 inline SimplexId getNumberOfEdgesInternal() const override {
691
692#ifndef TTK_ENABLE_KAMIKAZE
693 if(!edgeIntervals_.size())
694 return -1;
695#endif
696
697 return edgeIntervals_.back() + 1;
698 }
699
700 inline SimplexId getNumberOfTrianglesInternal() const override {
701
702#ifndef TTK_ENABLE_KAMIKAZE
703 if(!triangleIntervals_.size())
704 return -1;
705#endif
706
707 return triangleIntervals_.back() + 1;
708 }
709
710 inline SimplexId
712 return vertexNumber_;
713 }
714
715 inline const std::vector<std::array<SimplexId, 3>> *
717 // if it is a triangle mesh
718 if(getDimensionality() == 2) {
719 triangleList_.resize(cellNumber_, std::array<SimplexId, 3>());
720 for(SimplexId cid = 0; cid < cellNumber_; cid++) {
721 triangleList_[cid][0] = cellArray_->getCellVertex(cid, 0);
722 triangleList_[cid][1] = cellArray_->getCellVertex(cid, 1);
723 triangleList_[cid][2] = cellArray_->getCellVertex(cid, 2);
724 }
725 } else {
726 triangleList_.reserve(triangleIntervals_.back() + 1);
727 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
728 ImplicitCluster *exnode = searchCache(nid);
729 if(exnode->internalTriangleList_.empty()) {
730 buildInternalTriangleMap(exnode, true, false);
731 }
732 triangleList_.insert(triangleList_.end(),
733 exnode->internalTriangleList_.begin(),
734 exnode->internalTriangleList_.end());
735 }
736 }
737 return &triangleList_;
738 }
739
740 inline int getTriangleEdgeInternal(const SimplexId &triangleId,
741 const int &localEdgeId,
742 SimplexId &edgeId) const override {
743
744#ifndef TTK_ENABLE_KAMIKAZE
745 if(triangleId < 0 || triangleId > triangleIntervals_.back()) {
746 edgeId = -1;
747 return 0;
748 }
749 if((localEdgeId < 0) || (localEdgeId > 2)) {
750 edgeId = -2;
751 return 0;
752 }
753#endif
754
755 const SimplexId nid = findNodeIndex(triangleId, SIMPLEX_ID::TRIANGLE_ID);
756 const SimplexId localTriangleId
757 = triangleId - triangleIntervals_[nid - 1] - 1;
758 ImplicitCluster *exnode = searchCache(nid);
759 if(exnode->triangleEdges_.empty()) {
761 }
762 edgeId = (exnode->triangleEdges_)[localTriangleId][localEdgeId];
763 return 0;
764 }
765
767 const SimplexId &triangleId) const override {
768#ifndef TTK_ENABLE_KAMIKAZE
769 if((triangleId < 0) || (triangleId > triangleIntervals_.back()))
770 return -1;
771#endif
772
773 (void)triangleId;
774 return 3;
775 }
776
777 inline const std::vector<std::vector<SimplexId>> *
779 if(triangleEdgeVector_.empty()) {
780 triangleEdgeVector_.reserve(triangleIntervals_.size() + 1);
781 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
782 ImplicitCluster *exnode = searchCache(nid);
783 if(exnode->triangleEdges_.empty()) {
785 }
786 for(size_t i = 0; i < exnode->triangleEdges_.size(); i++) {
787 triangleEdgeVector_.emplace_back(
788 exnode->triangleEdges_.at(i).begin(),
789 exnode->triangleEdges_.at(i).end());
790 }
791 }
792 }
793 return &triangleEdgeVector_;
794 }
795
797 const SimplexId &triangleId,
798 const int &localLinkId,
799 SimplexId &linkId) const override {
800
801#ifndef TTK_ENABLE_KAMIKAZE
802 if((triangleId < 0) || (triangleId > triangleIntervals_.back())) {
803 linkId = -1;
804 return 0;
805 }
806 if(localLinkId < 0) {
807 linkId = -2;
808 return 0;
809 }
810#endif
811
812 const SimplexId nid = findNodeIndex(triangleId, SIMPLEX_ID::TRIANGLE_ID);
813 const SimplexId localTriangleId
814 = triangleId - triangleIntervals_[nid - 1] - 1;
815 ImplicitCluster *exnode = searchCache(nid);
816 if(exnode->triangleLinks_.empty()) {
818 }
819
820 if(localLinkId >= exnode->triangleLinks_.size(localTriangleId)) {
821 linkId = -2;
822 } else {
823 linkId = exnode->triangleLinks_.get(localTriangleId, localLinkId);
824 }
825 return 0;
826 }
827
829 const SimplexId &triangleId) const override {
830
831#ifndef TTK_ENABLE_KAMIKAZE
832 if((triangleId < 0) || (triangleId > triangleIntervals_.back()))
833 return -1;
834#endif
835
836 const SimplexId nid = findNodeIndex(triangleId, SIMPLEX_ID::TRIANGLE_ID);
837 const SimplexId localTriangleId
838 = triangleId - triangleIntervals_[nid - 1] - 1;
839 ImplicitCluster *exnode = searchCache(nid);
840 if(exnode->triangleLinks_.empty()) {
842 }
843 return exnode->triangleLinks_.size(localTriangleId);
844 }
845
846 inline const std::vector<std::vector<SimplexId>> *
848 triangleLinkList_.reserve(triangleIntervals_.back() + 1);
849 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
850 std::vector<std::vector<SimplexId>> localTriangleLinks;
851 ImplicitCluster *exnode = searchCache(nid);
852 if(exnode->triangleLinks_.empty()) {
854 }
855 exnode->triangleLinks_.copyTo(localTriangleLinks);
857 localTriangleLinks.begin(),
858 localTriangleLinks.end());
859 }
860 return &triangleLinkList_;
861 }
862
864 const SimplexId &triangleId,
865 const int &localStarId,
866 SimplexId &starId) const override {
867
868#ifndef TTK_ENABLE_KAMIKAZE
869 if((triangleId < 0) || !triangleIntervals_.size()
870 || (triangleId > triangleIntervals_.back())) {
871 starId = -1;
872 return 0;
873 }
874 if(localStarId < 0) {
875 starId = -2;
876 return 0;
877 }
878#endif
879
880 const SimplexId nid = findNodeIndex(triangleId, SIMPLEX_ID::TRIANGLE_ID);
881 const SimplexId localTriangleId
882 = triangleId - triangleIntervals_[nid - 1] - 1;
883 ImplicitCluster *exnode = searchCache(nid);
884 if(exnode->triangleStars_.empty()) {
886 }
887
888 if(localStarId >= exnode->triangleStars_.size(localTriangleId)) {
889 starId = -2;
890 } else {
891 starId = exnode->triangleStars_.get(localTriangleId, localStarId);
892 }
893 return 0;
894 }
895
897 const SimplexId &triangleId) const override {
898
899#ifndef TTK_ENABLE_KAMIKAZE
900 if((triangleId < 0) || !triangleIntervals_.size()
901 || (triangleId > triangleIntervals_.back()))
902 return -1;
903#endif
904
905 const SimplexId nid = findNodeIndex(triangleId, SIMPLEX_ID::TRIANGLE_ID);
906 const SimplexId localTriangleId
907 = triangleId - triangleIntervals_[nid - 1] - 1;
908 ImplicitCluster *exnode = searchCache(nid);
909 if(exnode->triangleStars_.empty()) {
911 }
912 return exnode->triangleStars_.size(localTriangleId);
913 }
914
915 inline const std::vector<std::vector<SimplexId>> *
917 triangleStarList_.reserve(triangleIntervals_.back() + 1);
918 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
919 std::vector<std::vector<SimplexId>> localTriangleStars;
920 ImplicitCluster *exnode = searchCache(nid);
921 if(exnode->triangleStars_.empty()) {
923 }
925 localTriangleStars.begin(),
926 localTriangleStars.end());
927 }
928 return &triangleStarList_;
929 }
930
931 inline int getTriangleVertexInternal(const SimplexId &triangleId,
932 const int &localVertexId,
933 SimplexId &vertexId) const override {
934
935#ifndef TTK_ENABLE_KAMIKAZE
936 if((triangleId < 0) || (triangleId > triangleIntervals_.back())) {
937 vertexId = -1;
938 return 0;
939 }
940 if((localVertexId < 0) || (localVertexId > 2)) {
941 vertexId = -2;
942 return 0;
943 }
944#endif
945
946 const SimplexId nid = findNodeIndex(triangleId, SIMPLEX_ID::TRIANGLE_ID);
947 const SimplexId localTriangleId
948 = triangleId - triangleIntervals_[nid - 1] - 1;
949 ImplicitCluster *exnode = searchCache(nid);
950 if(exnode->internalTriangleList_.empty()) {
951 buildInternalTriangleMap(exnode, true, false);
952 }
953 vertexId
954 = exnode->internalTriangleList_.at(localTriangleId)[localVertexId];
955 return 0;
956 }
957
958 inline int getVertexEdgeInternal(const SimplexId &vertexId,
959 const int &localEdgeId,
960 SimplexId &edgeId) const override {
961
962#ifndef TTK_ENABLE_KAMIKAZE
963 if((vertexId < 0) || (vertexId >= vertexNumber_)) {
964 edgeId = -1;
965 return 0;
966 }
967 if(localEdgeId < 0) {
968 edgeId = -1;
969 return 0;
970 }
971#endif
972
973 const SimplexId nid = vertexIndices_[vertexId];
974 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
975 ImplicitCluster *exnode = searchCache(nid);
976 if(exnode->vertexEdges_.empty()) {
977 getClusterVertexEdges(exnode);
978 }
979 if(localEdgeId >= exnode->vertexEdges_.size(localVertexId)) {
980 edgeId = -2;
981 } else {
982 edgeId = exnode->vertexEdges_.get(localVertexId, localEdgeId);
983 }
984 return 0;
985 }
986
987 inline SimplexId
988 getVertexEdgeNumberInternal(const SimplexId &vertexId) const override {
989
990#ifndef TTK_ENABLE_KAMIKAZE
991 if((vertexId < 0) || (vertexId >= vertexNumber_))
992 return -1;
993#endif
994
995 const SimplexId nid = vertexIndices_[vertexId];
996 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
997 ImplicitCluster *exnode = searchCache(nid);
998 if(exnode->vertexEdges_.empty()) {
999 getClusterVertexEdges(exnode);
1000 }
1001 return exnode->vertexEdges_.size(localVertexId);
1002 }
1003
1004 inline const std::vector<std::vector<SimplexId>> *
1007 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1008 std::vector<std::vector<SimplexId>> localVertexEdges;
1009 ImplicitCluster *exnode = searchCache(nid);
1010 if(exnode->vertexEdges_.empty()) {
1011 getClusterVertexEdges(exnode);
1012 }
1013 exnode->vertexEdges_.copyTo(localVertexEdges);
1014 vertexEdgeList_.insert(vertexEdgeList_.end(), localVertexEdges.begin(),
1015 localVertexEdges.end());
1016 }
1017
1018 return &vertexEdgeList_;
1019 }
1020
1022 const SimplexId &vertexId,
1023 const int &localLinkId,
1024 SimplexId &linkId) const override {
1025
1026#ifndef TTK_ENABLE_KAMIKAZE
1027 if((vertexId < 0) || (vertexId > vertexIntervals_.back())) {
1028 linkId = -1;
1029 return 0;
1030 }
1031 if(localLinkId < 0) {
1032 linkId = -2;
1033 return 0;
1034 }
1035#endif
1036
1037 const SimplexId nid = vertexIndices_[vertexId];
1038 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1039 ImplicitCluster *exnode = searchCache(nid);
1040 if(exnode->vertexLinks_.empty()) {
1041 getClusterVertexLinks(exnode);
1042 }
1043 if(localLinkId >= exnode->vertexLinks_.size(localVertexId)) {
1044 linkId = -2;
1045 } else {
1046 linkId = exnode->vertexLinks_.get(localVertexId, localLinkId);
1047 }
1048 return 0;
1049 }
1050
1052 const SimplexId &vertexId) const override {
1053
1054#ifndef TTK_ENABLE_KAMIKAZE
1055 if((vertexId < 0) || (vertexId > vertexIntervals_.back()))
1056 return -1;
1057#endif
1058
1059 const SimplexId nid = vertexIndices_[vertexId];
1060 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1061 ImplicitCluster *exnode = searchCache(nid);
1062 if(exnode->vertexLinks_.empty()) {
1063 getClusterVertexLinks(exnode);
1064 }
1065 return exnode->vertexLinks_.size(localVertexId);
1066 }
1067
1068 inline const std::vector<std::vector<SimplexId>> *
1070 vertexLinkList_.reserve(vertexIntervals_.back() + 1);
1071 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1072 std::vector<std::vector<SimplexId>> localVertexLinks;
1073 ImplicitCluster *exnode = searchCache(nid);
1074 if(exnode->vertexLinks_.empty()) {
1075 getClusterVertexLinks(exnode);
1076 }
1077 exnode->vertexLinks_.copyTo(localVertexLinks);
1078 vertexLinkList_.insert(vertexLinkList_.end(), localVertexLinks.begin(),
1079 localVertexLinks.end());
1080 }
1081 return &vertexLinkList_;
1082 }
1083
1085 const SimplexId &vertexId,
1086 const int &localNeighborId,
1087 SimplexId &neighborId) const override {
1088#ifndef TTK_ENABLE_KAMIKAZE
1089 if((vertexId < 0) || (vertexId >= vertexNumber_)) {
1090 neighborId = -1;
1091 return 0;
1092 }
1093 if(localNeighborId < 0) {
1094 neighborId = -2;
1095 return 0;
1096 }
1097#endif
1098
1099 const SimplexId nid = vertexIndices_[vertexId];
1100 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1101 ImplicitCluster *exnode = searchCache(nid);
1102 if(exnode == nullptr) {
1103 return -1;
1104 }
1105 if(exnode->vertexNeighbors_.empty()) {
1107 }
1108 if(localNeighborId >= exnode->vertexNeighbors_.size(localVertexId)) {
1109 neighborId = -2;
1110 } else {
1111 neighborId
1112 = exnode->vertexNeighbors_.get(localVertexId, localNeighborId);
1113 }
1114 return 0;
1115 }
1116
1118 const SimplexId &vertexId) const override {
1119
1120#ifndef TTK_ENABLE_KAMIKAZE
1121 if((vertexId < 0) || (vertexId >= vertexNumber_))
1122 return -1;
1123#endif
1124
1125 const SimplexId nid = vertexIndices_[vertexId];
1126 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1127 ImplicitCluster *exnode = searchCache(nid);
1128 if(exnode->vertexNeighbors_.empty()) {
1130 }
1131 return exnode->vertexNeighbors_.size(localVertexId);
1132 }
1133
1134 inline const std::vector<std::vector<SimplexId>> *
1137 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1138 std::vector<std::vector<SimplexId>> localVertexNeighbors;
1139 ImplicitCluster *exnode = searchCache(nid);
1140 if(exnode->vertexNeighbors_.empty()) {
1142 }
1143 exnode->vertexNeighbors_.copyTo(localVertexNeighbors);
1145 localVertexNeighbors.begin(),
1146 localVertexNeighbors.end());
1147 }
1148 return &vertexNeighborList_;
1149 }
1150
1152 const SimplexId &vertexId, float &x, float &y, float &z) const override {
1153
1154#ifndef TTK_ENABLE_KAMIKAZE
1155 if((vertexId < 0) || (vertexId >= vertexNumber_))
1156 return -1;
1157#endif
1158
1159 if(doublePrecision_) {
1160 x = ((const double *)pointSet_)[3 * vertexId];
1161 y = ((const double *)pointSet_)[3 * vertexId + 1];
1162 z = ((const double *)pointSet_)[3 * vertexId + 2];
1163 } else {
1164 x = ((const float *)pointSet_)[3 * vertexId];
1165 y = ((const float *)pointSet_)[3 * vertexId + 1];
1166 z = ((const float *)pointSet_)[3 * vertexId + 2];
1167 }
1168
1169 return 0;
1170 }
1171
1173 const SimplexId &vertexId,
1174 const int &localStarId,
1175 SimplexId &starId) const override {
1176
1177#ifndef TTK_ENABLE_KAMIKAZE
1178 if((vertexId < 0) || (vertexId >= vertexNumber_)) {
1179 starId = -1;
1180 return 0;
1181 }
1182 if(localStarId < 0) {
1183 starId = -2;
1184 return 0;
1185 }
1186#endif
1187
1188 const SimplexId nid = vertexIndices_[vertexId];
1189 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1190 ImplicitCluster *exnode = searchCache(nid);
1191 if(exnode->vertexStars_.empty()) {
1192 getClusterVertexStars(exnode);
1193 }
1194 if(localStarId >= exnode->vertexStars_.size(localVertexId)) {
1195 starId = -2;
1196 } else {
1197 starId = exnode->vertexStars_.get(localVertexId, localStarId);
1198 }
1199 return 0;
1200 }
1201
1203 const SimplexId &vertexId) const override {
1204
1205#ifndef TTK_ENABLE_KAMIKAZE
1206 if((vertexId < 0) || (vertexId >= vertexNumber_))
1207 return -1;
1208#endif
1209
1210 const SimplexId nid = vertexIndices_[vertexId];
1211 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1212 ImplicitCluster *exnode = searchCache(nid);
1213 if(exnode->vertexStars_.empty()) {
1214 getClusterVertexStars(exnode);
1215 }
1216 return exnode->vertexStars_.size(localVertexId);
1217 }
1218
1219 inline const std::vector<std::vector<SimplexId>> *
1222 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1223 std::vector<std::vector<SimplexId>> localVertexStars;
1224 ImplicitCluster *exnode = searchCache(nid);
1225 if(exnode->vertexStars_.empty()) {
1226 getClusterVertexStars(exnode);
1227 }
1228 exnode->vertexStars_.copyTo(localVertexStars);
1229 vertexStarList_.insert(vertexStarList_.end(), localVertexStars.begin(),
1230 localVertexStars.end());
1231 }
1232 return &vertexStarList_;
1233 }
1234
1235 inline int getVertexTriangleInternal(const SimplexId &vertexId,
1236 const int &localTriangleId,
1237 SimplexId &triangleId) const override {
1238
1239#ifndef TTK_ENABLE_KAMIKAZE
1240 if((vertexId < 0) || (vertexId >= vertexNumber_)) {
1241 triangleId = -1;
1242 return 0;
1243 }
1244 if(localTriangleId < 0) {
1245 triangleId = -2;
1246 return 0;
1247 }
1248#endif
1249
1250 const SimplexId nid = vertexIndices_[vertexId];
1251 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1252 ImplicitCluster *exnode = searchCache(nid);
1253 if(exnode->vertexTriangles_.empty()) {
1255 }
1256 if(localTriangleId >= exnode->vertexTriangles_.size(localVertexId)) {
1257 triangleId = -2;
1258 } else {
1259 triangleId
1260 = exnode->vertexTriangles_.get(localVertexId, localTriangleId);
1261 }
1262 return 0;
1263 }
1264
1266 const SimplexId &vertexId) const override {
1267
1268#ifndef TTK_ENABLE_KAMIKAZE
1269 if((vertexId < 0) || (vertexId >= vertexNumber_))
1270 return -1;
1271#endif
1272
1273 const SimplexId nid = vertexIndices_[vertexId];
1274 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1275 ImplicitCluster *exnode = searchCache(nid);
1276 if(exnode->vertexTriangles_.empty()) {
1278 }
1279 return exnode->vertexTriangles_.size(localVertexId);
1280 }
1281
1282 inline const std::vector<std::vector<SimplexId>> *
1285 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1286 std::vector<std::vector<SimplexId>> localVertexTriangles;
1287 ImplicitCluster *exnode = searchCache(nid);
1288 if(exnode->vertexTriangles_.empty()) {
1290 }
1291 exnode->vertexTriangles_.copyTo(localVertexTriangles);
1293 localVertexTriangles.begin(),
1294 localVertexTriangles.end());
1295 }
1296 return &vertexTriangleList_;
1297 }
1298
1300 const SimplexId &edgeId) const override {
1301#ifndef TTK_ENABLE_KAMIKAZE
1302 if((edgeId < 0) || (edgeId > edgeIntervals_.back()))
1303 return false;
1304#endif
1305 const SimplexId nid = findNodeIndex(edgeId, SIMPLEX_ID::EDGE_ID);
1306 const SimplexId localedgeId = edgeId - edgeIntervals_[nid - 1] - 1;
1307 ImplicitCluster *exnode = searchCache(nid);
1308 getBoundaryCells(exnode, 1);
1309 return (exnode->boundaryEdges_)[localedgeId];
1310 }
1311
1312 bool isEmpty() const override {
1313 return !vertexNumber_;
1314 }
1315
1317 const SimplexId &triangleId) const override {
1318 if(getDimensionality() == 2)
1319 return false;
1320
1321#ifndef TTK_ENABLE_KAMIKAZE
1322 if((triangleId < 0) || (triangleId > triangleIntervals_.back()))
1323 return false;
1324#endif
1325 const SimplexId nid = findNodeIndex(triangleId, SIMPLEX_ID::TRIANGLE_ID);
1326 const SimplexId localtriangleId
1327 = triangleId - triangleIntervals_[nid - 1] - 1;
1328 ImplicitCluster *exnode = searchCache(nid);
1329 getBoundaryCells(exnode);
1330 return (exnode->boundaryTriangles_)[localtriangleId];
1331 }
1332
1334 const SimplexId &vertexId) const override {
1335#ifndef TTK_ENABLE_KAMIKAZE
1336 if((vertexId < 0) || (vertexId >= vertexNumber_))
1337 return false;
1338#endif
1339 const SimplexId nid = vertexIndices_[vertexId];
1340 const SimplexId localVertexId = vertexId - vertexIntervals_[nid - 1] - 1;
1341 ImplicitCluster *exnode = searchCache(nid);
1342 getBoundaryCells(exnode, 0);
1343 return (exnode->boundaryVertices_)[localVertexId];
1344 }
1345
1347 return 0;
1348 }
1349
1351 return 0;
1352 }
1353
1355 if(getDimensionality() == 2) {
1357 } else if(getDimensionality() == 3) {
1359 }
1360 return 0;
1361 }
1362
1363 inline int preconditionCellEdgesInternal() override {
1364 return 0;
1365 }
1366
1368 return 0;
1369 }
1370
1372 return 0;
1373 }
1374
1375 inline int preconditionEdgesInternal() override {
1376
1377#ifndef TTK_ENABLE_KAMIKAZE
1378 if(vertexNumber_ <= 0)
1379 return -1;
1380 if(cellNumber_ <= 0)
1381 return -2;
1382 if(!cellArray_)
1383 return -3;
1384 if(nodeNumber_ <= 0)
1385 return -4;
1386#endif
1387
1388 if(edgeIntervals_.empty()) {
1389 Timer t;
1390 edgeIntervals_.resize(nodeNumber_ + 1);
1391 edgeIntervals_[0] = -1;
1392 std::vector<SimplexId> edgeCount(nodeNumber_ + 1);
1393
1394#ifdef TTK_ENABLE_OPENMP
1395#pragma omp parallel for num_threads(threadNumber_)
1396#endif
1397 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1398 edgeCount[nid] = countInternalEdges(nid);
1399 }
1400
1401 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1402 edgeIntervals_[nid] = edgeIntervals_[nid - 1] + edgeCount[nid];
1403 }
1404
1405 this->printMsg("Edges preconditioned in "
1406 + std::to_string(t.getElapsedTime()) + " s.");
1407 }
1408
1409 return 0;
1410 }
1411
1412 inline int preconditionEdgeLinksInternal() override {
1413 return 0;
1414 }
1415
1416 inline int preconditionEdgeStarsInternal() override {
1417 return 0;
1418 }
1419
1421 return 0;
1422 }
1423
1424 inline int preconditionTrianglesInternal() override {
1425#ifndef TTK_ENABLE_KAMIKAZE
1426 if(vertexNumber_ <= 0)
1427 return -1;
1428 if(cellNumber_ <= 0)
1429 return -2;
1430 if(!cellArray_)
1431 return -3;
1432 if(nodeNumber_ <= 0)
1433 return -4;
1434#endif
1435
1436 // build triangle interval list
1437 if(triangleIntervals_.empty()) {
1438 Timer t;
1439 triangleIntervals_.resize(nodeNumber_ + 1);
1440 triangleIntervals_[0] = -1;
1441 std::vector<SimplexId> triangleCount(nodeNumber_ + 1);
1442#ifdef TTK_ENABLE_OPENMP
1443#pragma omp parallel for num_threads(threadNumber_)
1444#endif
1445 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1446 triangleCount[nid] = countInternalTriangles(nid);
1447 }
1448
1449 for(SimplexId nid = 1; nid <= nodeNumber_; nid++) {
1451 = triangleIntervals_[nid - 1] + triangleCount[nid];
1452 }
1453
1454 this->printMsg("Triangles preconditioned in "
1455 + std::to_string(t.getElapsedTime()) + " s.");
1456 }
1457
1458 return 0;
1459 }
1460
1462 return 0;
1463 }
1464
1466 return 0;
1467 }
1468
1470 return 0;
1471 }
1472
1473 inline int preconditionVertexEdgesInternal() override {
1474 return 0;
1475 }
1476
1477 inline int preconditionVertexLinksInternal() override {
1478 if(getDimensionality() == 2) {
1480 } else if(getDimensionality() == 3) {
1482 } else {
1483 this->printErr("Unsupported dimension for vertex link precondition");
1484 return -1;
1485 }
1486 return 0;
1487 }
1488
1490 return 0;
1491 }
1492
1493 inline int preconditionVertexStarsInternal() override {
1494
1495#ifndef TTK_ENABLE_KAMIKAZE
1496 if(!cellArray_)
1497 return -1;
1498#endif
1499
1500 return 0;
1501 }
1502
1504 return 0;
1505 }
1506
1510 inline void initCache(const float ratio = 0.2) {
1511 cacheSize_ = nodeNumber_ * ratio + 1;
1512 caches_.resize(threadNumber_);
1513 cacheMaps_.resize(threadNumber_);
1514 for(int i = 0; i < threadNumber_; i++) {
1515 caches_[i].clear();
1516 cacheMaps_[i].clear();
1517 }
1518 this->printMsg("Initializing cache: " + std::to_string(cacheSize_));
1519 }
1520
1524 inline size_t getCacheSize() {
1525 return cacheSize_;
1526 }
1527
1532 inline int resetCache(int option) {
1533 for(int i = 0; i < threadNumber_; i++) {
1534 caches_[i].clear();
1535 cacheMaps_[i].clear();
1536 }
1537 if(option) {
1538 caches_.resize(1);
1539 cacheMaps_.resize(1);
1541 } else {
1542 caches_.resize(threadNumber_);
1543 cacheMaps_.resize(threadNumber_);
1545 }
1546 return 0;
1547 }
1548
1549 protected:
1550 inline int clear() {
1551 vertexIntervals_.clear();
1552 edgeIntervals_.clear();
1553 triangleIntervals_.clear();
1554 cellIntervals_.clear();
1555 externalCells_.clear();
1556 cacheMaps_.clear();
1557 cacheMaps_.clear();
1559 }
1560
1564 inline SimplexId findNodeIndex(SimplexId id, SIMPLEX_ID idType) const {
1565 const std::vector<SimplexId> *intervals = nullptr;
1566 // determine which vector to search
1567 if(idType == SIMPLEX_ID::EDGE_ID) {
1568 intervals = &edgeIntervals_;
1569 } else if(idType == SIMPLEX_ID::TRIANGLE_ID) {
1570 intervals = &triangleIntervals_;
1571 } else {
1572 return -1;
1573 }
1574
1575 const std::vector<SimplexId>::const_iterator low
1576 = lower_bound(intervals->begin(), intervals->end(), id);
1577 return (low - intervals->begin());
1578 }
1579
1584 const SimplexId reservedId = 0) const {
1585 ThreadId threadId = 0;
1586#ifdef TTK_ENABLE_OPENMP
1587 threadId = omp_get_thread_num();
1588#endif
1589
1590 // cannot find the expanded node in the cache
1591 if(cacheMaps_[threadId].find(nodeId) == cacheMaps_[threadId].end()) {
1592 if(caches_[threadId].size() >= cacheSize_) {
1593 if(caches_[threadId].back().nid == reservedId) {
1594 return nullptr;
1595 }
1596 cacheMaps_[threadId].erase(caches_[threadId].back().nid);
1597 caches_[threadId].pop_back();
1598 }
1599 const ImplicitCluster localCluster(nodeId);
1600 caches_[threadId].emplace_front(localCluster);
1601 cacheMaps_[threadId][nodeId] = caches_[threadId].begin();
1602 }
1603 return &(*cacheMaps_[threadId][nodeId]);
1604 }
1605
1609 int buildInternalEdgeMap(ImplicitCluster *const nodePtr,
1610 bool computeInternalEdgeList,
1611 bool computeInternalEdgeMap) const;
1615 int buildExternalEdgeMap(ImplicitCluster *const nodePtr) const;
1616
1620 int buildInternalTriangleMap(ImplicitCluster *const nodePtr,
1621 bool computeInternalTriangleList,
1622 bool computeInternalTriangleMap) const;
1623
1627 int buildExternalTriangleMap(ImplicitCluster *const nodePtr) const;
1628
1633
1637 int countInternalTriangles(SimplexId nodeId) const;
1638
1642 int getClusterCellNeighbors(ImplicitCluster *const nodePtr) const;
1643
1647 int getClusterCellTriangles(ImplicitCluster *const nodePtr) const;
1648
1652 int getClusterEdgeLinks(ImplicitCluster *const nodePtr) const;
1653
1657 int getClusterEdgeStars(ImplicitCluster *const nodePtr) const;
1658
1662 int getClusterEdgeTriangles(ImplicitCluster *const nodePtr) const;
1663
1668 int getClusterTetraEdges(ImplicitCluster *const nodePtr) const;
1669
1673 int getClusterTriangleEdges(ImplicitCluster *const nodePtr) const;
1674
1678 int getClusterTriangleLinks(ImplicitCluster *const nodePtr) const;
1679
1683 int getClusterTriangleStars(ImplicitCluster *const nodePtr) const;
1684
1688 int getClusterVertexEdges(ImplicitCluster *const nodePtr) const;
1689
1693 int getClusterVertexLinks(ImplicitCluster *const nodePtr) const;
1694
1698 int getClusterVertexNeighbors(ImplicitCluster *const nodePtr) const;
1699
1704 int getClusterVertexStars(ImplicitCluster *const nodePtr) const;
1705
1709 int getClusterVertexTriangles(ImplicitCluster *const nodePtr) const;
1710
1714 int getBoundaryCells(ImplicitCluster *const nodePtr,
1715 const SimplexId dim = 2) const;
1716
1723 const void *pointSet_;
1724 const int *vertexIndices_;
1725 std::vector<SimplexId> vertexIntervals_;
1726 std::vector<SimplexId> edgeIntervals_;
1727 std::vector<SimplexId> triangleIntervals_;
1728 std::vector<SimplexId> cellIntervals_;
1729 std::shared_ptr<CellArray> cellArray_;
1730 std::vector<std::vector<SimplexId>> externalCells_;
1731
1732 // Cache system
1734 mutable std::vector<std::list<ImplicitCluster>> caches_;
1735 mutable std::vector<
1736 boost::unordered_map<SimplexId, std::list<ImplicitCluster>::iterator>>
1738 };
1739} // namespace ttk
#define TTK_TRIANGULATION_INTERNAL(NAME)
long long int idType
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
std::vector< std::vector< SimplexId > > vertexStarList_
std::vector< std::array< SimplexId, 3 > > triangleList_
std::vector< std::vector< SimplexId > > triangleLinkList_
std::vector< std::vector< SimplexId > > vertexNeighborList_
std::vector< std::vector< SimplexId > > vertexLinkList_
std::vector< std::vector< SimplexId > > edgeLinkList_
std::vector< std::vector< SimplexId > > vertexEdgeList_
std::vector< std::vector< SimplexId > > triangleEdgeVector_
std::vector< std::vector< SimplexId > > triangleStarList_
virtual SimplexId getCellTriangleNumber(const SimplexId &cellId) const
std::vector< std::vector< SimplexId > > cellNeighborList_
std::vector< std::array< SimplexId, 2 > > edgeList_
std::vector< std::vector< SimplexId > > edgeStarList_
std::vector< std::vector< SimplexId > > vertexTriangleList_
std::vector< std::vector< SimplexId > > cellEdgeVector_
std::vector< std::vector< SimplexId > > cellTriangleVector_
std::vector< std::vector< SimplexId > > edgeTriangleList_
CompactTriangulation is a class implemented based on the TopoCluster data structure,...
int setInputCells(const SimplexId &cellNumber, const LongSimplexId *cellArray)
SimplexId findNodeIndex(SimplexId id, SIMPLEX_ID idType) const
void initCache(const float ratio=0.2)
int preconditionVertexLinksInternal() override
int TTK_TRIANGULATION_INTERNAL() getCellVertex(const SimplexId &cellId, const int &localVertexId, SimplexId &vertexId) const override
int preconditionBoundaryTrianglesInternal() override
int TTK_TRIANGULATION_INTERNAL() getTriangleLink(const SimplexId &triangleId, const int &localLinkId, SimplexId &linkId) const override
const std::vector< std::vector< SimplexId > > * getCellEdgesInternal() override
SimplexId getVertexEdgeNumberInternal(const SimplexId &vertexId) const override
int getClusterEdgeStars(ImplicitCluster *const nodePtr) const
int getClusterVertexTriangles(ImplicitCluster *const nodePtr) const
int preconditionBoundaryVerticesInternal() override
SimplexId TTK_TRIANGULATION_INTERNAL() getNumberOfCells() const override
~CompactTriangulation() override
SimplexId getCellTriangleNumberInternal(const SimplexId &cellId) const override
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getVertexLinks() override
int getTriangleVertexInternal(const SimplexId &triangleId, const int &localVertexId, SimplexId &vertexId) const override
SimplexId getCellEdgeNumberInternal(const SimplexId &cellId) const override
SimplexId getEdgeTriangleNumberInternal(const SimplexId &edgeId) const override
int getClusterVertexStars(ImplicitCluster *const nodePtr) const
int getClusterTriangleStars(ImplicitCluster *const nodePtr) const
CompactTriangulation & operator=(const CompactTriangulation &rhs)
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getCellNeighbors() override
int TTK_TRIANGULATION_INTERNAL() getVertexLink(const SimplexId &vertexId, const int &localLinkId, SimplexId &linkId) const override
SimplexId TTK_TRIANGULATION_INTERNAL() getCellNeighborNumber(const SimplexId &cellId) const override
SimplexId getVertexTriangleNumberInternal(const SimplexId &vertexId) const override
SimplexId TTK_TRIANGULATION_INTERNAL() getCellVertexNumber(const SimplexId &cellId) const override
int TTK_TRIANGULATION_INTERNAL() getEdgeLink(const SimplexId &edgeId, const int &localLinkId, SimplexId &linkId) const override
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getTriangleStars() override
const std::vector< std::array< SimplexId, 2 > > *TTK_TRIANGULATION_INTERNAL() getEdges() override
const std::vector< std::vector< SimplexId > > * getCellTrianglesInternal() override
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getVertexNeighbors() override
SimplexId TTK_TRIANGULATION_INTERNAL() getVertexLinkNumber(const SimplexId &vertexId) const override
int preconditionCellTrianglesInternal() override
std::vector< std::vector< SimplexId > > externalCells_
int TTK_TRIANGULATION_INTERNAL() getVertexNeighbor(const SimplexId &vertexId, const int &localNeighborId, SimplexId &neighborId) const override
int getEdgeVertexInternal(const SimplexId &edgeId, const int &localVertexId, SimplexId &vertexId) const override
int getVertexTriangleInternal(const SimplexId &vertexId, const int &localTriangleId, SimplexId &triangleId) const override
std::vector< SimplexId > cellIntervals_
int countInternalTriangles(SimplexId nodeId) const
int preconditionTriangleEdgesInternal() override
int getClusterTriangleEdges(ImplicitCluster *const nodePtr) const
CompactTriangulation & operator=(CompactTriangulation &&rhs)=default
int getClusterCellTriangles(ImplicitCluster *const nodePtr) const
SimplexId TTK_TRIANGULATION_INTERNAL() getNumberOfVertices() const override
int getBoundaryCells(ImplicitCluster *const nodePtr, const SimplexId dim=2) const
std::vector< boost::unordered_map< SimplexId, std::list< ImplicitCluster >::iterator > > cacheMaps_
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getVertexStars() override
int buildInternalTriangleMap(ImplicitCluster *const nodePtr, bool computeInternalTriangleList, bool computeInternalTriangleMap) const
int getClusterVertexNeighbors(ImplicitCluster *const nodePtr) const
int getClusterVertexEdges(ImplicitCluster *const nodePtr) const
const std::vector< std::vector< SimplexId > > * getTriangleEdgesInternal() override
SimplexId TTK_TRIANGULATION_INTERNAL() getEdgeLinkNumber(const SimplexId &edgeId) const override
std::vector< SimplexId > vertexIntervals_
int getCellTriangleInternal(const SimplexId &cellId, const int &localTriangleId, SimplexId &triangleId) const override
CompactTriangulation(CompactTriangulation &&rhs)=default
int getTriangleEdgeInternal(const SimplexId &triangleId, const int &localEdgeId, SimplexId &edgeId) const override
int TTK_TRIANGULATION_INTERNAL() getVertexStar(const SimplexId &vertexId, const int &localStarId, SimplexId &starId) const override
const std::vector< std::vector< SimplexId > > * getVertexTrianglesInternal() override
int getClusterEdgeLinks(ImplicitCluster *const nodePtr) const
int preconditionVertexStarsInternal() override
bool TTK_TRIANGULATION_INTERNAL() isTriangleOnBoundary(const SimplexId &triangleId) const override
int buildInternalEdgeMap(ImplicitCluster *const nodePtr, bool computeInternalEdgeList, bool computeInternalEdgeMap) const
int getClusterVertexLinks(ImplicitCluster *const nodePtr) const
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getEdgeLinks() override
int preconditionBoundaryEdgesInternal() override
int getVertexEdgeInternal(const SimplexId &vertexId, const int &localEdgeId, SimplexId &edgeId) const override
int preconditionCellNeighborsInternal() override
const std::vector< std::vector< SimplexId > > * getVertexEdgesInternal() override
std::vector< SimplexId > edgeIntervals_
int getEdgeTriangleInternal(const SimplexId &edgeId, const int &localTriangleId, SimplexId &triangleId) const override
int reorderVertices(std::vector< SimplexId > &vertexMap)
SimplexId TTK_TRIANGULATION_INTERNAL() getTriangleLinkNumber(const SimplexId &triangleId) const override
bool TTK_TRIANGULATION_INTERNAL() isEdgeOnBoundary(const SimplexId &edgeId) const override
int TTK_TRIANGULATION_INTERNAL() getCellNeighbor(const SimplexId &cellId, const int &localNeighborId, SimplexId &neighborId) const override
int preconditionTriangleLinksInternal() override
SimplexId TTK_TRIANGULATION_INTERNAL() getTriangleStarNumber(const SimplexId &triangleId) const override
int reorderCells(const std::vector< SimplexId > &vertexMap, const SimplexId &cellNumber, const LongSimplexId *connectivity, const LongSimplexId *offset)
SimplexId countInternalEdges(SimplexId nodeId) const
int getClusterEdgeTriangles(ImplicitCluster *const nodePtr) const
int preconditionTriangleStarsInternal() override
std::shared_ptr< CellArray > cellArray_
int preconditionVertexTrianglesInternal() override
SimplexId getTriangleEdgeNumberInternal(const SimplexId &triangleId) const override
SimplexId TTK_TRIANGULATION_INTERNAL() getVertexStarNumber(const SimplexId &vertexId) const override
std::vector< SimplexId > triangleIntervals_
int buildExternalEdgeMap(ImplicitCluster *const nodePtr) const
const std::vector< std::array< SimplexId, 3 > > *TTK_TRIANGULATION_INTERNAL() getTriangles() override
int setInputPoints(const SimplexId &pointNumber, const void *pointSet, const int *indexArray, const bool &doublePrecision=false)
int getCellEdgeInternal(const SimplexId &cellId, const int &localEdgeId, SimplexId &edgeId) const override
SimplexId TTK_TRIANGULATION_INTERNAL() getEdgeStarNumber(const SimplexId &edgeId) const override
int preconditionEdgeTrianglesInternal() override
int getClusterCellNeighbors(ImplicitCluster *const nodePtr) const
int TTK_TRIANGULATION_INTERNAL() getVertexPoint(const SimplexId &vertexId, float &x, float &y, float &z) const override
int preconditionVertexEdgesInternal() override
SimplexId getNumberOfTrianglesInternal() const override
int preconditionVertexNeighborsInternal() override
SimplexId getNumberOfEdgesInternal() const override
int getClusterTriangleLinks(ImplicitCluster *const nodePtr) const
std::vector< std::list< ImplicitCluster > > caches_
ImplicitCluster * searchCache(const SimplexId &nodeId, const SimplexId reservedId=0) const
SimplexId TTK_TRIANGULATION_INTERNAL() getVertexNeighborNumber(const SimplexId &vertexId) const override
int TTK_TRIANGULATION_INTERNAL() getDimensionality() const override
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getTriangleLinks() override
int buildExternalTriangleMap(ImplicitCluster *const nodePtr) const
int TTK_TRIANGULATION_INTERNAL() getTriangleStar(const SimplexId &triangleId, const int &localStarId, SimplexId &starId) const override
const std::vector< std::vector< SimplexId > > * getEdgeTrianglesInternal() override
int getClusterTetraEdges(ImplicitCluster *const nodePtr) const
const std::vector< std::vector< SimplexId > > *TTK_TRIANGULATION_INTERNAL() getEdgeStars() override
bool TTK_TRIANGULATION_INTERNAL() isVertexOnBoundary(const SimplexId &vertexId) const override
int TTK_TRIANGULATION_INTERNAL() getEdgeStar(const SimplexId &edgeId, const int &localStarId, SimplexId &starId) const override
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
Definition Debug.h:149
Replacement for std::vector<std::vector<SimplexId>>
void copyTo(std::vector< std::vector< SimplexId > > &dst, int threadNumber=1) const
Copy buffers to a std::vector<std::vector<SimplexId>>
SimplexId get(SimplexId id, SimplexId local) const
Returns the data inside the sub-vectors.
SimplexId size(SimplexId id) const
Get the size of a particular sub-vector.
bool empty() const
If the underlying buffers are empty.
ImplicitCluster()=default
~ImplicitCluster()=default
double getElapsedTime()
Definition Timer.h:15
The Topology ToolKit.
long long int LongSimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:15
int ThreadId
Identifier type for threads (i.e. with OpenMP).
Definition DataTypes.h:26
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
T end(std::pair< T, T > &p)
Definition ripserpy.cpp:483
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)