47 criticalPointsNumber_ = number;
48 criticalPoints_ =
static_cast<float *
>(points);
49 criticalPointsIdentifier_ =
static_cast<SimplexId *
>(ids);
50 criticalPointsCellIds_ =
static_cast<SimplexId *
>(cellIds);
51 criticalPointsType_ =
static_cast<unsigned char *
>(type);
59 separatriceNumber_ = number;
60 sepCellIds_ =
static_cast<SimplexId *
>(cellIds);
61 sepCellDims_ =
static_cast<unsigned char *
>(cellDims);
62 sepMask_ =
static_cast<unsigned char *
>(mask);
63 sepPoints_ =
static_cast<float *
>(points);
74 if(triangl !=
nullptr) {
83 template <
typename triangulationType>
84 int execute(
const triangulationType &triangulation);
95 template <
typename triangulationType>
96 size_t findSeparatrixMiddle(
const size_t a,
98 const triangulationType &triangulation);
109 int findSepsVertices(
const std::vector<size_t> &seps,
110 std::vector<LongSimplexId> &srcs,
111 std::vector<LongSimplexId> &dsts)
const;
122 template <
typename triangulationType>
123 int quadrangulate(
size_t &ndegen,
const triangulationType &triangulation);
133 int dualQuadrangulate();
143 template <
typename triangulationType>
144 int subdivise(
const triangulationType &triangulation);
155 template <
typename triangulationType>
156 int detectCellSeps(
const triangulationType &triangulation);
164 template <
typename triangulationType>
165 bool checkSurfaceCloseness(
const triangulationType &triangulation)
const;
175 using Quad = std::array<LongSimplexId, 4>;
184 template <
typename triangulationType>
185 int subdiviseDegenerateQuads(std::vector<Quad> &outputSubd,
186 const triangulationType &triangulation);
194 float *criticalPoints_{};
200 unsigned char *criticalPointsType_{};
207 unsigned char *sepMask_{};
209 unsigned char *sepCellDims_{};
214 std::vector<size_t> sepBegs_{};
216 std::vector<size_t> sepEnds_{};
218 std::vector<SimplexId> sepMids_{};
220 std::vector<SimplexId> morseSeg_{};
222 std::vector<std::pair<SimplexId, std::vector<size_t>>> quadSeps_{};
246template <
typename triangulationType>
247int ttk::MorseSmaleQuadrangulation::detectCellSeps(
248 const triangulationType &triangulation) {
250 ExplicitTriangulation newT{};
255 newT.preconditionEdges();
256 newT.preconditionVertexNeighbors();
257 newT.preconditionVertexEdges();
258 newT.preconditionVertexTriangles();
259 newT.preconditionEdgeTriangles();
260 newT.preconditionTriangleEdges();
262 auto nEdges = triangulation.getNumberOfEdges();
265 std::vector<SimplexId> edgeOnSep(newT.getNumberOfEdges(), -1);
267 size_t critPoints{0};
268 if(sepMask_[0] == 0) {
274 if(sepCellDims_[a] == 0) {
275 return sepCellIds_[a];
277 if(sepCellDims_[a] == 1) {
278 return verticesNumber_ + sepCellIds_[a];
280 if(sepCellDims_[a] == 2) {
281 return verticesNumber_ + nEdges + sepCellIds_[a];
291 for(
SimplexId i = 1; i < separatriceNumber_; ++i) {
294 if(sepMask_[i] == 0) {
297 if(critPoints % 2 == 1) {
298 prev = critPointId(i);
305 = (critPoints % 2 == 0) ? critPoints / 2 - 1 : critPoints / 2;
311 auto ne = newT.getVertexEdgeNumber(curr);
314 newT.getVertexEdge(curr, j, e);
316 newT.getEdgeVertex(e, 0, e0);
317 newT.getEdgeVertex(e, 1, e1);
319 if((e0 == prev && e1 == curr) || (e1 == prev && e0 == curr)) {
320 edgeOnSep[e] = currSepId;
329 std::vector<bool> isSaddle(newT.getNumberOfVertices(),
false);
331 for(
SimplexId i = 0; i < criticalPointsNumber_; ++i) {
333 if(criticalPointsType_[i] != 1) {
336 isSaddle[verticesNumber_ + criticalPointsCellIds_[i]] =
true;
339 auto getTriangleEdges
341 newT.getTriangleEdge(tr, 0, e0);
342 newT.getTriangleEdge(tr, 1, e1);
343 newT.getTriangleEdge(tr, 2, e2);
348 auto sepIdAroundTriangle = [&](
const SimplexId tr) {
350 getTriangleEdges(tr, e0, e1, e2);
352 std::set<SimplexId> sepId{};
353 if(edgeOnSep[e0] != -1 && edgeOnSep[e1] != -1) {
354 sepId.emplace(edgeOnSep[e0]);
355 sepId.emplace(edgeOnSep[e1]);
356 }
else if(edgeOnSep[e1] != -1 && edgeOnSep[e2] != -1) {
357 sepId.emplace(edgeOnSep[e1]);
358 sepId.emplace(edgeOnSep[e2]);
359 }
else if(edgeOnSep[e0] != -1 && edgeOnSep[e2] != -1) {
360 sepId.emplace(edgeOnSep[e0]);
361 sepId.emplace(edgeOnSep[e2]);
366 auto hasTriangleSaddle = [&](
const SimplexId tr) {
368 newT.getTriangleVertex(tr, 0, a);
369 newT.getTriangleVertex(tr, 1, b);
370 newT.getTriangleVertex(tr, 2, c);
371 return (isSaddle[a] || isSaddle[b] || isSaddle[c]);
375 std::vector<SimplexId> processed(newT.getNumberOfTriangles(), -1);
378 std::vector<SimplexId> saddles{};
380 for(
SimplexId i = 0; i < criticalPointsNumber_; ++i) {
382 if(criticalPointsType_[i] == 1) {
383 saddles.emplace_back(verticesNumber_ + criticalPointsCellIds_[i]);
388 for(
size_t i = 0; i < saddles.size(); ++i) {
391 auto sadtri = newT.getVertexTriangleNumber(saddle);
393#ifdef TTK_ENABLE_OPENMP
394#pragma omp parallel for num_threads(threadNumber_)
397 std::queue<SimplexId> toProcess{};
399 newT.getVertexTriangle(saddle, j, tr);
401 std::set<SimplexId>
const sepIdBeg = sepIdAroundTriangle(tr);
407 while(!toProcess.empty()) {
408 auto curr = toProcess.front();
412#ifdef TTK_ENABLE_OPENMP
413 if(processed[curr] == -1 || processed[curr] > iter) {
414#pragma omp atomic write
415 processed[curr] = iter;
418 else if(processed[curr] == iter) {
422 else if(processed[curr] < iter) {
426 if(processed[curr] != -1) {
433 bool const hasSaddle = hasTriangleSaddle(curr);
436 auto sepIdEnd = sepIdAroundTriangle(curr);
438 if(hasSaddle && sepIdEnd.size() == 2) {
440 std::vector<size_t> cellSeps{};
441 std::set_union(sepIdBeg.begin(), sepIdBeg.end(), sepIdEnd.begin(),
442 sepIdEnd.end(), std::back_inserter(cellSeps));
443 if(cellSeps.size() > 2) {
445#ifdef TTK_ENABLE_OPENMP
450 quadSeps_.emplace_back(iter, cellSeps);
458 newT.getTriangleVertex(curr, k, vert);
459 if(vert >= verticesNumber_) {
462 bool vertOnSep =
false;
463 for(
SimplexId l = 0; l < newT.getVertexEdgeNumber(vert); ++l) {
465 newT.getVertexEdge(vert, l, e);
466 if(edgeOnSep[e] != -1) {
472#ifdef TTK_ENABLE_OPENMP
473#pragma omp atomic write
475 morseSeg_[vert] = iter;
480 std::array<SimplexId, 3> edges{};
481 getTriangleEdges(curr, edges[0], edges[1], edges[2]);
482 for(
const auto e : edges) {
484 if(edgeOnSep[e] != -1) {
487 for(
SimplexId k = 0; k < newT.getEdgeTriangleNumber(e); ++k) {
489 newT.getEdgeTriangle(e, k, neigh);
491 if(processed[neigh] == -1) {
492 toProcess.push(neigh);
494#ifdef TTK_ENABLE_OPENMP
496 else if(processed[neigh] > iter) {
497 toProcess.push(neigh);
500 else if(processed[neigh] < iter) {
520template <
typename triangulationType>
521int ttk::MorseSmaleQuadrangulation::quadrangulate(
522 size_t &ndegen,
const triangulationType &triangulation) {
526 std::vector<size_t> sepFlatEdges{};
528 for(
SimplexId i = 0; i < separatriceNumber_; ++i) {
529 if(sepMask_[i] == 1) {
532 sepFlatEdges.emplace_back(i);
536 auto numSeps = sepFlatEdges.size() / 2;
539 sepBegs_.resize(numSeps);
540 sepEnds_.resize(numSeps);
541 morseSeg_.resize(verticesNumber_);
542 std::fill(morseSeg_.begin(), morseSeg_.end(), -1);
546 for(
size_t i = 0; i < numSeps; ++i) {
548 sepBegs_[i] = sepFlatEdges[2 * i];
549 sepEnds_[i] = sepFlatEdges[2 * i + 1];
552 detectCellSeps(triangulation);
554 outputCells_.reserve(quadSeps_.size());
556 for(
const auto &qsp : quadSeps_) {
558 const auto &qs{qsp.second};
560 std::vector<LongSimplexId> srcs{};
561 std::vector<LongSimplexId> dsts{};
563 findSepsVertices(qs, srcs, dsts);
566 std::set<LongSimplexId>
const srcs_set(srcs.begin(), srcs.end());
567 std::set<LongSimplexId>
const dsts_set(dsts.begin(), dsts.end());
568 srcs.assign(srcs_set.begin(), srcs_set.end());
569 dsts.assign(dsts_set.begin(), dsts_set.end());
576 if(dsts.size() != 2) {
580 if(srcs.size() == 2) {
581 outputCells_.emplace_back(Quad{dsts[0], srcs[0], dsts[1], srcs[1]});
582 }
else if(srcs.size() == 1) {
583 outputCells_.emplace_back(Quad{dsts[0], srcs[0], dsts[1], srcs[0]});
597template <
typename triangulationType>
598size_t ttk::MorseSmaleQuadrangulation::findSeparatrixMiddle(
599 const size_t a,
const size_t b,
const triangulationType &triangulation) {
603 std::vector<float> distFromA(b - a + 1);
604 std::array<float, dim> prev{}, curr{};
606 if(distFromA.empty()) {
610 curr[0] = sepPoints_[dim * a];
611 curr[1] = sepPoints_[dim * a + 1];
612 curr[2] = sepPoints_[dim * a + 2];
615 for(
size_t i = 1; i < b - a + 1; ++i) {
616 std::swap(curr, prev);
617 curr[0] = sepPoints_[dim * (a + i)];
618 curr[1] = sepPoints_[dim * (a + i) + 1];
619 curr[2] = sepPoints_[dim * (a + i) + 2];
624 auto distAB = distFromA.back();
625 for(
auto &el : distFromA) {
626 el = std::abs(el - distAB / 2.0);
631 + (std::min_element(distFromA.begin(), distFromA.end())
632 - distFromA.begin());
635 outputPoints_.emplace_back(sepPoints_[dim * pos]);
636 outputPoints_.emplace_back(sepPoints_[dim * pos + 1]);
637 outputPoints_.emplace_back(sepPoints_[dim * pos + 2]);
642 switch(sepCellDims_[pos]) {
644 outputPointsIds_.emplace_back(sepCellIds_[pos]);
648 triangulation.getEdgeVertex(sepCellIds_[pos], 0,
id);
649 outputPointsIds_.emplace_back(
id);
654 triangulation.getTriangleVertex(sepCellIds_[pos], 0,
id);
655 outputPointsIds_.emplace_back(
id);
662 outputPointsTypes_.emplace_back(1);
667template <
typename triangulationType>
668int ttk::MorseSmaleQuadrangulation::subdiviseDegenerateQuads(
669 std::vector<Quad> &outputSubd,
const triangulationType &triangulation) {
671 for(
size_t i = 0; i < outputCells_.size(); ++i) {
672 auto q = outputCells_[i];
673 auto seps = quadSeps_[i].second;
680 std::vector<LongSimplexId> srcs{};
681 std::vector<LongSimplexId> dsts{};
683 findSepsVertices(seps, srcs, dsts);
686 int count_vi = 0, count_vk = 0;
687 for(
const auto &s : dsts) {
696 LongSimplexId const vert2Seps = count_vi > count_vk ? q[0] : q[2];
697 LongSimplexId const vert1Sep = count_vi > count_vk ? q[2] : q[0];
699 std::vector<size_t> borderseps{};
700 for(
size_t j = 0; j < seps.size(); ++j) {
701 if(dsts[j] == vert2Seps && srcs[j] == q[1]) {
702 borderseps.emplace_back(seps[j]);
706 if(borderseps.size() < 2) {
712 std::vector<SimplexId>
const boundi{criticalPointsIdentifier_[q[0]]};
713 std::vector<SimplexId>
const boundk{criticalPointsIdentifier_[q[2]]};
714 std::array<std::vector<float>, 6> outputDists{};
717 criticalPointsIdentifier_[q[0]], triangulation, outputDists[0], boundk);
719 criticalPointsIdentifier_[q[2]], triangulation, outputDists[1], boundi);
721 auto inf = std::numeric_limits<float>::infinity();
722 std::vector<float> sum(outputDists[0].size(), inf);
724 for(
size_t j = 0; j < sum.size(); ++j) {
725 auto m = outputDists[0][j];
726 auto n = outputDists[1][j];
727 if(m == inf || n == inf) {
731 sum[j] = m + n + std::abs(m - n);
737 triangulation.getVertexPoint(a, x, y, z);
738 outputPoints_.emplace_back(x);
739 outputPoints_.emplace_back(y);
740 outputPoints_.emplace_back(z);
741 outputPointsIds_.emplace_back(a);
742 outputPointsTypes_.emplace_back(type);
743 outputPointsCells_.emplace_back(idx);
744 return outputPointsIds_.size() - 1;
747 auto v0 = std::min_element(sum.begin(), sum.end()) - sum.begin();
748 auto v0Pos =
static_cast<LongSimplexId>(insertNewPoint(v0, i, 3));
752 std::vector<SimplexId>
const bounds{criticalPointsIdentifier_[q[0]],
753 criticalPointsIdentifier_[q[1]],
754 criticalPointsIdentifier_[q[2]]};
756 auto m0Pos = sepMids_[borderseps[0]];
757 auto m1Pos = sepMids_[borderseps[1]];
758 auto m0 = outputPointsIds_[m0Pos];
759 auto m1 = outputPointsIds_[m1Pos];
762 outputDists[2], bounds);
767 std::fill(sum.begin(), sum.end(), inf);
769 for(
size_t j = 0; j < sum.size(); ++j) {
770 auto m = outputDists[2][j];
771 auto n = outputDists[3][j];
772 auto o = outputDists[4][j];
773 if(m == inf || n == inf || o == inf) {
777 sum[j] = m + n + o + std::abs(m - n) + std::abs(m - o) + std::abs(n - o);
780 auto v1 = std::min_element(sum.begin(), sum.end()) - sum.begin();
781 auto v1Pos =
static_cast<LongSimplexId>(insertNewPoint(v1, i, 4));
782 std::fill(sum.begin(), sum.end(), inf);
784 for(
size_t j = 0; j < sum.size(); ++j) {
785 auto m = outputDists[2][j];
786 auto n = outputDists[3][j];
787 auto o = outputDists[5][j];
788 if(m == inf || n == inf || o == inf) {
792 sum[j] = m + n + o + std::abs(m - n) + std::abs(m - o) + std::abs(n - o);
795 auto v2 = std::min_element(sum.begin(), sum.end()) - sum.begin();
796 auto v2Pos =
static_cast<LongSimplexId>(insertNewPoint(v2, i, 4));
798 outputSubd.emplace_back(Quad{vert2Seps, m0Pos, v1Pos, v0Pos});
799 outputSubd.emplace_back(Quad{vert2Seps, m1Pos, v2Pos, v0Pos});
800 outputSubd.emplace_back(Quad{q[1], m0Pos, v1Pos, vert1Sep});
801 outputSubd.emplace_back(Quad{q[1], m1Pos, v2Pos, vert1Sep});
802 outputSubd.emplace_back(Quad{vert1Sep, v1Pos, v0Pos, v2Pos});
807template <
typename triangulationType>
808int ttk::MorseSmaleQuadrangulation::subdivise(
809 const triangulationType &triangulation) {
812 sepMids_.resize(sepBegs_.size());
814 for(
size_t i = 0; i < sepMids_.size(); ++i) {
816 sepMids_[i] = outputPoints_.size() / 3;
817 findSeparatrixMiddle(sepBegs_[i], sepEnds_[i], triangulation);
818 outputPointsCells_.emplace_back(i);
822 std::vector<size_t>
const cellBary(outputCells_.size());
824 std::array<std::vector<float>, 4> outputDists{};
827 decltype(outputCells_) outputSubd{};
828 outputSubd.reserve(4 * outputCells_.size());
830 for(
size_t i = 0; i < outputCells_.size(); ++i) {
831 auto q = outputCells_[i];
832 auto seps = quadSeps_[i].second;
839 std::vector<LongSimplexId> sepMids(seps.size());
840 std::vector<SimplexId> midsNearestVertex(seps.size());
841 for(
size_t j = 0; j < seps.size(); ++j) {
842 sepMids[j] = sepMids_[seps[j]];
843 midsNearestVertex[j] = outputPointsIds_[sepMids_[seps[j]]];
849 std::vector<SimplexId>
const bounds{
850 criticalPointsIdentifier_[q[0]], criticalPointsIdentifier_[q[1]],
851 criticalPointsIdentifier_[q[2]], criticalPointsIdentifier_[q[3]]};
854 std::vector<bool> mask(morseSeg_.size(),
false);
856 for(
size_t j = 0; j < morseSeg_.size(); ++j) {
857 if(morseSeg_[j] == quadSeps_[i].first) {
862 for(
const auto s : seps) {
863 for(
size_t j = sepBegs_[s]; j <= sepEnds_[s]; ++j) {
864 if(sepCellDims_[j] == 1) {
865 auto e = sepCellIds_[j];
867 triangulation.getEdgeVertex(e, 0, e0);
868 triangulation.getEdgeVertex(e, 1, e1);
875#ifdef TTK_ENABLE_OPENMP
876#pragma omp parallel for num_threads(threadNumber_)
878 for(
size_t j = 0; j < outputDists.size(); ++j) {
880 outputDists.at(j), std::vector<SimplexId>(), mask);
883 auto inf = std::numeric_limits<float>::infinity();
884 std::vector<float> sum(outputDists[0].size(), inf);
886#ifdef TTK_ENABLE_OPENMP
887#pragma omp parallel for num_threads(threadNumber_)
889 for(
size_t j = 0; j < sum.size(); ++j) {
891 if(morseSeg_[j] != quadSeps_[i].first) {
894 auto m = outputDists[0][j];
895 auto n = outputDists[1][j];
896 auto o = outputDists[2][j];
897 auto p = outputDists[3][j];
898 if(m == inf || n == inf || o == inf || p == inf) {
902 sum[j] = m + n + o + p + std::abs(m - o) + std::abs(n - p);
905 size_t const verticesInCell
908 sum.begin(), sum.end(), std::numeric_limits<float>::infinity());
910 const size_t thresholdVertsInCell{50};
911 if(verticesInCell <= thresholdVertsInCell) {
912 this->
printMsg(
"Small cell detected");
916 if(verticesInCell == 0) {
917 this->
printMsg(
"Barycenter of cell " + std::to_string(i) +
" not found");
919 baryId = outputPointsIds_[sepMids[0]];
921 baryId = std::min_element(sum.begin(), sum.end()) - sum.begin();
927 triangulation.getVertexPoint(baryId, x, y, z);
928 outputPoints_.emplace_back(x);
929 outputPoints_.emplace_back(y);
930 outputPoints_.emplace_back(z);
931 outputPointsIds_.emplace_back(baryId);
932 outputPointsTypes_.emplace_back(2);
933 outputPointsCells_.emplace_back(i);
936 std::vector<LongSimplexId> srcs{};
937 std::vector<LongSimplexId> dsts{};
939 findSepsVertices(seps, srcs, dsts);
941 auto sepsQuadVertex = [&](
const size_t a,
const size_t b) {
942 if(srcs[a] == srcs[b]) {
943 outputSubd.emplace_back(Quad{srcs[a], sepMids[a], baryPos, sepMids[b]});
945 if(dsts[a] == dsts[b]) {
946 outputSubd.emplace_back(Quad{dsts[a], sepMids[a], baryPos, sepMids[b]});
952 sepsQuadVertex(0, 1);
953 sepsQuadVertex(0, 2);
954 sepsQuadVertex(0, 3);
955 sepsQuadVertex(1, 2);
956 sepsQuadVertex(1, 3);
957 sepsQuadVertex(2, 3);
960 subdiviseDegenerateQuads(outputSubd, triangulation);
963 outputCells_ = std::move(outputSubd);
968template <
typename triangulationType>
969bool ttk::MorseSmaleQuadrangulation::checkSurfaceCloseness(
970 const triangulationType &triangulation)
const {
972 bool triangulationClosed{
true};
974 for(
SimplexId i = 0; i < verticesNumber_; ++i) {
975 if(triangulation.isVertexOnBoundary(i)) {
976 triangulationClosed =
false;
981 std::map<std::pair<LongSimplexId, LongSimplexId>, std::set<size_t>>
985 for(
size_t i = 0; i < outputCells_.size(); ++i) {
986 auto q = outputCells_[i];
989 quadEdges[std::make_pair(q[0], q[1])].emplace(i);
991 quadEdges[std::make_pair(q[1], q[0])].emplace(i);
994 quadEdges[std::make_pair(q[1], q[2])].emplace(i);
996 quadEdges[std::make_pair(q[2], q[1])].emplace(i);
999 quadEdges[std::make_pair(q[2], q[3])].emplace(i);
1001 quadEdges[std::make_pair(q[3], q[2])].emplace(i);
1004 quadEdges[std::make_pair(q[3], q[0])].emplace(i);
1006 quadEdges[std::make_pair(q[0], q[3])].emplace(i);
1010 bool quadrangulationClosed{
true};
1011 for(
const auto &e : quadEdges) {
1012 if(e.second.size() < 2) {
1013 quadrangulationClosed =
false;
1019 return triangulationClosed == quadrangulationClosed;
1023template <
typename triangulationType>
1025 const triangulationType &triangulation) {
1030 if(separatriceNumber_ == 0) {
1031 this->printErr(
"Unable to perform quadrangulation without separatrices");
1037 outputPoints_.resize(3 * criticalPointsNumber_);
1038 outputPointsIds_.resize(criticalPointsNumber_);
1039 outputPointsTypes_.resize(criticalPointsNumber_);
1040 outputPointsCells_.resize(criticalPointsNumber_);
1043 for(
SimplexId i = 0; i < criticalPointsNumber_; ++i) {
1044 outputPoints_[3 * i] = criticalPoints_[3 * i];
1045 outputPoints_[3 * i + 1] = criticalPoints_[3 * i + 1];
1046 outputPoints_[3 * i + 2] = criticalPoints_[3 * i + 2];
1047 outputPointsIds_[i] = criticalPointsIdentifier_[i];
1048 outputPointsTypes_[i] = 0;
1049 outputPointsCells_[i] = i;
1056 int const ret = quadrangulate(ndegen, triangulation);
1059 subdivise(triangulation);
1063 this->printErr(
"Unable to generate a quadrangulation from the given "
1064 "Morse-Smale complex");
1068 if(DualQuadrangulation) {
1069 dualQuadrangulate();
1072 if(!checkSurfaceCloseness(triangulation)) {
1074 this->printErr(
"Output surface does not match input surface closeness");
1081 std::string
const s_degen{
1082 ndegen > 0 ?
"(" + std::to_string(ndegen) +
" degenerated) " :
""};
1084 this->
printMsg(
"Produced " + std::to_string(this->outputCells_.size())
1085 +
" quads " + s_degen +
"("
1086 + std::to_string(this->outputPointsIds_.size()) +
" points)",
#define TTK_PSORT(NTHREADS,...)
Parallel sort macro.
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
virtual int preconditionBoundaryVertices()
virtual int preconditionVertexNeighbors()
virtual SimplexId getNumberOfVertices() const
virtual int preconditionVertexTriangles()
Subdivise a triangulation according to triangle barycenter.
void preconditionTriangulation(AbstractTriangulation *const triangulation)
int execute(const triangulationType &inputTriangl, ExplicitTriangulation &outputTriangl)
Minimalist debugging class.
void setDebugMsgPrefix(const std::string &prefix)
TTK processing package for the topological simplification of scalar data.
std::vector< float > outputPoints_
std::vector< SimplexId > outputPointsCells_
std::vector< Quad > outputCells_
std::vector< SimplexId > outputPointsIds_
void setDualQuadrangulation(const bool input)
std::vector< SimplexId > outputPointsTypes_
BarycentricSubdivision bs
void setShowResError(const bool value)
MorseSmaleQuadrangulation()
void setSeparatrices(const unsigned int number, void *const cellIds, void *const cellDims, void *const mask, void *const points)
void preconditionTriangulation(AbstractTriangulation *const triangl)
void setCriticalPoints(const unsigned int number, void *const points, void *const ids, void *const cellIds, void *const type)
int execute(const triangulationType &triangulation)
int shortestPath(const SimplexId source, const triangulationType &triangulation, std::vector< T > &outputDists, const std::vector< SimplexId > &bounds=std::vector< SimplexId >(), const std::vector< bool > &mask=std::vector< bool >())
Compute the Dijkstra shortest path from source.
T distance(const T *p0, const T *p1, const int &dimension=3)
long long int LongSimplexId
Identifier type for simplices of any dimension.
int SimplexId
Identifier type for simplices of any dimension.
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/|__ _|"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)