TTK
Loading...
Searching...
No Matches
MandatoryCriticalPoints.h
Go to the documentation of this file.
1
30
31#pragma once
32
33// base code includes
34#include <ContourTree.h>
36#include <Triangulation.h>
37
38// std includes
39#include <queue>
40#include <vector>
41
42namespace ttk {
43
44 class Graph : virtual public Debug {
45 public:
46 class Vertex {
47 friend class Graph;
48
49 public:
50 inline int getNumberOfEdges() const {
51 return (int)edgeIdx_.size();
52 }
53 inline int getEdgeIdx(const int &connectedEdge) const {
54 if(connectedEdge < (int)edgeIdx_.size())
55 return edgeIdx_[connectedEdge];
56 else
57 return -1;
58 }
59
60 protected:
61 std::vector<int> edgeIdx_{};
62 };
63 class Edge {
64 friend class Graph;
65
66 public:
67 Edge(const int &start, const int &end) {
68 vertexIdx_.first = start;
69 vertexIdx_.second = end;
70 }
71 const std::pair<int, int> &getVertexIdx() const {
72 return vertexIdx_;
73 }
74
75 protected:
76 std::pair<int, int> vertexIdx_{};
77 };
78
79 public:
80 inline int getNumberOfVertices() const {
81 return (int)vertexList_.size();
82 }
83 inline int getNumberOfEdges() const {
84 return (int)edgeList_.size();
85 }
87 int addVertex() {
88 Vertex newVertex;
89 vertexList_.push_back(newVertex);
90 return (int)vertexList_.size() - 1;
91 }
93 const Vertex &getVertex(const int idx) const {
94 return vertexList_[idx];
95 }
97 int addEdge(const int &start, const int &end) {
98 if((start < (int)vertexList_.size()) && (end < (int)vertexList_.size())) {
99 Edge newEdge(start, end);
100 edgeList_.push_back(newEdge);
101 vertexList_[start].edgeIdx_.push_back(edgeList_.size() - 1);
102 vertexList_[end].edgeIdx_.push_back(edgeList_.size() - 1);
103 return (int)edgeList_.size() - 1;
104 } else
105 return -1;
106 }
109 const Edge &getEdge(const int idx) const {
110 return edgeList_[idx];
111 }
112 inline void clear() {
113 vertexList_.clear();
114 edgeList_.clear();
115 }
116
117 protected:
118 std::vector<Vertex> vertexList_{};
119 std::vector<Edge> edgeList_{};
120 };
121
124 bool operator()(const std::pair<std::pair<int, int>, double> &left,
125 const std::pair<std::pair<int, int>, double> &right) const {
126 return (left.second < right.second);
127 }
128 };
129
132 bool operator()(const std::pair<int, int> &left,
133 const std::pair<int, int> &right) const {
134 return (left.second < right.second);
135 }
136 };
137
138 // TODO : template
141 bool operator()(const std::pair<int, double> &left,
142 const std::pair<int, double> &right) const {
143 return (left.second < right.second);
144 }
145 };
146
147 class MandatoryCriticalPoints : virtual public Debug {
148
149 public:
150 enum class PointType : unsigned char {
151 Minimum = 0,
152 JoinSaddle = 1,
153 SplitSaddle = 2,
154 Maximum = 3
155 };
156
157 enum class TreeType { JoinTree, SplitTree };
159
160 public:
162 return computePlanarLayout(
166 }
167
169 return computePlanarLayout(
173 }
174
183 template <typename triangulationType>
184 int buildSubTrees(const triangulationType &triangulation);
185
188 template <class dataType, typename triangulationType>
189 int execute(const triangulationType &triangulation);
190
191 template <class dataType>
192 inline int fillVertexScalars(void *upperData, void *lowerData) {
193 dataType *upperBoundField = (dataType *)upperData;
194 dataType *lowerBoundField = (dataType *)lowerData;
195 if((int)upperVertexScalars_.size() != vertexNumber_)
197 if((int)lowerVertexScalars_.size() != vertexNumber_)
199#ifdef TTK_ENABLE_OPENMP
200#pragma omp parallel for num_threads(threadNumber_)
201#endif
202 for(int i = 0; i < vertexNumber_; i++) {
203 upperVertexScalars_[i] = (double)upperBoundField[i];
204 lowerVertexScalars_[i] = (double)lowerBoundField[i];
205 }
206 return 0;
207 }
208
210 const int &vertexId0,
211 const int &vertexId1) const;
212
213 void flush();
214
215 inline double getGlobalMaximum() const {
216 return globalMaximumValue_;
217 }
218 inline double getGlobalMinimum() const {
219 return globalMinimumValue_;
220 }
221
222 inline const Graph *getJoinTreeGraph() {
223 return &(mdtJoinTree_);
224 }
225
226 inline const std::vector<double> *getJoinTreeXLayout() {
227 return &(mdtJoinTreePointXCoord_);
228 }
229
230 inline const std::vector<double> *getJoinTreeYLayout() {
231 return &(mdtJoinTreePointYCoord_);
232 }
233
234 inline const Graph *getSplitTreeGraph() {
235 return &(mdtSplitTree_);
236 }
237
238 inline const std::vector<double> *getSplitTreeXLayout() {
239 return &(mdtSplitTreePointXCoord_);
240 }
241
242 inline const std::vector<double> *getSplitTreeYLayout() {
243 return &(mdtSplitTreePointYCoord_);
244 }
245
246 inline const std::vector<int> *getMdtJoinTreePointComponentId() const {
248 }
249 inline const std::vector<int> *getMdtSplitTreePointComponentId() const {
251 }
252 inline const std::vector<PointType> *getMdtJoinTreePointType() const {
253 return &(mdtJoinTreePointType_);
254 }
255 inline const std::vector<PointType> *getMdtSplitTreePointType() const {
256 return &(mdtSplitTreePointType_);
257 }
258 inline const std::vector<double> *getMdtJoinTreePointLowInterval() const {
260 }
261 inline const std::vector<double> *getMdtSplitTreePointLowInterval() const {
263 }
264 inline const std::vector<double> *getMdtJoinTreePointUpInterval() const {
266 }
267 inline const std::vector<double> *getMdtSplitTreePointUpInterval() const {
269 }
270 inline const std::vector<int> *getMdtJoinTreeEdgeSwitchable() {
272 }
273 inline const std::vector<int> *getMdtSplitTreeEdgeSwitchable() {
275 }
276
277 inline bool areSaddlesSwitchables(const TreeType treeType,
278 const int &firstId,
279 const int &secondId) const {
280 const double firstLower
281 = (treeType == TreeType::JoinTree)
284 const double firstUpper
285 = (treeType == TreeType::JoinTree)
288 const double secondLower
289 = (treeType == TreeType::JoinTree)
292 const double secondUpper
293 = (treeType == TreeType::JoinTree)
296 return !((secondUpper < firstLower) || (firstUpper < secondLower));
297 }
298
299 // TODO Mettre les fonctions d'output dans le cpp
300
301 template <typename triangulationType>
302 inline int computeAllJoinSaddle(const triangulationType &triangulation) {
303 if(mandatoryJoinSaddleVertex_.size() > 0) {
304 computeJoinSaddle(0, triangulation, true);
305 for(int i = 1; i < (int)mandatoryJoinSaddleVertex_.size(); i++)
306 computeJoinSaddle(i, triangulation, false);
307 } else {
308 int *output = outputMandatoryJoinSaddle_;
309 for(int i = 0; i < vertexNumber_; i++) {
310 output[i] = -1;
311 }
312 }
313 return 0;
314 }
315
317 if(mandatoryMaximumVertex_.size() > 0) {
318 computeMaximum(0, true, false);
319 for(int i = 0; i < (int)mandatoryMaximumVertex_.size(); i++)
320 computeMaximum(i, false, false);
321 } else {
322 int *output = outputMandatoryMaximum_;
323 for(int i = 0; i < vertexNumber_; i++) {
324 output[i] = -1;
325 }
326 }
327 return 0;
328 }
329
331 if(mandatoryMinimumVertex_.size() > 0) {
332 computeMinimum(0, true, false);
333 for(int i = 0; i < (int)mandatoryMinimumVertex_.size(); i++)
334 computeMinimum(i, false, false);
335 } else {
336 int *output = outputMandatoryMinimum_;
337 for(int i = 0; i < vertexNumber_; i++) {
338 output[i] = -1;
339 }
340 }
341 return 0;
342 }
343
344 template <typename triangulationType>
345 inline int computeAllSplitSaddle(const triangulationType &triangulation) {
346 if(mandatorySplitSaddleVertex_.size() > 0) {
347 computeSplitSaddle(0, triangulation, true);
348 for(int i = 1; i < (int)mandatorySplitSaddleVertex_.size(); i++)
349 computeSplitSaddle(i, triangulation, false);
350 } else {
351 int *output = outputMandatorySplitSaddle_;
352 for(int i = 0; i < vertexNumber_; i++) {
353 output[i] = -1;
354 }
355 }
356 return 0;
357 }
358
359 template <typename triangulationType>
360 inline int computeJoinSaddle(const int &id,
361 const triangulationType &triangulation,
362 const bool &reset = true) {
363 int *output = outputMandatoryJoinSaddle_;
364 if(reset)
365 for(int i = 0; i < vertexNumber_; i++) {
366 output[i] = -1;
367 }
368 if(id < (int)mandatoryJoinSaddleVertex_.size()) {
374 mandatoryJoinSaddleComponentVertices_[id], triangulation);
375 for(int i = 0;
376 i < (int)mandatoryJoinSaddleComponentVertices_[id].size(); i++) {
377 output[mandatoryJoinSaddleComponentVertices_[id][i]] += 1;
378 }
379 }
380 }
381 return 0;
382 }
383
384 int computeMaximum(const int &id,
385 const bool &reset = true,
386 const bool &ttkNotUsed(parallel) = true) {
387 int *output = outputMandatoryMaximum_;
388 if(reset)
389 for(int i = 0; i < vertexNumber_; i++)
390 output[i] = -1;
391 if(id < (int)mandatoryMaximumVertex_.size()) {
392 if(!isMdtMaximumSimplified_[id]) {
397 for(int i = 0; i < (int)mandatoryMaximumComponentVertices_[id].size();
398 i++)
399 output[mandatoryMaximumComponentVertices_[id][i]] = id;
400 }
401 }
402 return 0;
403 }
404
405 int computeMinimum(const int &id,
406 const bool &reset = true,
407 const bool &ttkNotUsed(parallel) = true) {
408 int *output = outputMandatoryMinimum_;
409 if(reset)
410 for(int i = 0; i < vertexNumber_; i++)
411 output[i] = -1;
412 if(id < (int)mandatoryMinimumVertex_.size()) {
413 if(!isMdtMinimumSimplified_[id]) {
418 for(int i = 0; i < (int)mandatoryMinimumComponentVertices_[id].size();
419 i++)
420 output[mandatoryMinimumComponentVertices_[id][i]] = id;
421 }
422 }
423 return 0;
424 }
425
426 template <typename triangulationType>
427 inline int computeSplitSaddle(const int &id,
428 const triangulationType &triangulation,
429 const bool &reset = true) {
430 int *output = outputMandatorySplitSaddle_;
431 if(reset) {
432 for(int i = 0; i < vertexNumber_; i++) {
433 output[i] = -1;
434 }
435 }
436 if(id < (int)mandatorySplitSaddleVertex_.size()) {
442 mandatorySplitSaddleComponentVertices_[id], triangulation);
443 for(int i = 0;
444 i < (int)mandatorySplitSaddleComponentVertices_[id].size(); i++) {
445 output[mandatorySplitSaddleComponentVertices_[id][i]] += 1;
446 }
447 }
448 }
449 return 0;
450 }
451
452 inline int setDebugLevel(const int &debugLevel) override {
453 Debug::setDebugLevel(debugLevel);
454 upperJoinTree_.setDebugLevel(debugLevel);
455 lowerJoinTree_.setDebugLevel(debugLevel);
456 upperSplitTree_.setDebugLevel(debugLevel);
457 lowerSplitTree_.setDebugLevel(debugLevel);
458 return 0;
459 }
460
461 inline int setLowerBoundFieldPointer(void *data) {
463 return 0;
464 }
465
466 inline int setOutputJoinSaddleDataPointer(void *data) {
467 outputMandatoryJoinSaddle_ = static_cast<int *>(data);
468 return 0;
469 }
470
477 inline int setOutputMaximumDataPointer(void *data) {
478 outputMandatoryMaximum_ = static_cast<int *>(data);
479 return 0;
480 }
481
488 inline int setOutputMinimumDataPointer(void *data) {
489 outputMandatoryMinimum_ = static_cast<int *>(data);
490 return 0;
491 }
492
493 inline int setOutputSplitSaddleDataPointer(void *data) {
494 outputMandatorySplitSaddle_ = static_cast<int *>(data);
495 return 0;
496 }
497
498 inline int setUpperBoundFieldPointer(void *data) {
500 return 0;
501 }
502
503 inline int setSimplificationThreshold(double normalizedThreshold) {
504 normalizedThreshold_ = normalizedThreshold;
505 return 0;
506 }
507
508 inline int setSoSoffsets(int *offsets = nullptr) {
509 if((int)vertexSoSoffsets_.size() != vertexNumber_)
511 if(offsets) {
512 for(int i = 0; i < vertexNumber_; i++) {
513 vertexSoSoffsets_[i] = offsets[i];
514 }
515 } else {
516 for(int i = 0; i < vertexNumber_; i++) {
517 vertexSoSoffsets_[i] = i;
518 }
519 }
520 return 0;
521 }
522
523 inline void
525 if(triangulation) {
526 triangulation->preconditionVertexNeighbors();
527 }
528 }
529
533 inline int setVertexNumber(const int &vertexNumber) {
534 vertexNumber_ = vertexNumber;
535 return 0;
536 }
537
542 inline int setVertexPosition(const int &i, const double point[3]) {
543 if((int)vertexPositions_.size() != vertexNumber_)
544 vertexPositions_.resize(vertexNumber_, std::vector<double>(3));
545 if(i < vertexNumber_) {
546 if(vertexPositions_[i].size() != 3)
547 vertexPositions_[i].resize(3);
548 vertexPositions_[i][0] = point[0];
549 vertexPositions_[i][1] = point[1];
550 vertexPositions_[i][2] = point[2];
551 return 0;
552 }
553 return -1;
554 }
555
556 inline int simplifyJoinTree() {
562 == 0) {
573 == 0) {
574 return 0;
575 } else
576 return -1;
577 } else
578 return -1;
579 }
580
581 inline int simplifySplitTree() {
587 == 0) {
598 == 0) {
599 return 0;
600 } else
601 return -1;
602 } else
603 return -1;
604 }
605
606 protected:
608 const TreeType treeType,
609 Graph &mdtTree,
610 std::vector<int> &mdtTreePointComponentId,
611 std::vector<PointType> &mdtTreePointType,
612 std::vector<double> &mdtTreePointLowInterval,
613 std::vector<double> &mdtTreePointUpInterval,
614 std::vector<int> &mdtTreeEdgeSwitchable,
615 const std::vector<int> &mdtExtremumParentSaddle,
616 const std::vector<int> &mdtSaddleParentSaddle,
617 const std::vector<bool> &isExtremumSimplified,
618 const std::vector<bool> &isSaddleSimplified,
619 const std::vector<std::pair<double, double>> &extremumInterval,
620 const std::vector<std::pair<int, int>> &mandatorySaddleVertices,
621 const int extremaNumber,
622 const int saddleNumber,
623 const PointType extremumType,
624 const PointType saddleType,
625 const PointType otherExtremumType,
626 const double globalOtherExtremumValue) const;
627
629 int
630 buildPairs(const TreeType treeType,
631 const std::vector<std::pair<int, int>> &saddleList,
632 const std::vector<std::vector<int>> &mergedExtrema,
633 const std::vector<std::pair<double, double>> &extremumInterval,
634 SubLevelSetTree &lowerTree,
635 SubLevelSetTree &upperTree,
636 std::vector<std::pair<std::pair<int, int>, double>>
637 &extremaSaddlePair) const;
638
639 int computePlanarLayout(const TreeType &treeType,
640 const Graph &mdtTree,
641 const std::vector<PointType> &mdtTreePointType,
642 const std::vector<double> &mdtTreePointLowInterval,
643 const std::vector<double> &mdtTreePointUpInterval,
644 std::vector<double> &xCoord,
645 std::vector<double> &yCoord) const;
646
647 int computeExtremumComponent(const PointType &pointType,
648 const SubLevelSetTree &tree,
649 const int seedVertexId,
650 const std::vector<double> &vertexScalars,
651 std::vector<int> &componentVertexList) const;
652
653 template <typename triangulationType>
655 const int componentId,
656 const PointType &pointType,
657 const std::vector<std::pair<int, int>> &mandatorySaddleVertex,
658 const std::vector<double> &lowVertexScalars,
659 const std::vector<double> &upVertexInterval,
660 std::vector<int> &componentVertexList,
661 const triangulationType &triangulation) const;
662
664 const PointType pointType,
665 SubLevelSetTree &firstTree,
666 SubLevelSetTree &secondTree,
667 std::vector<int> &mandatoryExtremum,
668 std::vector<std::pair<double, double>> &criticalInterval) const;
669
672 const PointType pointType,
673 SubLevelSetTree &lowerTree,
674 SubLevelSetTree &upperTree,
675 const std::vector<int> &mandatoryExtremumVertex,
676 std::vector<std::pair<int, int>> &mandatorySaddleVertex,
677 std::vector<std::vector<int>> &mandatoryMergedExtrema);
678
680 const int &startingSuperArcId,
681 const double &targetValue) const;
682
683 void getSubTreeSuperArcIds(const SubLevelSetTree *tree,
684 const int &rootSuperArcId,
685 std::vector<int> &subTreeSuperArcId) const;
686
687 inline int getVertexSuperArcId(const int &vertexId,
688 const SubLevelSetTree *tree) const {
689
690 int superArcId = tree->getVertexSuperArcId(vertexId);
691 // If superArcId == -1, it may be a leaf so look for the nearest super arc
692 if(superArcId == -1) {
693 int nodeId = tree->getVertexNodeId(vertexId);
694 if(tree->getNode(nodeId)->getNumberOfUpSuperArcs()) {
695 superArcId = tree->getNode(nodeId)->getUpSuperArcId(0);
696 } else if(tree->getNode(nodeId)->getNumberOfDownSuperArcs()) {
697 superArcId = tree->getNode(nodeId)->getDownSuperArcId(0);
698 }
699 }
700 return superArcId;
701 }
702
703 int simplify(const double normalizedThreshold,
704 const TreeType treeType,
705 const std::vector<std::pair<std::pair<int, int>, double>>
706 &extremaSaddlePair,
707 const std::vector<std::vector<int>> &mergedExtrema,
708 const int numberOfExtrema,
709 std::vector<bool> &extremumSimplified,
710 std::vector<bool> &saddleSimplified,
711 std::vector<int> &extremumParentSaddle,
712 std::vector<int> &saddleParentSaddle) const;
713
714 protected:
730 std::vector<std::vector<double>> vertexPositions_{};
732 std::vector<int> vertexSoSoffsets_{};
734 std::vector<double> upperVertexScalars_{};
736 std::vector<double> lowerVertexScalars_{};
746 std::vector<int> upperMinimumList_{};
748 std::vector<int> lowerMinimumList_{};
750 std::vector<int> upperMaximumList_{};
752 std::vector<int> lowerMaximumList_{};
754 std::vector<int> mandatoryMinimumVertex_{};
756 std::vector<int> mandatoryMaximumVertex_{};
758 std::vector<std::pair<double, double>> mandatoryMinimumInterval_{};
760 std::vector<std::pair<double, double>> mandatoryMaximumInterval_{};
762 std::vector<std::pair<int, int>> mandatoryJoinSaddleVertex_{};
764 std::vector<std::pair<int, int>> mandatorySplitSaddleVertex_{};
767 std::vector<std::vector<int>> mergedMaximaId_{};
770 std::vector<std::vector<int>> mergedMinimaId_{};
772 std::vector<std::pair<std::pair<int, int>, double>> mdtMinJoinSaddlePair_{};
774 std::vector<std::pair<std::pair<int, int>, double>>
780 std::vector<bool> isMdtMinimumSimplified_;
783 std::vector<bool> isMdtJoinSaddleSimplified_{};
786 std::vector<bool> isMdtSplitSaddleSimplified_{};
789 std::vector<bool> isMdtMaximumSimplified_{};
790
791 // Graph
792 std::vector<int> mdtMinimumParentSaddleId_{};
795 std::vector<int> mdtMaximumParentSaddleId_{};
796
799
802 std::vector<PointType> mdtJoinTreePointType_{};
803 std::vector<PointType> mdtSplitTreePointType_{};
804 std::vector<double> mdtJoinTreePointLowInterval_{};
805 std::vector<double> mdtSplitTreePointLowInterval_{};
806 std::vector<double> mdtJoinTreePointUpInterval_{};
807 std::vector<double> mdtSplitTreePointUpInterval_{};
808
809 std::vector<int> mdtJoinTreeEdgeSwitchable_{};
810 std::vector<int> mdtSplitTreeEdgeSwitchable_{};
811
812 std::vector<double> mdtJoinTreePointXCoord_{};
813 std::vector<double> mdtSplitTreePointXCoord_{};
814
815 std::vector<double> mdtJoinTreePointYCoord_{};
816 std::vector<double> mdtSplitTreePointYCoord_{};
817
820
822 std::vector<std::vector<int>> mandatoryMaximumComponentVertices_{};
825 std::vector<std::vector<int>> mandatoryMinimumComponentVertices_{};
828 std::vector<std::vector<int>> mandatoryJoinSaddleComponentVertices_{};
831 std::vector<std::vector<int>> mandatorySplitSaddleComponentVertices_{};
832 };
833} // namespace ttk
834
835// if the package is a pure template class, uncomment the following line
836// #include <MandatoryCriticalPoints.cpp>
837
838// template functions
839template <class dataType, typename triangulationType>
841 const triangulationType &triangulation) {
842
843 Timer t;
844
845// Check the consistency of the variables
846// TODO Move the output checks in the right functions
847#ifndef TTK_ENABLE_KAMIKAZE
849 return -1;
851 return -2;
853 return -3;
855 return -4;
857 return -5;
859 return -6;
860 if(!vertexNumber_)
861 return -7;
862 if(!vertexPositions_.size())
863 return -8;
864#endif
865
866 // Init the input
867 fillVertexScalars<dataType>(inputUpperBoundField_, inputLowerBoundField_);
868
869 // Build the join trees and split trees
870 buildSubTrees(triangulation);
871
872// Compute mandatory extrema
873#ifdef TTK_ENABLE_OPENMP
874#pragma omp parallel sections
875#endif
876 {
877#ifdef TTK_ENABLE_OPENMP
878#pragma omp section
879#endif
880 {
884 }
885#ifdef TTK_ENABLE_OPENMP
886#pragma omp section
887#endif
888 {
892 }
893 }
894
895 // Compute mandatory saddles
902
903 // Build pairs of <extremum,saddle>
910
911 // Simplify pairs
920
921 // Build the mandatory trees
942
943 // Compute the planar layout for the output trees
951
952 // Clear outputs
955 mandatoryMinimumComponentVertices_.end(), std::vector<int>());
959 mandatoryJoinSaddleComponentVertices_.end(), std::vector<int>());
963 mandatorySplitSaddleComponentVertices_.end(), std::vector<int>());
966 mandatoryMaximumComponentVertices_.end(), std::vector<int>());
967
968 this->printMsg(
969 "Data-set (" + std::to_string(vertexNumber_) + " points) processed", 1.0,
970 t.getElapsedTime(), this->threadNumber_);
971 return 0;
972}
973
974template <typename triangulationType>
976 const triangulationType &triangulation) {
977
978 Timer t;
979
980#ifndef TTK_ENABLE_KAMIKAZE
981 if(vertexNumber_ <= 0)
982 return -1;
983 if((int)upperVertexScalars_.size() != vertexNumber_)
984 return -2;
985 if((int)lowerVertexScalars_.size() != vertexNumber_)
986 return -3;
987 if((int)vertexPositions_.size() != vertexNumber_)
988 return -4;
989 if(triangulation.getNumberOfVertices() != vertexNumber_)
990 return -5;
991 if((int)vertexSoSoffsets_.size() != vertexNumber_)
992 return -6;
993#endif
994
995 // upperMaximumList_ and lowerMinimumList_ computation (not sorted by function
996 // value)
997 lowerMinimumList_.clear();
998 upperMaximumList_.clear();
999#ifdef TTK_ENABLE_OPENMP
1000#pragma omp parallel for num_threads(threadNumber_)
1001#endif
1002 for(int i = 0; i < vertexNumber_; i++) {
1003 bool isLowerMin = true;
1004 bool isUpperMax = true;
1005 SimplexId neighborNumber = triangulation.getVertexNeighborNumber(i);
1006 for(SimplexId j = 0; j < neighborNumber; j++) {
1007 SimplexId neighborId{-1};
1008 triangulation.getVertexNeighbor(i, j, neighborId);
1009 if((lowerVertexScalars_[neighborId] < lowerVertexScalars_[i])
1010 || ((lowerVertexScalars_[neighborId] == lowerVertexScalars_[i])
1011 && (vertexSoSoffsets_[neighborId] < vertexSoSoffsets_[i])))
1012 isLowerMin = false;
1013 if((upperVertexScalars_[neighborId] > upperVertexScalars_[i])
1014 || ((upperVertexScalars_[neighborId] == upperVertexScalars_[i])
1015 && (vertexSoSoffsets_[neighborId] > vertexSoSoffsets_[i])))
1016 isUpperMax = false;
1017 if(!isUpperMax && !isLowerMin)
1018 break;
1019 }
1020 if(isLowerMin) {
1021#ifdef TTK_ENABLE_OPENMP
1022#pragma omp critical
1023#endif
1024 { lowerMinimumList_.push_back(i); }
1025 }
1026 if(isUpperMax) {
1027#ifdef TTK_ENABLE_OPENMP
1028#pragma omp critical
1029#endif
1030 { upperMaximumList_.push_back(i); }
1031 }
1032 }
1033
1034#ifdef TTK_ENABLE_OPENMP
1035#pragma omp parallel sections num_threads(threadNumber_)
1036#endif
1037 {
1038#ifdef TTK_ENABLE_OPENMP
1039#pragma omp section
1040#endif
1041 {
1042 upperJoinTree_.setNumberOfVertices(vertexNumber_);
1043 upperJoinTree_.setVertexScalars(&upperVertexScalars_);
1044 upperJoinTree_.setVertexPositions(&vertexPositions_);
1045 upperJoinTree_.setTriangulation(&triangulation);
1046 upperJoinTree_.setVertexSoSoffsets(&vertexSoSoffsets_);
1047 upperJoinTree_.buildExtremumList(upperMinimumList_, true);
1048 upperJoinTree_.build();
1049 }
1050#ifdef TTK_ENABLE_OPENMP
1051#pragma omp section
1052#endif
1053 {
1054 lowerJoinTree_.setNumberOfVertices(vertexNumber_);
1055 lowerJoinTree_.setVertexScalars(&lowerVertexScalars_);
1056 lowerJoinTree_.setVertexPositions(&vertexPositions_);
1057 lowerJoinTree_.setTriangulation(&triangulation);
1058 lowerJoinTree_.setVertexSoSoffsets(&vertexSoSoffsets_);
1059 lowerJoinTree_.setMinimumList(lowerMinimumList_);
1060 lowerJoinTree_.build();
1061 }
1062#ifdef TTK_ENABLE_OPENMP
1063#pragma omp section
1064#endif
1065 {
1066 upperSplitTree_.setNumberOfVertices(vertexNumber_);
1067 upperSplitTree_.setVertexScalars(&upperVertexScalars_);
1068 upperSplitTree_.setVertexPositions(&vertexPositions_);
1069 upperSplitTree_.setTriangulation(&triangulation);
1070 upperSplitTree_.setVertexSoSoffsets(&vertexSoSoffsets_);
1071 upperSplitTree_.setMaximumList(upperMaximumList_);
1072 upperSplitTree_.build();
1073 }
1074#ifdef TTK_ENABLE_OPENMP
1075#pragma omp section
1076#endif
1077 {
1078 lowerSplitTree_.setNumberOfVertices(vertexNumber_);
1079 lowerSplitTree_.setVertexScalars(&lowerVertexScalars_);
1080 lowerSplitTree_.setVertexPositions(&vertexPositions_);
1081 lowerSplitTree_.setTriangulation(&triangulation);
1082 lowerSplitTree_.setVertexSoSoffsets(&vertexSoSoffsets_);
1083 lowerSplitTree_.buildExtremumList(lowerMaximumList_, false);
1084 lowerSplitTree_.build();
1085 }
1086 }
1087 this->printMsg("4 SubLevelSetTrees computed", 1.0, t.getElapsedTime(),
1088 this->threadNumber_);
1089 return 0;
1090}
1091
1092template <typename triangulationType>
1094 const int componentId,
1095 const PointType &pointType,
1096 const std::vector<std::pair<int, int>> &mandatorySaddleVertex,
1097 const std::vector<double> &lowVertexScalars,
1098 const std::vector<double> &upVertexScalars,
1099 std::vector<int> &componentVertexList,
1100 const triangulationType &triangulation) const {
1101
1102 const int seedVertexId = mandatorySaddleVertex[componentId].first;
1103 const double lowInterval = lowVertexScalars[seedVertexId];
1104 const double upInterval
1105 = upVertexScalars[mandatorySaddleVertex[componentId].second];
1106
1107 componentVertexList.clear();
1108
1109 std::vector<bool> isVisited(vertexNumber_, false);
1110 std::queue<SimplexId> idQueue;
1111 idQueue.push(seedVertexId);
1112
1113 while(!(idQueue.empty())) {
1114 int vertexId = idQueue.front();
1115 idQueue.pop();
1116 if(!isVisited[vertexId]) {
1117 isVisited[vertexId] = true;
1118 double lowerValue = lowerVertexScalars_[vertexId];
1119 double upperValue = upperVertexScalars_[vertexId];
1120 if((pointType == PointType::JoinSaddle && (!(lowerValue > upInterval))
1121 && (upperValue > lowInterval))
1122 || (pointType == PointType::SplitSaddle
1123 && (!(upperValue < lowInterval)) && (lowerValue < upInterval))) {
1124 componentVertexList.push_back(vertexId);
1125 // Neighbors
1126 SimplexId neighborNumber
1127 = triangulation.getVertexNeighborNumber(vertexId);
1128 for(SimplexId i = 0; i < neighborNumber; i++) {
1129 SimplexId neighborVertexId;
1130 triangulation.getVertexNeighbor(vertexId, i, neighborVertexId);
1131 idQueue.push(neighborVertexId);
1132 }
1133 }
1134 }
1135 }
1136 return 0;
1137}
#define ttkNotUsed(x)
Mark function/method parameters that are not used in the function body at all.
Definition: BaseClass.h:47
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
Minimalist debugging class.
Definition: Debug.h:88
virtual int setDebugLevel(const int &debugLevel)
Definition: Debug.cpp:147
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
Edge(const int &start, const int &end)
const std::pair< int, int > & getVertexIdx() const
std::pair< int, int > vertexIdx_
std::vector< int > edgeIdx_
int getEdgeIdx(const int &connectedEdge) const
const Edge & getEdge(const int idx) const
int addEdge(const int &start, const int &end)
Add an edge between the vertex start and end, returns it's index.
const Vertex & getVertex(const int idx) const
Get a pointer to the vertex idx.
std::vector< Edge > edgeList_
std::vector< Vertex > vertexList_
int addVertex()
Add a vertex, returns it's index.
int getNumberOfVertices() const
int getNumberOfEdges() const
TTK processing package for the computation of mandatory critical points in uncertain scalar data.
std::vector< std::pair< int, int > > mandatorySplitSaddleVertex_
Pair of mandatory vertices for each split saddle component.
std::vector< std::pair< std::pair< int, int >, double > > mdtMaxSplitSaddlePair_
Pairs ( (M,S), d(M,S) ) Of maxima and split saddles.
int computeJoinSaddle(const int &id, const triangulationType &triangulation, const bool &reset=true)
int execute(const triangulationType &triangulation)
std::vector< double > mdtJoinTreePointXCoord_
int vertexNumber_
Number of vertices.
std::vector< std::vector< int > > mandatoryMinimumComponentVertices_
const std::vector< PointType > * getMdtJoinTreePointType() const
std::vector< double > mdtSplitTreePointLowInterval_
std::vector< double > mdtJoinTreePointLowInterval_
int computePlanarLayout(const TreeType &treeType, const Graph &mdtTree, const std::vector< PointType > &mdtTreePointType, const std::vector< double > &mdtTreePointLowInterval, const std::vector< double > &mdtTreePointUpInterval, std::vector< double > &xCoord, std::vector< double > &yCoord) const
int enumerateMandatorySaddles(const PointType pointType, SubLevelSetTree &lowerTree, SubLevelSetTree &upperTree, const std::vector< int > &mandatoryExtremumVertex, std::vector< std::pair< int, int > > &mandatorySaddleVertex, std::vector< std::vector< int > > &mandatoryMergedExtrema)
TODO : Multiplicity.
std::vector< PointType > mdtJoinTreePointType_
std::vector< int > mdtSplitTreeEdgeSwitchable_
bool areSaddlesSwitchables(const TreeType treeType, const int &firstId, const int &secondId) const
const std::vector< double > * getJoinTreeYLayout()
int computeAllSplitSaddle(const triangulationType &triangulation)
int enumerateMandatoryExtrema(const PointType pointType, SubLevelSetTree &firstTree, SubLevelSetTree &secondTree, std::vector< int > &mandatoryExtremum, std::vector< std::pair< double, double > > &criticalInterval) const
std::vector< std::vector< double > > vertexPositions_
Position (x,y,z) of each vertex.
std::vector< std::vector< int > > mandatoryMaximumComponentVertices_
List of the vertices forming each of the mandatory maximum components.
int buildMandatoryTree(const TreeType treeType, Graph &mdtTree, std::vector< int > &mdtTreePointComponentId, std::vector< PointType > &mdtTreePointType, std::vector< double > &mdtTreePointLowInterval, std::vector< double > &mdtTreePointUpInterval, std::vector< int > &mdtTreeEdgeSwitchable, const std::vector< int > &mdtExtremumParentSaddle, const std::vector< int > &mdtSaddleParentSaddle, const std::vector< bool > &isExtremumSimplified, const std::vector< bool > &isSaddleSimplified, const std::vector< std::pair< double, double > > &extremumInterval, const std::vector< std::pair< int, int > > &mandatorySaddleVertices, const int extremaNumber, const int saddleNumber, const PointType extremumType, const PointType saddleType, const PointType otherExtremumType, const double globalOtherExtremumValue) const
int computeSplitSaddle(const int &id, const triangulationType &triangulation, const bool &reset=true)
int * outputMandatoryMinimum_
Void pointer to the output mandatory minima components.
int getVertexSuperArcId(const int &vertexId, const SubLevelSetTree *tree) const
std::vector< int > mdtSplitSaddleParentSaddleId_
const std::vector< int > * getMdtJoinTreeEdgeSwitchable()
void getSubTreeSuperArcIds(const SubLevelSetTree *tree, const int &rootSuperArcId, std::vector< int > &subTreeSuperArcId) const
SubLevelSetTree lowerJoinTree_
Join tree of the lower bound scalar field.
std::vector< std::vector< int > > mergedMinimaId_
std::vector< int > upperMinimumList_
List of vertex id of the minima in the upper bound scalar field.
void * inputUpperBoundField_
Void pointer to the input upper bound scalar field.
int * outputMandatoryJoinSaddle_
Void pointer to the output mandatory join saddles components.
std::vector< int > mdtJoinSaddleParentSaddleId_
SubLevelSetTree lowerSplitTree_
Split tree of the lower bound scalar field.
int computeMaximum(const int &id, const bool &reset=true, const bool &ttkNotUsed(parallel)=true)
const std::vector< double > * getMdtJoinTreePointLowInterval() const
const std::vector< PointType > * getMdtSplitTreePointType() const
const std::vector< double > * getMdtSplitTreePointLowInterval() const
int computeSaddleComponent(const int componentId, const PointType &pointType, const std::vector< std::pair< int, int > > &mandatorySaddleVertex, const std::vector< double > &lowVertexScalars, const std::vector< double > &upVertexInterval, std::vector< int > &componentVertexList, const triangulationType &triangulation) const
std::vector< PointType > mdtSplitTreePointType_
void * inputLowerBoundField_
Void pointer to the input lower bound scalar field.
std::vector< int > mdtMaximumParentSaddleId_
std::vector< std::pair< std::pair< int, int >, double > > mdtMinJoinSaddlePair_
Pairs ( (M,S), d(M,S) ) Of minima and join saddles.
int setVertexPosition(const int &i, const double point[3])
const std::vector< double > * getSplitTreeYLayout()
int simplify(const double normalizedThreshold, const TreeType treeType, const std::vector< std::pair< std::pair< int, int >, double > > &extremaSaddlePair, const std::vector< std::vector< int > > &mergedExtrema, const int numberOfExtrema, std::vector< bool > &extremumSimplified, std::vector< bool > &saddleSimplified, std::vector< int > &extremumParentSaddle, std::vector< int > &saddleParentSaddle) const
int setVertexNumber(const int &vertexNumber)
std::vector< int > lowerMaximumList_
List of vertex id of the maxima in the lower bound scalar field.
std::vector< double > upperVertexScalars_
Copy of the input upper scalar field converted in double.
std::vector< double > mdtJoinTreePointUpInterval_
const std::vector< double > * getMdtSplitTreePointUpInterval() const
std::vector< bool > isMdtMinimumSimplified_
std::vector< int > mdtJoinTreePointComponentId_
std::vector< double > lowerVertexScalars_
Copy of the input lower scalar field converted in double.
std::vector< bool > isMdtSplitSaddleSimplified_
int setSoSoffsets(int *offsets=nullptr)
double normalizedThreshold_
Value of the simplification threshold.
SubLevelSetTree upperJoinTree_
Join tree of the upper bound scalar field.
int findCommonAncestorNodeId(const SubLevelSetTree *tree, const int &vertexId0, const int &vertexId1) const
std::vector< int > mdtSplitTreePointComponentId_
std::vector< std::pair< int, int > > mandatoryJoinSaddleVertex_
Pair of mandatory vertices for each join saddle component.
std::vector< bool > isMdtMaximumSimplified_
SubLevelSetTree upperSplitTree_
Split tree of the upper bound scalar field.
const std::vector< double > * getJoinTreeXLayout()
const std::vector< int > * getMdtSplitTreePointComponentId() const
std::vector< int > vertexSoSoffsets_
Offsets.
std::vector< int > mdtJoinTreeEdgeSwitchable_
std::vector< std::pair< double, double > > mandatoryMaximumInterval_
Critical interval for each maximum component.
int computeMinimum(const int &id, const bool &reset=true, const bool &ttkNotUsed(parallel)=true)
int getSubTreeRootSuperArcId(const SubLevelSetTree *tree, const int &startingSuperArcId, const double &targetValue) const
std::vector< double > mdtSplitTreePointXCoord_
const std::vector< int > * getMdtJoinTreePointComponentId() const
int computeExtremumComponent(const PointType &pointType, const SubLevelSetTree &tree, const int seedVertexId, const std::vector< double > &vertexScalars, std::vector< int > &componentVertexList) const
int buildPairs(const TreeType treeType, const std::vector< std::pair< int, int > > &saddleList, const std::vector< std::vector< int > > &mergedExtrema, const std::vector< std::pair< double, double > > &extremumInterval, SubLevelSetTree &lowerTree, SubLevelSetTree &upperTree, std::vector< std::pair< std::pair< int, int >, double > > &extremaSaddlePair) const
TODO : Replace SubLevelSetTrees by scalar fields for vertex value.
std::vector< std::vector< int > > mandatorySplitSaddleComponentVertices_
std::vector< int > lowerMinimumList_
List of vertex id of the minima in the lower bound scalar field.
int * outputMandatorySplitSaddle_
Void pointer to the output mandatory split saddles components.
std::vector< std::vector< int > > mandatoryJoinSaddleComponentVertices_
std::vector< int > mdtMinimumParentSaddleId_
int setSimplificationThreshold(double normalizedThreshold)
std::vector< std::vector< int > > mergedMaximaId_
std::vector< std::pair< double, double > > mandatoryMinimumInterval_
Critical interval for each minimum component.
const std::vector< double > * getSplitTreeXLayout()
std::vector< double > mdtSplitTreePointYCoord_
std::vector< double > mdtJoinTreePointYCoord_
int fillVertexScalars(void *upperData, void *lowerData)
int setDebugLevel(const int &debugLevel) override
const std::vector< double > * getMdtJoinTreePointUpInterval() const
std::vector< double > mdtSplitTreePointUpInterval_
int buildSubTrees(const triangulationType &triangulation)
int * outputMandatoryMaximum_
Void pointer to the output mandatory maxima components.
std::vector< bool > isMdtJoinSaddleSimplified_
const std::vector< int > * getMdtSplitTreeEdgeSwitchable()
void preconditionTriangulation(AbstractTriangulation *const triangulation)
std::vector< int > upperMaximumList_
List of vertex id of the maxima in the upper bound scalar field.
std::vector< int > mandatoryMinimumVertex_
Mandatory vertex for each minimum component.
int computeAllJoinSaddle(const triangulationType &triangulation)
std::vector< int > mandatoryMaximumVertex_
Mandatory vertex for each maximum component.
int getUpSuperArcId(const int &neighborId) const
Definition: ContourTree.h:172
int getNumberOfDownSuperArcs() const
Definition: ContourTree.h:182
int getNumberOfUpSuperArcs() const
Definition: ContourTree.h:190
int getDownSuperArcId(const int &neighborId) const
Definition: ContourTree.h:160
int getVertexSuperArcId(const int &vertexId) const
Definition: ContourTree.h:436
const Node * getNode(const int &nodeId) const
Definition: ContourTree.h:305
int getVertexNodeId(const int &vertexId) const
Definition: ContourTree.h:459
double getElapsedTime()
Definition: Timer.h:15
The Topology ToolKit.
int SimplexId
Identifier type for simplices of any dimension.
Definition: DataTypes.h:22
Comparison between critical point pairs ( (Extremum,Saddle), dist(M,S) )
bool operator()(const std::pair< std::pair< int, int >, double > &left, const std::pair< std::pair< int, int >, double > &right) const
Comparison between mandatory saddles (Saddle id, Number of merged extrema)
bool operator()(const std::pair< int, int > &left, const std::pair< int, int > &right) const
Comparison of the second member of a std::pair<int,double>
bool operator()(const std::pair< int, double > &left, const std::pair< int, double > &right) const
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)