109 template <
typename dataType,
typename triangulationType>
111 const size_t vectorsMTime,
112 const triangulationType &triangulation) {
116 return this->dcvf_.
buildField<dataType, triangulationType>(triangulation);
119 template <
typename dataType,
typename triangulationType>
121 const bool storePlotPoints,
122 std::vector<PlotPoint> &listOfPlotPoints,
123 const triangulationType &triangulation) {
126 std::array<std::vector<SimplexId>, 4> criticalCellsByDim;
129 int numCriticalPoints = criticalCellsByDim[0].size()
130 + criticalCellsByDim[1].size()
131 + criticalCellsByDim[2].size();
132 int numSinks = criticalCellsByDim[0].size();
133 int numSources = criticalCellsByDim[2].size();
134 int orbitsAdded{0}, orbitsRemoved{0};
135 double weightThres{-1000000};
136 if(numCriticalPoints < criticalThreshold)
139 std::vector<CandidatePair> pairs;
143 pairs, criticalCellsByDim[1], triangulation);
146 pairs, criticalCellsByDim[dim - 1], triangulation);
147 }
else if(dim == 3) {
148 this->
printErr(
"This filter can not simplify for 3D yet.");
153 const auto orderPairs
155 return a.
weight > b.weight;
160 = std::priority_queue<CandidatePair, std::vector<CandidatePair>,
161 decltype(orderPairs)>;
162 pqType options{orderPairs};
163 for(
auto pair : pairs) {
168 while(!options.empty()
169 and numCriticalPoints - 2
170 >=
static_cast<int>(criticalThreshold)) {
174 if(bestOption.
type == 0) {
183 std::vector<SimplexId> saddle{bestOption.
death};
186 pairs, saddle, triangulation);
189 pairs, saddle, triangulation);
191 for(
auto pair : pairs) {
198 }
else if(bestOption.
type == 2) {
207 std::vector<SimplexId> saddle{bestOption.
birth};
210 pairs, saddle, triangulation);
213 pairs, saddle, triangulation);
215 for(
auto pair : pairs) {
223 std::vector<Cell> vpath;
225 if(bestOption.
type == 0) {
226 vpath.emplace_back(
Cell(1, bestOption.
death));
227 }
else if(bestOption.
type == 2) {
228 vpath.emplace_back(
Cell(1, bestOption.
birth));
233 bestOption.
nextCell, vpath, triangulation,
false);
236 bestOption.
nextCell, vpath, triangulation,
false);
238 if(bestOption.
type == 0) {
240 != vpath.back().id_) {
243 std::vector<SimplexId> saddle{bestOption.
death};
246 pairs, saddle, triangulation);
249 pairs, saddle, triangulation);
251 for(
auto pair : pairs) {
257 }
else if(bestOption.
type == 2) {
259 != vpath.back().id_) {
262 std::vector<SimplexId> saddle{bestOption.
birth};
265 pairs, saddle, triangulation);
268 pairs, saddle, triangulation);
270 for(
auto pair : pairs) {
283 = std::max(weightThres,
static_cast<double>(bestOption.
weight));
286 if(storePlotPoints) {
287 listOfPlotPoints.emplace_back(
288 numCriticalPoints, numSinks, numSources, weightThres);
289 listOfPlotPoints.back().orbitsAdded = orbitsAdded;
290 listOfPlotPoints.back().orbitsRemoved = orbitsRemoved;
294 if(bestOption.
type == 0) {
296 }
else if(bestOption.
type == 2) {
303 orbitsRemoved = orbitsRemoved + bestOption.
alternations;
306 if(storePlotPoints) {
307 listOfPlotPoints.emplace_back(
308 numCriticalPoints - 2, numSinks, numSources, weightThres);
309 listOfPlotPoints.back().orbitsAdded = orbitsAdded;
310 listOfPlotPoints.back().orbitsRemoved = orbitsRemoved;
320 numCriticalPoints -= 2;
328 numCriticalPoints -= 2;
333 this->
printMsg(
"Simplified to " + std::to_string(numCriticalPoints)
334 +
" critical point(s)",
351 this->dcvf_ = std::move(
dcvf);
360 return std::move(this->dcvf_);
373 template <
typename dataType,
typename triangulationType>
374 std::vector<std::vector<CandidatePair>>
376 const triangulationType &triangulation)
const;
394 template <
typename dataType,
395 typename triangulationType,
399 std::vector<std::vector<CandidatePair>>
401 const GFS &getFaceStar,
402 const GFSN &getFaceStarNumber,
403 const OB &isOnBoundary,
404 const triangulationType &triangulation,
405 const dataType dummyVariable)
const;
414 template <
typename dataType,
typename triangulationType>
416 const std::vector<SimplexId> &criticalEdges,
417 const triangulationType &triangulation)
const;
426 template <
typename dataType,
typename triangulationType>
428 const std::vector<SimplexId> &criticalSaddles,
429 const triangulationType &triangulation)
const;
453 const std::vector<CandidatePair> &pairs,
454 const std::array<std::vector<SimplexId>, 4> &criticalCellsByDim,
455 const std::vector<bool> &pairedMinima,
456 const std::vector<bool> &paired1Saddles,
457 const std::vector<bool> &paired2Saddles,
458 const std::vector<bool> &pairedMaxima)
const;
463 int pathSize = vpath.size();
466 int previousDim = vpath[1].dim_;
467 int previousSecondDim = vpath[2].dim_;
468 for(
int i = 1; i < pathSize; i++) {
470 if(vpath[i].dim_ != previousSecondDim) {
474 if(vpath[i].dim_ != previousDim) {
484template <
typename dataType,
typename triangulationType>
485std::vector<std::vector<ttk::VectorSimplification::CandidatePair>>
487 const std::vector<SimplexId> &criticalEdges,
488 const triangulationType &triangulation)
const {
490 const auto dim = this->
dcvf_.getDimensionality();
491 std::vector<std::vector<CandidatePair>> res(criticalEdges.size());
494#ifdef TTK_ENABLE_OPENMP
495#pragma omp parallel for num_threads(threadNumber_)
497 for(
size_t i = 0; i < criticalEdges.size(); ++i) {
499 const auto sid = criticalEdges[i];
501 const auto followVPath = [
this, dim, sid, &mins,
503 std::vector<Cell> vpath{};
504 vpath.emplace_back(
Cell{1, sid});
506 = this->
dcvf_.getDescendingPath<dataType, triangulationType>(
507 Cell{0, v}, vpath, triangulation,
false);
508 Cell &lastCell = vpath.back();
509 if(lastCell.dim_ == 0 && this->dcvf_.isCellCritical(lastCell)) {
510 auto weight = this->
dcvf_.getPersistence<dataType, triangulationType>(
511 vpath, triangulation);
512 mins.emplace_back(lastCell.id_,
Cell(0, v), sid, 0, weight);
513 mins.back().alternations = alternates;
514 }
else if(lastCell.dim_ == dim && this->dcvf_.isCellCritical(lastCell)) {
516 auto weight = this->
dcvf_.getPersistence<dataType, triangulationType>(
517 vpath, triangulation);
518 mins.emplace_back(sid,
Cell{0, v}, lastCell.
id_, 2, weight);
519 mins.back().alternations = alternates;
522#ifndef TTK_ENABLE_KAMIKAZE
524 if(sid < 0 || sid > triangulation.getNumberOfEdges()) {
525 std::cout <<
"[WARNING] Not valid sid " << sid << std::endl;
531 triangulation.getEdgeVertex(sid, 0, v0);
532 triangulation.getEdgeVertex(sid, 1, v1);
539 if(mins.size() >= 2 && mins[0].type == mins[1].type) {
540 if(mins[0].type == 0 && mins[0].birth == mins[1].birth) {
541 mins[0].generateOrbit =
true;
542 mins[1].generateOrbit =
true;
543 }
else if(mins[0].type == 2 && mins[0].death == mins[1].death) {
544 mins[0].generateOrbit =
true;
545 mins[1].generateOrbit =
true;
553template <
typename dataType,
554 typename triangulationType,
558std::vector<std::vector<ttk::VectorSimplification::CandidatePair>>
560 const std::vector<SimplexId> &criticalCells,
561 const GFS &getFaceStar,
562 const GFSN &getFaceStarNumber,
563 const OB &isOnBoundary,
564 const triangulationType &triangulation,
565 const dataType dummyVariable)
const {
570 const auto dim = this->
dcvf_.getDimensionality();
571 std::vector<std::vector<CandidatePair>> res(criticalCells.size());
574#ifdef TTK_ENABLE_OPENMP
575#pragma omp parallel for num_threads(threadNumber_)
577 for(
size_t i = 0; i < criticalCells.size(); ++i) {
578 const auto sid = criticalCells[i];
581 const auto followVPath = [
this, dim, sid, &maxs,
583 std::vector<Cell> vpath{};
584 vpath.emplace_back(
Cell{dim - 1, sid});
586 = this->
dcvf_.getAscendingPath<dataType, triangulationType>(
587 Cell{dim, v}, vpath, triangulation,
false);
588 Cell &lastCell = vpath.back();
589 if(lastCell.dim_ == dim && this->dcvf_.isCellCritical(lastCell)) {
590 auto weight = this->
dcvf_.getPersistence<dataType, triangulationType>(
591 vpath, triangulation);
592 maxs.emplace_back(sid,
Cell{dim, v}, lastCell.
id_, 2, weight);
593 maxs.back().alternations = alternates;
594 }
else if(lastCell.dim_ == 0 && this->dcvf_.isCellCritical(lastCell)) {
596 auto weight = this->
dcvf_.getPersistence<dataType, triangulationType>(
597 vpath, triangulation);
598 maxs.emplace_back(lastCell.id_,
Cell{dim, v}, sid, 0, weight);
599 maxs.back().alternations = alternates;
603 const auto starNumber = getFaceStarNumber(sid);
605 for(
SimplexId j = 0; j < starNumber; ++j) {
607 getFaceStar(sid, j, cellId);
612 if(!isOnBoundary(sid) && maxs.size() >= 2) {
615 if(maxs.size() >= 2 && maxs[0].type == maxs[1].type) {
616 if(maxs[0].type == 0 && maxs[0].birth == maxs[1].birth) {
617 maxs[0].generateOrbit =
true;
618 maxs[1].generateOrbit =
true;
619 }
else if(maxs[0].type == 2 && maxs[0].death == maxs[1].death) {
620 maxs[0].generateOrbit =
true;
621 maxs[1].generateOrbit =
true;
630template <
typename dataType,
typename triangulationType>
632 std::vector<CandidatePair> &pairs,
633 const std::vector<SimplexId> &criticalEdges,
634 const triangulationType &triangulation)
const {
637 criticalEdges, triangulation);
639 for(
size_t i = 0; i < saddle1ToMinima.size(); ++i) {
640 auto &mins = saddle1ToMinima[i];
642 for(
size_t j = 0; j < mins.size(); ++j) {
643 pairs.emplace_back(mins[j]);
648template <
typename dataType,
typename triangulationType>
650 std::vector<CandidatePair> &pairs,
651 const std::vector<SimplexId> &criticalSaddles,
652 const triangulationType &triangulation)
const {
654 const auto dim = this->
dcvf_.getDimensionality();
661 return triangulation.getTriangleStar(a, i, r);
664 return triangulation.getTriangleStarNumber(a);
667 return triangulation.isTriangleOnBoundary(a);
669 triangulation,
static_cast<dataType
>(0.0))
673 return triangulation.getEdgeStar(a, i, r);
676 return triangulation.getEdgeStarNumber(a);
679 return triangulation.isEdgeOnBoundary(a);
681 triangulation,
static_cast<dataType
>(0.0));
683 for(
size_t i = 0; i < saddle2ToMaxima.size(); ++i) {
684 auto &maxs = saddle2ToMaxima[i];
686 for(
size_t j = 0; j < maxs.size(); ++j) {
687 pairs.emplace_back(maxs[j]);
#define TTK_FORCE_USE(x)
Force the compiler to use the function/method parameter.
AbstractTriangulation is an interface class that defines an interface for efficient traversal methods...
virtual int setThreadNumber(const int threadNumber)
virtual int setDebugLevel(const int &debugLevel)
int printErr(const std::string &msg, const debug::LineMode &lineMode=debug::LineMode::NEW, std::ostream &stream=std::cerr) const
void setFullOrbitSimplification(bool doFullOrbit)
void getDescSaddlePairs(std::vector< CandidatePair > &pairs, const std::vector< SimplexId > &criticalEdges, const triangulationType &triangulation) const
Compute the candidate pairs from descending paths from saddles.
ttk::dcvf::DiscreteVectorField && getField()
void setField(ttk::dcvf::DiscreteVectorField &&dcvf)
Ugly hack to avoid a call to buildField().
std::vector< std::vector< CandidatePair > > getSaddle2ToAscPair(const std::vector< SimplexId > &criticalCells, const GFS &getFaceStar, const GFSN &getFaceStarNumber, const OB &isOnBoundary, const triangulationType &triangulation, const dataType dummyVariable) const
Follow the ascending 1-separatrices to compute the saddles -> extrema association.
int buildField(const void *const vectors, const size_t vectorsMTime, const triangulationType &triangulation)
bool isAlternatingVpath(std::vector< Cell > &vpath)
Determine if the VPath has 'alternating' behavior of dimension ex: 0-1 to 1-2.
dcvf::DiscreteVectorField dcvf_
int performSimplification(const int criticalThreshold, const bool storePlotPoints, std::vector< PlotPoint > &listOfPlotPoints, const triangulationType &triangulation)
void preconditionTriangulation(AbstractTriangulation *const data)
void getAscSaddlePairs(std::vector< CandidatePair > &pairs, const std::vector< SimplexId > &criticalSaddles, const triangulationType &triangulation) const
Compute the candidate pairs from ascending paths from saddles.
std::vector< std::vector< CandidatePair > > getSaddle1ToDescPair(const std::vector< SimplexId > &criticalEdges, const triangulationType &triangulation) const
Follow the descending 1-separatrices to compute the saddles -> extrema association.
void displayStats(const std::vector< CandidatePair > &pairs, const std::array< std::vector< SimplexId >, 4 > &criticalCellsByDim, const std::vector< bool > &pairedMinima, const std::vector< bool > &paired1Saddles, const std::vector< bool > &paired2Saddles, const std::vector< bool > &pairedMaxima) const
Print number of pairs, critical cells per dimension & unpaired cells.
TTK discreteVectorField processing package.
int reverseAscendingPath(const std::vector< Cell > &vpath, const triangulationType &triangulation) const
bool isCellCritical(const int cellDim, const SimplexId cellId) const
int getCriticalPoints(std::array< std::vector< SimplexId >, 4 > &criticalCellsByDim, const triangulationType &triangulation) const
int getAscendingPath(const Cell &cell, std::vector< Cell > &vpath, const triangulationType &triangulation, const bool stopOnCycle) const
int buildField(const triangulationType &triangulation)
void setReverseFullOrbit(bool data)
void preconditionTriangulation(AbstractTriangulation *const data)
int reverseAlternatingPath(const std::vector< Cell > &vpath, const triangulationType &triangulation) const
int getDescendingPath(const Cell &cell, std::vector< Cell > &vpath, const triangulationType &triangulation, const bool stopOnCycle) const
void setInputVectorField(const void *const data, const size_t mTime)
int getDimensionality() const
int reverseDescendingPath(const std::vector< Cell > &vpath, const triangulationType &triangulation) const
TTK base package defining the standard types.
int SimplexId
Identifier type for simplices of any dimension.
Candidate pair struct for information of pairs connected by V-Paths We need to know the start and end...
CandidatePair(SimplexId b, Cell next, SimplexId d, int t, float w)
PlotPoint(SimplexId num, SimplexId sinks, SimplexId sources, double w)
printMsg(debug::output::BOLD+" | | | | | . \\ | | (__| | / __/| |_| / __/| (_) |"+debug::output::ENDCOLOR, debug::Priority::PERFORMANCE, debug::LineMode::NEW, stream)