75 std::vector<int> &mdtTreePointComponentId,
76 std::vector<PointType> &mdtTreePointType,
77 std::vector<double> &mdtTreePointLowInterval,
78 std::vector<double> &mdtTreePointUpInterval,
79 std::vector<int> &mdtTreeEdgeSwitchable,
80 const std::vector<int> &mdtExtremumParentSaddle,
81 const std::vector<int> &mdtSaddleParentSaddle,
82 const std::vector<bool> &isExtremumSimplified,
83 const std::vector<bool> &isSaddleSimplified,
84 const std::vector<std::pair<double, double>> &extremumInterval,
85 const std::vector<std::pair<int, int>> &mandatorySaddleVertices,
86 const int extremaNumber,
87 const int saddleNumber,
91 const double globalOtherExtremumValue)
const {
93 const std::string treeName
98 mdtTreePointComponentId.clear();
99 mdtTreePointComponentId.reserve(extremaNumber + saddleNumber + 1);
100 mdtTreePointType.clear();
101 mdtTreePointType.reserve(extremaNumber + saddleNumber + 1);
102 mdtTreePointLowInterval.clear();
103 mdtTreePointLowInterval.reserve(extremaNumber + saddleNumber + 1);
104 mdtTreePointUpInterval.clear();
105 mdtTreePointUpInterval.reserve(extremaNumber + saddleNumber + 1);
106 mdtTreeEdgeSwitchable.clear();
109 std::vector<int> saddleGraphVertex(saddleNumber, -1);
111 for(
int i = 0; i < extremaNumber; i++) {
113 if(isExtremumSimplified[i])
116 int const extremumGraphPoint = mdtTree.
addVertex();
117 mdtTreePointComponentId.push_back(i);
118 mdtTreePointType.push_back(extremumType);
120 mdtTreePointLowInterval.push_back(extremumInterval[i].first);
121 mdtTreePointUpInterval.push_back(extremumInterval[i].second);
123 int const parentSaddle = mdtExtremumParentSaddle[i];
125 if(parentSaddle == -1)
128 if(saddleGraphVertex[parentSaddle] == -1) {
129 saddleGraphVertex[parentSaddle] = mdtTree.
addVertex();
130 mdtTreePointComponentId.push_back(parentSaddle);
131 mdtTreePointType.push_back(saddleType);
132 int const lowerVertex = mandatorySaddleVertices[parentSaddle].first;
133 int const upperVertex = mandatorySaddleVertices[parentSaddle].second;
138 mdtTree.
addEdge(saddleGraphVertex[parentSaddle], extremumGraphPoint);
140 mdtTreeEdgeSwitchable.push_back(0);
145 this->
printWrn(
"Mandatory " + treeName +
" empty.");
153 mdtTreePointComponentId.push_back(-1);
154 mdtTreePointType.push_back(otherExtremumType);
155 mdtTreePointLowInterval.push_back(globalOtherExtremumValue);
156 mdtTreePointUpInterval.push_back(globalOtherExtremumValue);
158 mdtTreeEdgeSwitchable.push_back(0);
159 this->
printWrn(
"Mandatory " + treeName +
" with only one minimum.");
164 for(
int i = 0; i < saddleNumber; i++) {
167 if(isSaddleSimplified[i]) {
171 if(saddleGraphVertex[i] == -1) {
172 saddleGraphVertex[i] = mdtTree.
addVertex();
173 mdtTreePointComponentId.push_back(i);
174 mdtTreePointType.push_back(saddleType);
175 int const lowerVertex = mandatorySaddleVertices[i].first;
176 int const upperVertex = mandatorySaddleVertices[i].second;
181 int const parentSaddle = mdtSaddleParentSaddle[i];
184 if(parentSaddle != i) {
186 if(saddleGraphVertex[parentSaddle] == -1) {
187 saddleGraphVertex[parentSaddle] = mdtTree.
addVertex();
188 mdtTreePointComponentId.push_back(parentSaddle);
189 mdtTreePointType.push_back(saddleType);
190 int const lowerVertex = mandatorySaddleVertices[parentSaddle].first;
191 int const upperVertex = mandatorySaddleVertices[parentSaddle].second;
196 mdtTree.
addEdge(saddleGraphVertex[parentSaddle], saddleGraphVertex[i]);
198 mdtTreeEdgeSwitchable.push_back(
201 int const globalOtherExtremumGraphPoint = mdtTree.
addVertex();
202 mdtTreePointComponentId.push_back(-1);
203 mdtTreePointType.push_back(otherExtremumType);
204 mdtTreePointLowInterval.push_back(globalOtherExtremumValue);
205 mdtTreePointUpInterval.push_back(globalOtherExtremumValue);
206 mdtTree.
addEdge(globalOtherExtremumGraphPoint, saddleGraphVertex[i]);
207 mdtTreeEdgeSwitchable.push_back(0);
213 this->
printMsg(
"Building of the mandatory " + treeName +
"");
217 this->
printMsg(
"List of mandatory " + treeName +
" graph points:",
220 std::stringstream msg{};
221 msg <<
" (" << std::setw(3) << std::right << i <<
") ";
222 msg << std::setw(12) << std::right;
223 switch(mdtTreePointType[i]) {
231 msg <<
"Join Saddle";
234 msg <<
"Split Saddle";
239 msg <<
" id = " << std::setw(3) << mdtTreePointComponentId[i];
240 msg <<
" I = [ " << mdtTreePointLowInterval[i];
241 msg <<
" ; " << mdtTreePointUpInterval[i];
249 std::stringstream msg{};
250 msg <<
" (" << std::setw(3) << std::right << i <<
") ";
252 msg << std::setw(3) << std::right
255 msg << std::setw(3) << std::left
331 const Graph &mdtTree,
332 const std::vector<PointType> &mdtTreePointType,
333 const std::vector<double> &mdtTreePointLowInterval,
334 const std::vector<double> &mdtTreePointUpInterval,
335 std::vector<double> &xCoord,
336 std::vector<double> &yCoord)
const {
342 const double range = rangeMax - rangeMin;
345 int rootGraphPointId = -1;
347 for(
size_t i = 0; i < mdtTreePointType.size(); i++) {
349 rootGraphPointId = i;
354 for(
size_t i = 0; i < mdtTreePointType.size(); i++) {
356 rootGraphPointId = i;
361 if(rootGraphPointId == -1) {
366 int downRootPointId = -1;
373 if(downRootPointId == -1) {
378 xCoord.resize(numberOfPoints);
379 yCoord.resize(numberOfPoints);
382 std::vector<std::pair<double, double>> xInterval(numberOfPoints);
383 xInterval[rootGraphPointId].first = -0.5 * (double)numberOfPoints;
384 xInterval[rootGraphPointId].second = 0.5 * (double)numberOfPoints;
386 std::vector<std::pair<int, double>> xOrder(numberOfPoints);
388 std::queue<int> graphPointQueue;
389 graphPointQueue.push(rootGraphPointId);
391 while(!graphPointQueue.empty()) {
393 int const graphPoint = graphPointQueue.front();
394 graphPointQueue.pop();
398 int numberOfDownEdges = 0;
399 for(
int i = 0; i < numberOfEdges; i++) {
406 xOrder[graphPoint].first = graphPoint;
407 xOrder[graphPoint].second
408 = (xInterval[graphPoint].second + xInterval[graphPoint].first) * 0.5;
410 if(numberOfDownEdges == 0)
413 int downPointCount = 0;
415 for(
int i = 0; i < numberOfEdges; i++) {
417 int downGraphPoint = -1;
422 if(downGraphPoint == -1)
425 xInterval[downGraphPoint].first
426 = xInterval[graphPoint].first
427 + ((xInterval[graphPoint].second - xInterval[graphPoint].first)
428 * (
double)downPointCount / (double)numberOfDownEdges);
429 xInterval[downGraphPoint].second
430 = xInterval[graphPoint].first
431 + ((xInterval[graphPoint].second - xInterval[graphPoint].first)
432 * (
double)(downPointCount + 1) / (
double)numberOfDownEdges);
435 graphPointQueue.push(downGraphPoint);
440 for(
int i = 0; i < numberOfPoints; i++) {
442 = ((0.5 * (mdtTreePointLowInterval[i] + mdtTreePointUpInterval[i]))
450 std::sort(xOrder.begin(), xOrder.end(), xCoordCmp);
453 for(
int i = 0; i < numberOfPoints; i++) {
454 if(xOrder[i].first != rootGraphPointId) {
455 xCoord[xOrder[i].first]
456 = (double)pointCount * (1.0 / ((
int)numberOfPoints - 2.0));
461 xCoord[rootGraphPointId] = xCoord[downRootPointId];
463 const std::string treeName
466 this->
printMsg(
"Planar layout for mandatory " + treeName +
": root point ("
467 + std::to_string(downRootPointId) +
")",
470 for(
int i = 0; i < numberOfPoints; i++) {
471 std::stringstream msg;
472 msg <<
" (" << i <<
") :"
473 <<
" x = " << xCoord[i] <<
" y = " << yCoord[i];
542 std::vector<int> &mandatoryExtremum,
543 std::vector<std::pair<double, double>> &criticalInterval)
const {
547#ifndef TTK_ENABLE_KAMIKAZE
560 size_t const extremumNumber = extremumList.size();
561 std::vector<int> vertexId(extremumNumber);
562 std::vector<double> vertexValue(extremumNumber);
563 std::vector<int>
const superArcId(extremumNumber);
565 std::vector<int> subTreeSuperArcId;
568 mandatoryExtremum.clear();
569 criticalInterval.clear();
572 std::vector<bool> isSuperArcAlreadyVisited(
578 for(
size_t i = 0; i < extremumNumber; i++) {
580 bool isMandatory =
true;
582 vertexId[i] = extremumList[i];
586 int const secondTreeSuperArcId
590 int rootSuperArcId = -1;
591 if(!isSuperArcAlreadyVisited[secondTreeSuperArcId]) {
593 &secondTree, secondTreeSuperArcId, vertexValue[i]);
600 subTreeSuperArcId.clear();
601 std::queue<int> superArcQueue;
602 superArcQueue.push(rootSuperArcId);
603 while(isMandatory && (!superArcQueue.empty())) {
604 int const spaId = superArcQueue.front();
606 if(isSuperArcAlreadyVisited[spaId]) {
610 int const numberOfDownSuperArcs
612 if(numberOfDownSuperArcs > 0) {
613 for(
int j = 0; j < numberOfDownSuperArcs; j++) {
618 subTreeSuperArcId.push_back(spaId);
626 mandatoryExtremum.push_back(vertexId[i]);
629 criticalInterval.emplace_back(vertexValue[i], vertexValue[i]);
630 for(
int j = 0; j < (int)subTreeSuperArcId.size(); j++) {
631 isSuperArcAlreadyVisited[subTreeSuperArcId[j]] =
true;
634 double const downNodeValue = secondTree.
getNodeScalar(downNodeId);
636 if(downNodeValue < criticalInterval.back().first) {
637 criticalInterval.back().first = downNodeValue;
640 if(downNodeValue > criticalInterval.back().second) {
641 criticalInterval.back().second = downNodeValue;
648 while((spaId != -1) && !(isSuperArcAlreadyVisited[spaId])) {
649 isSuperArcAlreadyVisited[spaId] =
true;
691#ifdef TTK_ENABLE_OPENMP
698 this->
printMsg(
"Computed " + std::to_string(mandatoryExtremum.size())
699 +
" mandatory " + pt,
703 for(
size_t i = 0; i < mandatoryExtremum.size(); i++) {
704 std::stringstream msg;
705 msg <<
" -> " << pt <<
" (" << std::setw(3) << std::right << i <<
") ";
707 <<
"Vertex " << std::setw(9) << std::left << mandatoryExtremum[i];
708 msg <<
" \tInterval [ " << std::setw(12) << std::right
709 << criticalInterval[i].first <<
" ; " << std::setprecision(9)
710 << std::setw(11) << std::left << criticalInterval[i].second <<
" ]";
722 const std::vector<int> &mandatoryExtremumVertex,
723 std::vector<std::pair<int, int>> &mandatorySaddleVertex,
724 std::vector<std::vector<int>> &mandatoryMergedExtrema) {
743 const unsigned int extremaNumber = mandatoryExtremumVertex.size();
745 std::vector<int> upperSaddleList;
746 std::vector<int> lowerSaddleList;
751 std::vector<std::vector<int>> lowerToUpperLinks;
752 std::vector<std::vector<int>> upperToLowerLinks;
754 std::vector<std::vector<int>> mergedExtrema;
762#ifdef TTK_ENABLE_OPENMP
765 for(
int i = 0; i < (int)mandatoryExtremumVertex.size(); i++) {
773 bool multipleSaddleFound;
776 multipleSaddleFound =
false;
779#ifdef TTK_ENABLE_OPENMP
780#pragma omp critical(upperTreeTransverse)
784 if(++upperTransverse[upperSuperArcId]) {
788 if(upperTransverse[upperSuperArcId] > 1) {
789 multipleSaddleFound =
true;
798 if(upperSuperArcId == -1) {
802 if(!multipleSaddleFound) {
805#ifdef TTK_ENABLE_OPENMP
808 upperSaddleList.push_back(saddleId);
811 }
while(!(saddleFound || rootReached));
814 multipleSaddleFound =
false;
817#ifdef TTK_ENABLE_OPENMP
818#pragma omp critical(lowerTreeTransverse)
822 if(++lowerTransverse[lowerSuperArcId]) {
826 if(lowerTransverse[lowerSuperArcId] > 1) {
827 multipleSaddleFound =
true;
836 if(lowerSuperArcId == -1) {
840 if(!multipleSaddleFound) {
843#ifdef TTK_ENABLE_OPENMP
846 lowerSaddleList.push_back(saddleId);
849 }
while(!(saddleFound || rootReached));
856#ifdef TTK_ENABLE_OPENMP
857#pragma omp parallel num_threads(threadNumber_)
862#ifdef TTK_ENABLE_OPENMP
865 for(
int i = 0; i < (int)upperTransverse.size(); i++) {
866 upperTransverse[i] = -1;
869#ifdef TTK_ENABLE_OPENMP
872 for(
int i = 0; i < (int)lowerTransverse.size(); i++) {
873 lowerTransverse[i] = -1;
877#ifdef TTK_ENABLE_OPENMP
880 for(
int i = 0; i < (int)upperSaddleList.size(); i++) {
883 upperTransverse[superArcId] = i;
886#ifdef TTK_ENABLE_OPENMP
889 for(
int i = 0; i < (int)lowerSaddleList.size(); i++) {
892 lowerTransverse[superArcId] = i;
896#ifdef TTK_ENABLE_OPENMP
901#ifdef TTK_ENABLE_OPENMP
905 upperLca.
addNodes(mandatoryExtremumVertex.size()
906 + upperSaddleList.size());
909#ifdef TTK_ENABLE_OPENMP
913 lowerLca.
addNodes(mandatoryExtremumVertex.size()
914 + lowerSaddleList.size());
919#ifdef TTK_ENABLE_OPENMP
922 for(
int i = 0; i < (int)mandatoryExtremumVertex.size(); i++) {
927 while((superArcId != -1) && (upperTransverse[superArcId] == -1)) {
931 if(superArcId != -1) {
932 lcaSaddleId = extremaNumber + upperTransverse[superArcId];
936#ifdef TTK_ENABLE_OPENMP
937#pragma omp critical(upperLca)
944 while((superArcId != -1) && (lowerTransverse[superArcId] == -1)) {
948 if(superArcId != -1) {
949 lcaSaddleId = extremaNumber + lowerTransverse[superArcId];
953#ifdef TTK_ENABLE_OPENMP
954#pragma omp critical(lowerLca)
961#ifdef TTK_ENABLE_OPENMP
964 for(
int i = 0; i < (int)upperSaddleList.size(); i++) {
970 }
while((superArcId != -1) && (upperTransverse[superArcId] == -1));
971 if(superArcId != -1) {
972 int const lcaSuccessorSaddleId = extremaNumber + i;
973 int const lcaAncestorSaddleId
974 = extremaNumber + upperTransverse[superArcId];
978#ifdef TTK_ENABLE_OPENMP
979#pragma omp critical(upperLca)
981 upperLca.
getNode(lcaAncestorSaddleId)
986#ifdef TTK_ENABLE_OPENMP
989 for(
int i = 0; i < (int)lowerSaddleList.size(); i++) {
995 }
while((superArcId != -1) && (lowerTransverse[superArcId] == -1));
996 if(superArcId != -1) {
997 int const lcaSuccessorSaddleId = extremaNumber + i;
998 int const lcaAncestorSaddleId
999 = extremaNumber + lowerTransverse[superArcId];
1003#ifdef TTK_ENABLE_OPENMP
1004#pragma omp critical(lowerLca)
1006 lowerLca.
getNode(lcaAncestorSaddleId)
1012#ifdef TTK_ENABLE_OPENMP
1016#ifdef TTK_ENABLE_OPENMP
1020#ifdef TTK_ENABLE_OPENMP
1027 std::vector<std::vector<int>> localLowerToUpperLinks;
1028 std::vector<std::vector<int>> localUpperToLowerLinks;
1030 std::vector<std::vector<int>> localMergedExtrema;
1032 localLowerToUpperLinks.resize(lowerSaddleList.size());
1033 localUpperToLowerLinks.resize(upperSaddleList.size());
1034 localMergedExtrema.resize(lowerSaddleList.size());
1036 unsigned int const kmax = (extremaNumber * (extremaNumber - 1)) / 2;
1038#ifdef TTK_ENABLE_OPENMP
1041 for(
int k = 0; k < (int)kmax; k++) {
1042 unsigned int i = k / extremaNumber;
1043 unsigned int j = k % extremaNumber;
1045 i = extremaNumber - i - 2;
1046 j = extremaNumber - j - 1;
1048 int const uppLCA = upperLca.
query(i, j) - extremaNumber;
1049 int const lowLCA = lowerLca.
query(i, j) - extremaNumber;
1050 localLowerToUpperLinks[lowLCA].push_back(uppLCA);
1051 localUpperToLowerLinks[uppLCA].push_back(lowLCA);
1052 localMergedExtrema[lowLCA].push_back(i);
1053 localMergedExtrema[lowLCA].push_back(j);
1057#ifdef TTK_ENABLE_OPENMP
1061 lowerToUpperLinks.resize(lowerSaddleList.size());
1062 upperToLowerLinks.resize(upperSaddleList.size());
1063 mergedExtrema.resize(lowerSaddleList.size());
1066 for(
unsigned int i = 0; i < localLowerToUpperLinks.size(); i++) {
1067 std::vector<int>::iterator newEnd;
1069 localLowerToUpperLinks[i].
begin(), localLowerToUpperLinks[i].
end());
1070#ifdef TTK_ENABLE_OPENMP
1071#pragma omp critical(lowerToUpperFusion)
1074 lowerToUpperLinks[i].insert(
1075 lowerToUpperLinks[i].
end(),
1076 make_move_iterator(localLowerToUpperLinks[i].
begin()),
1077 make_move_iterator(newEnd));
1079 localLowerToUpperLinks[i].clear();
1081 localLowerToUpperLinks.clear();
1083 for(
unsigned int i = 0; i < localUpperToLowerLinks.size(); i++) {
1084 std::vector<int>::iterator newEnd;
1086 localUpperToLowerLinks[i].
begin(), localUpperToLowerLinks[i].
end());
1087#ifdef TTK_ENABLE_OPENMP
1088#pragma omp critical(upperToLowerFusion)
1091 upperToLowerLinks[i].insert(
1092 upperToLowerLinks[i].
end(),
1093 make_move_iterator(localUpperToLowerLinks[i].
begin()),
1094 make_move_iterator(newEnd));
1096 localUpperToLowerLinks[i].clear();
1098 localUpperToLowerLinks.clear();
1100 for(
unsigned int i = 0; i < localMergedExtrema.size(); i++) {
1101 std::vector<int>::iterator newEnd;
1102 std::sort(localMergedExtrema[i].
begin(), localMergedExtrema[i].
end());
1104 = unique(localMergedExtrema[i].
begin(), localMergedExtrema[i].
end());
1105#ifdef TTK_ENABLE_OPENMP
1106#pragma omp critical(mergedExtremaFusion)
1109 mergedExtrema[i].insert(
1110 mergedExtrema[i].
end(),
1111 make_move_iterator(localMergedExtrema[i].
begin()),
1112 make_move_iterator(newEnd));
1114 localMergedExtrema[i].clear();
1116 localMergedExtrema.clear();
1124 std::vector<bool> isLowerVisited(lowerSaddleList.size(),
false);
1125 std::vector<bool> isUpperVisited(upperSaddleList.size(),
false);
1126 std::vector<std::vector<int>> lowComponent;
1127 std::vector<std::vector<int>> uppComponent;
1128 for(
unsigned int i = 0; i < lowerSaddleList.size(); i++) {
1129 if(!isLowerVisited[i]) {
1131 lowComponent.emplace_back();
1132 uppComponent.emplace_back();
1133 int const componentId =
static_cast<int>(lowComponent.size()) - 1;
1134 lowComponent[componentId].push_back(i);
1135 isLowerVisited[i] =
true;
1137 std::vector<int> nextList;
1138 std::vector<int> currentList;
1139 currentList.push_back(i);
1141 std::vector<bool> *isVisited = &(isUpperVisited);
1142 std::vector<std::vector<int>> *component = &(uppComponent);
1143 std::vector<std::vector<int>> *linkList = &(lowerToUpperLinks);
1144 while(!currentList.empty()) {
1146 for(
unsigned int j = 0; j < currentList.size(); j++) {
1148 for(
unsigned int k = 0; k < (*linkList)[currentList[j]].size(); k++) {
1150 int const neighbor = (*linkList)[currentList[j]][k];
1152 if(!(*isVisited)[neighbor]) {
1154 (*isVisited)[neighbor] =
true;
1155 (*component)[componentId].push_back(neighbor);
1156 nextList.push_back(neighbor);
1161 isVisited = (isVisited == &(isUpperVisited)) ? &(isLowerVisited)
1162 : &(isUpperVisited);
1164 = (component == &(uppComponent)) ? &(lowComponent) : &(uppComponent);
1165 linkList = (linkList == &(lowerToUpperLinks)) ? &(upperToLowerLinks)
1166 : &(lowerToUpperLinks);
1167 currentList.swap(nextList);
1174 int const numberOfComponents =
static_cast<int>(lowComponent.size());
1175 mandatorySaddleVertex.resize(numberOfComponents, std::pair<int, int>(-1, -1));
1176 std::vector<std::vector<int>> mandatoryMergedExtrema_tmp;
1177 mandatoryMergedExtrema_tmp.resize(numberOfComponents, std::vector<int>());
1179 for(
int i = 0; i < numberOfComponents; i++) {
1182 nodeId = lowerSaddleList[lowComponent[i][0]];
1184 for(
unsigned int j = 0; j < lowComponent[i].size(); j++) {
1186 int const nId = lowerSaddleList[lowComponent[i][j]];
1188 double refScalar = 0;
1190 if(nodeScalar < refScalar) {
1195 for(
unsigned int j = 0; j < lowComponent[i].size(); j++) {
1196 mandatoryMergedExtrema_tmp[i].insert(
1197 mandatoryMergedExtrema_tmp[i].
end(),
1198 make_move_iterator(mergedExtrema[lowComponent[i][j]].
begin()),
1199 make_move_iterator(mergedExtrema[lowComponent[i][j]].
end()));
1200 mergedExtrema[lowComponent[i][j]].clear();
1204 nodeId = upperSaddleList[uppComponent[i][0]];
1206 for(
unsigned int j = 0; j < uppComponent[i].size(); j++) {
1208 int const nId = upperSaddleList[uppComponent[i][j]];
1210 double refScalar = 0;
1211 upperTree.
getVertexScalar(mandatorySaddleVertex[i].second, refScalar);
1212 if(nodeScalar > refScalar) {
1219 std::vector<std::pair<int, int>> order;
1220 for(
unsigned int i = 0; i < mandatoryMergedExtrema_tmp.size(); i++) {
1221 std::sort(mandatoryMergedExtrema_tmp[i].
begin(),
1222 mandatoryMergedExtrema_tmp[i].
end());
1223 std::vector<int>::iterator
const newEnd
1224 = unique(mandatoryMergedExtrema_tmp[i].
begin(),
1225 mandatoryMergedExtrema_tmp[i].
end());
1226 mandatoryMergedExtrema_tmp[i].resize(
1227 distance(mandatoryMergedExtrema_tmp[i].
begin(), newEnd));
1228 mandatoryMergedExtrema_tmp[i].shrink_to_fit();
1229 order.emplace_back(i, mandatoryMergedExtrema_tmp[i].size());
1233 std::sort(order.begin(), order.end(), cmp);
1235 mandatoryMergedExtrema.clear();
1236 mandatoryMergedExtrema.resize(mandatoryMergedExtrema_tmp.size());
1237 for(
unsigned int i = 0; i < order.size(); i++) {
1238 mandatoryMergedExtrema_tmp[order[i].first].swap(mandatoryMergedExtrema[i]);
1242#ifdef TTK_ENABLE_OPENMP
1243#pragma omp parallel sections
1246#ifdef TTK_ENABLE_OPENMP
1259#ifdef TTK_ENABLE_OPENMP
1274 const std::string st
1277 this->
printMsg(
"Computed " + std::to_string(mandatorySaddleVertex.size())
1278 +
" mandatory " + st,
1282 for(
size_t i = 0; i < mandatorySaddleVertex.size(); i++) {
1283 std::stringstream msg;
1284 msg <<
" -> " << st <<
" (";
1285 msg << std::setw(3) << std::right << i <<
")";
1286 msg <<
" Vertices <";
1287 msg << std::setw(9) << std::right << mandatorySaddleVertex[i].first
1289 msg << std::setw(9) << std::left << mandatorySaddleVertex[i].second <<
">";
1290 msg <<
" Interval [";
1291 double lowerValue = 0;
1292 double upperValue = 0;
1293 lowerTree.
getVertexScalar(mandatorySaddleVertex[i].first, lowerValue);
1294 upperTree.
getVertexScalar(mandatorySaddleVertex[i].second, upperValue);
1295 msg << std::setw(12) << std::right << lowerValue <<
" ; ";
1296 msg << std::setw(12) << std::left << upperValue <<
"]";
1380 const double normalizedThreshold,
1382 const std::vector<std::pair<std::pair<int, int>,
double>> &extremaSaddlePair,
1383 const std::vector<std::vector<int>> &mergedExtrema,
1384 const int numberOfExtrema,
1385 std::vector<bool> &extremumSimplified,
1386 std::vector<bool> &saddleSimplified,
1387 std::vector<int> &extremumParentSaddle,
1388 std::vector<int> &saddleParentSaddle)
const {
1391 double simplificationThreshold;
1392 if(normalizedThreshold > 1.0)
1394 else if(normalizedThreshold < 0.0)
1395 simplificationThreshold = 0.0;
1397 simplificationThreshold
1400 int extremaSimplifiedNumber = 0;
1401 int saddlesSimplifiedNumber = 0;
1404 extremumSimplified.resize(numberOfExtrema);
1405 fill(extremumSimplified.begin(), extremumSimplified.end(),
false);
1406 for(
size_t i = 0; i < extremaSaddlePair.size(); i++) {
1407 if(extremaSaddlePair[i].second < simplificationThreshold) {
1408 extremumSimplified[extremaSaddlePair[i].first.first] =
true;
1409 extremaSimplifiedNumber++;
1415 saddleSimplified.resize(mergedExtrema.size());
1416 fill(saddleSimplified.begin(), saddleSimplified.end(),
false);
1417 std::vector<int> nonSimplifiedExtremaNumber(mergedExtrema.size(), 0);
1418 extremumParentSaddle.resize(numberOfExtrema);
1419 fill(extremumParentSaddle.begin(), extremumParentSaddle.end(), -1);
1420 saddleParentSaddle.resize(mergedExtrema.size());
1421 fill(saddleParentSaddle.begin(), saddleParentSaddle.end(), -1);
1422 for(
size_t i = 0; i < mergedExtrema.size(); i++) {
1423 saddleParentSaddle[i] = i;
1424 for(
size_t j = 0; j < mergedExtrema[i].size(); j++) {
1425 if(!extremumSimplified[mergedExtrema[i][j]])
1426 nonSimplifiedExtremaNumber[i]++;
1428 if(nonSimplifiedExtremaNumber[i] > 1) {
1431 while(extremumSimplified[mergedExtrema[i][extremum]]) {
1434 if(!(extremumParentSaddle[mergedExtrema[i][extremum]] == -1)) {
1436 int rootSaddleId = extremumParentSaddle[mergedExtrema[i][extremum]];
1437 int lastSaddleId = -1;
1438 while(rootSaddleId != lastSaddleId) {
1439 lastSaddleId = rootSaddleId;
1440 rootSaddleId = saddleParentSaddle[rootSaddleId];
1443 if(!(nonSimplifiedExtremaNumber[i]
1444 > nonSimplifiedExtremaNumber[rootSaddleId])) {
1445 saddleSimplified[i] =
true;
1446 saddlesSimplifiedNumber++;
1450 saddleSimplified[i] =
true;
1451 saddlesSimplifiedNumber++;
1453 if(!saddleSimplified[i]) {
1454 for(
size_t j = 0; j < mergedExtrema[i].size(); j++) {
1455 int const extremaId = mergedExtrema[i][j];
1456 if(!extremumSimplified[extremaId]) {
1458 if(extremumParentSaddle[extremaId] == -1) {
1459 extremumParentSaddle[extremaId] = i;
1462 int rootSaddleId = extremumParentSaddle[extremaId];
1463 int lastSaddleId = -1;
1464 while(rootSaddleId != lastSaddleId) {
1465 lastSaddleId = rootSaddleId;
1466 rootSaddleId = saddleParentSaddle[rootSaddleId];
1469 saddleParentSaddle[rootSaddleId] = i;
1479 "#Simplified " + pt +
": " + std::to_string(extremaSimplifiedNumber)
1480 +
" (threshold value = " + std::to_string(simplificationThreshold) +
")");
1482 if(extremaSimplifiedNumber > 0) {
1484 for(
size_t i = 0; i < extremumSimplified.size(); i++) {
1485 if(extremumSimplified[i]) {
1486 std::stringstream msg;
1487 msg <<
" (" << i <<
")";
1493 const std::string st
1497 "#Simplified " + st +
": " + std::to_string(saddlesSimplifiedNumber)
1498 +
" (threshold value = " + std::to_string(simplificationThreshold) +
")");
1500 if(saddlesSimplifiedNumber > 0) {
1502 for(
size_t i = 0; i < saddleSimplified.size(); i++) {
1503 if(saddleSimplified[i]) {
1504 std::stringstream msg;
1505 msg <<
" (" << i <<
")";