57 const pair<double, double> &intersection,
58 const vector<vector<IntersectionTriangle>> &tetIntersections,
59 std::array<double, 3> &pA,
60 std::array<double, 3> &pB,
62 bool &edgeFiber)
const {
67 for(
int i = 0; i < 3; i++) {
68 if((fabs(intersection.first
69 - tetIntersections[tetId][triangleId].uv_[i].first)
71 && fabs(intersection.second
72 - tetIntersections[tetId][triangleId].uv_[i].second)
74 && fabs(intersection.first
75 - tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].first)
77 && fabs(intersection.second
78 - tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].second)
81 pivotVertexId = (i + 2) % 3;
88 if(pivotVertexId == -1) {
89 for(
int i = 0; i < 3; i++) {
90 if(tetIntersections[tetId][triangleId].uv_[i].first
91 > intersection.first) {
92 if((tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].first
93 <= intersection.first)
94 && (tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].first
95 <= intersection.first)) {
100 if(tetIntersections[tetId][triangleId].uv_[i].first
101 < intersection.first) {
102 if((tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].first
103 >= intersection.first)
104 && (tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].first
105 >= intersection.first)) {
112 if(pivotVertexId == -1) {
113 for(
int i = 0; i < 3; i++) {
114 if(tetIntersections[tetId][triangleId].uv_[i].second
115 > intersection.second) {
116 if((tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].second
117 <= intersection.second)
118 && (tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].second
119 <= intersection.second)) {
124 if(tetIntersections[tetId][triangleId].uv_[i].second
125 < intersection.second) {
126 if((tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].second
127 >= intersection.second)
128 && (tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].second
129 >= intersection.second)) {
137 if(pivotVertexId == -1) {
146 std::array<double, 2> baryCentrics0{}, baryCentrics1{};
147 std::array<double, 2> p{}, p0{}, p1{}, p2{};
149 p[0] = intersection.first;
150 p[1] = intersection.second;
152 p0[0] = tetIntersections[tetId][triangleId].uv_[pivotVertexId].first;
153 p0[1] = tetIntersections[tetId][triangleId].uv_[pivotVertexId].second;
156 = tetIntersections[tetId][triangleId].uv_[(pivotVertexId + 1) % 3].first;
158 = tetIntersections[tetId][triangleId].uv_[(pivotVertexId + 1) % 3].second;
161 = tetIntersections[tetId][triangleId].uv_[(pivotVertexId + 2) % 3].first;
163 = tetIntersections[tetId][triangleId].uv_[(pivotVertexId + 2) % 3].second;
166 p0.data(), p1.data(), p.data(), baryCentrics0, 2);
168 p0.data(), p2.data(), p.data(), baryCentrics1, 2);
170 for(
int i = 0; i < 3; i++) {
171 pA[i] = baryCentrics0[0]
172 * tetIntersections[tetId][triangleId].p_[pivotVertexId][i]
174 * tetIntersections[tetId][triangleId]
175 .p_[(pivotVertexId + 1) % 3][i];
178 for(
int i = 0; i < 3; i++) {
179 pB[i] = baryCentrics1[0]
180 * tetIntersections[tetId][triangleId].p_[pivotVertexId][i]
182 * tetIntersections[tetId][triangleId]
183 .p_[(pivotVertexId + 2) % 3][i];
195 const std::pair<double, double> &intersection,
198 std::vector<std::vector<IntersectionTriangle>> &tetIntersections,
199 std::vector<std::vector<Vertex>> &tetNewVertices)
const {
202 tetId, triangleId0, triangleId1, tetIntersections);
205 if(commonVertexNumber == 2) {
212 SimplexId pivotVertexIda = -1, pivotVertexIdb = -1;
213 std::array<double, 3> p0a{}, p1a{}, p0b{}, p1b{};
216 bool edgeFiber0 =
false;
218 p1a, pivotVertexIda, edgeFiber0);
220 bool edgeFiber1 =
false;
222 p1b, pivotVertexIdb, edgeFiber1);
241 bool vertexA =
false;
242 bool vertexB =
false;
243 if((fabs(p0a[0] - p1a[0]) < PREC_DBL) && (fabs(p0a[1] - p1a[1]) < PREC_DBL)
244 && (fabs(p0a[2] - p1a[2]) < PREC_DBL)) {
247 if((fabs(p0b[0] - p1b[0]) < PREC_DBL) && (fabs(p0b[1] - p1b[1]) < PREC_DBL)
248 && (fabs(p0b[2] - p1b[2]) < PREC_DBL)) {
251 if((vertexA) || (vertexB)) {
256 bool foundA =
false, foundB =
false;
257 std::array<double, 3> pA{}, pB{};
273 if((fabs(pA[0] - p1a[0]) > PREC_DBL_4)
274 || (fabs(pA[1] - p1a[1]) > PREC_DBL_4)
275 || (fabs(pA[2] - p1a[2]) > PREC_DBL_4)) {
289 if((fabs(pA[0] - p0b[0]) > PREC_DBL_4)
290 || (fabs(pA[1] - p0b[1]) > PREC_DBL_4)
291 || (fabs(pA[2] - p0b[2]) > PREC_DBL_4)) {
304 if((fabs(pA[0] - p1b[0]) > PREC_DBL_4)
305 || (fabs(pA[1] - p1b[1]) > PREC_DBL_4)
306 || (fabs(pA[2] - p1b[2]) > PREC_DBL_4)) {
312 if((!pA.size()) || (!pB.size()))
317 tetId, triangleId0, polygonEdgeId0, intersection, pA, pB, pivotVertexIda,
318 newVertexNumber, newTriangleNumber, tetIntersections, tetNewVertices);
323 tetId, triangleId1, polygonEdgeId1, intersection, pA, pB, pivotVertexIdb,
324 newVertexNumber, newTriangleNumber, tetIntersections, tetNewVertices);
334 const std::pair<double, double> &intersection,
335 const std::array<double, 3> &pA,
336 const std::array<double, 3> &pB,
340 std::vector<std::vector<IntersectionTriangle>> &tetIntersections,
341 std::vector<std::vector<Vertex>> &tetNewVertices)
const {
344 if((fabs(tetIntersections[tetId][triangleId].intersection_.first
345 - intersection.first)
347 && (fabs(tetIntersections[tetId][triangleId].intersection_.second
348 - intersection.second)
355 for(
int i = 0; i < 3; i++) {
356 if((fabs(intersection.first
357 - tetIntersections[tetId][triangleId].uv_[i].first)
359 && fabs(intersection.second
360 - tetIntersections[tetId][triangleId].uv_[i].second)
362 && fabs(intersection.first
363 - tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].first)
365 && fabs(intersection.second
366 - tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].second)
373 std::array<double, 3> barypA{}, barypB{};
375 tetIntersections[tetId][triangleId].p_[0].data(),
376 tetIntersections[tetId][triangleId].p_[1].data(),
377 tetIntersections[tetId][triangleId].p_[2].data(), pA.data(), barypA);
380 tetIntersections[tetId][triangleId].p_[0].data(),
381 tetIntersections[tetId][triangleId].p_[1].data(),
382 tetIntersections[tetId][triangleId].p_[2].data(), pB.data(), barypB);
387 std::array<double, 3> A = pA, B = pB;
388 std::array<double, 3> baryA = barypA, baryB = barypB;
389 if(fabs(barypB[(pivotVertexId + 1) % 3])
390 < fabs(barypA[(pivotVertexId + 1) % 3])) {
398 bool isAVertex =
false;
399 for(
int i = 0; i < 3; i++) {
400 if(fabs(baryA[i] - 1) < PREC_DBL) {
405 bool isBVertex =
false;
406 for(
int i = 0; i < 3; i++) {
407 if(fabs(baryB[i] - 1) < PREC_DBL) {
412 if((isAVertex) && (isBVertex))
416 SimplexId const vertexIdA = newVertexNumber;
418 tetNewVertices[tetId].resize(tetNewVertices[tetId].size() + 1);
419 for(
int i = 0; i < 3; i++)
420 tetNewVertices[tetId].back().p_[i] = A[i];
421 tetNewVertices[tetId].back().polygonEdgeId_ = polygonEdgeId;
422 tetNewVertices[tetId].back().uv_.first
423 = baryA[0] * tetIntersections[tetId][triangleId].uv_[0].first
424 + baryA[1] * tetIntersections[tetId][triangleId].uv_[1].first
425 + baryA[2] * tetIntersections[tetId][triangleId].uv_[2].first;
426 tetNewVertices[tetId].back().uv_.second
427 = baryA[0] * tetIntersections[tetId][triangleId].uv_[0].second
428 + baryA[1] * tetIntersections[tetId][triangleId].uv_[1].second
429 + baryA[2] * tetIntersections[tetId][triangleId].uv_[2].second;
430 tetNewVertices[tetId].back().t_
431 = baryA[0] * tetIntersections[tetId][triangleId].t_[0]
432 + baryA[1] * tetIntersections[tetId][triangleId].t_[1]
433 + baryA[2] * tetIntersections[tetId][triangleId].t_[2];
434 tetNewVertices[tetId].back().isIntersectionPoint_ =
true;
436 SimplexId const vertexIdB = newVertexNumber;
438 tetNewVertices[tetId].resize(tetNewVertices[tetId].size() + 1);
439 for(
int i = 0; i < 3; i++)
440 tetNewVertices[tetId].back().p_[i] = B[i];
441 tetNewVertices[tetId].back().polygonEdgeId_ = polygonEdgeId;
442 tetNewVertices[tetId].back().uv_.first
443 = baryB[0] * tetIntersections[tetId][triangleId].uv_[0].first
444 + baryB[1] * tetIntersections[tetId][triangleId].uv_[1].first
445 + baryB[2] * tetIntersections[tetId][triangleId].uv_[2].first;
446 tetNewVertices[tetId].back().uv_.second
447 = baryB[0] * tetIntersections[tetId][triangleId].uv_[0].second
448 + baryB[1] * tetIntersections[tetId][triangleId].uv_[1].second
449 + baryB[2] * tetIntersections[tetId][triangleId].uv_[2].second;
450 tetNewVertices[tetId].back().t_
451 = baryB[0] * tetIntersections[tetId][triangleId].t_[0]
452 + baryB[1] * tetIntersections[tetId][triangleId].t_[1]
453 + baryB[2] * tetIntersections[tetId][triangleId].t_[2];
454 tetNewVertices[tetId].back().isIntersectionPoint_ =
true;
459 (pivotVertexId + 2) % 3, tetNewVertices,
460 newTriangleNumber, tetIntersections);
468 tetId, triangleId, -vertexIdA, -vertexIdB, (pivotVertexId + 2) % 3,
469 tetNewVertices, newTriangleNumber, tetIntersections, &intersection);
473 tetId, triangleId, -vertexIdA, -vertexIdB, (pivotVertexId + 1) % 3,
474 tetNewVertices, newTriangleNumber, tetIntersections, &intersection);
476 (pivotVertexId + 2) % 3, -vertexIdA,
477 tetNewVertices, newTriangleNumber,
478 tetIntersections, &intersection);
483 (pivotVertexId + 2) % 3, -vertexIdB,
484 tetNewVertices, newTriangleNumber,
485 tetIntersections, &intersection);
491 (pivotVertexId + 1) % 3, tetNewVertices,
492 newTriangleNumber, tetIntersections);
496 tetIntersections[tetId][triangleId].intersection_ = intersection;
497 tetIntersections[tetId][triangleId].vertexIds_[0]
498 = tetIntersections[tetId][triangleId].vertexIds_[pivotVertexId];
499 tetIntersections[tetId][triangleId].uv_[0]
500 = tetIntersections[tetId][triangleId].uv_[pivotVertexId];
501 tetIntersections[tetId][triangleId].t_[0]
502 = tetIntersections[tetId][triangleId].t_[pivotVertexId];
503 for(
int i = 0; i < 3; i++)
504 tetIntersections[tetId][triangleId].p_[0][i]
505 = tetIntersections[tetId][triangleId].p_[pivotVertexId][i];
507 tetIntersections[tetId][triangleId].vertexIds_[1] = -vertexIdA;
508 tetIntersections[tetId][triangleId].uv_[1]
509 = tetNewVertices[tetId][vertexIdA - 1].uv_;
510 tetIntersections[tetId][triangleId].t_[1]
511 = tetNewVertices[tetId][vertexIdA - 1].t_;
512 for(
int i = 0; i < 3; i++)
513 tetIntersections[tetId][triangleId].p_[1][i]
514 = tetNewVertices[tetId][vertexIdA - 1].p_[i];
516 tetIntersections[tetId][triangleId].vertexIds_[2] = -vertexIdB;
517 tetIntersections[tetId][triangleId].uv_[2]
518 = tetNewVertices[tetId][vertexIdB - 1].uv_;
519 tetIntersections[tetId][triangleId].t_[2]
520 = tetNewVertices[tetId][vertexIdB - 1].t_;
521 for(
int i = 0; i < 3; i++)
522 tetIntersections[tetId][triangleId].p_[2][i]
523 = tetNewVertices[tetId][vertexIdB - 1].p_[i];
534 const vector<vector<Vertex>> &tetNewVertices,
536 vector<vector<IntersectionTriangle>> &tetIntersections,
537 const pair<double, double> *intersection)
const {
540 tetNewVertices, vertexId0, vertexId1,
546 tetIntersections[tetId].resize(tetIntersections[tetId].size() + 1);
547 tetIntersections[tetId].back().caseId_
548 = tetIntersections[tetId][triangleId].caseId_;
549 tetIntersections[tetId].back().polygonEdgeId_
550 = tetIntersections[tetId][triangleId].polygonEdgeId_;
551 tetIntersections[tetId].back().triangleId_ = -newTriangleNumber;
554 tetIntersections[tetId].back().intersection_ = *intersection;
556 tetIntersections[tetId].back().intersection_.first = -DBL_MAX;
557 tetIntersections[tetId].back().intersection_.second = -DBL_MAX;
563 for(
int i = 0; i < 3; i++) {
567 vertexId = vertexId1;
569 vertexId = vertexId2;
573 tetIntersections[tetId].back().vertexIds_[i]
574 = tetIntersections[tetId][triangleId].vertexIds_[vertexId];
575 tetIntersections[tetId].back().uv_[i]
576 = tetIntersections[tetId][triangleId].uv_[vertexId];
577 tetIntersections[tetId].back().t_[i]
578 = tetIntersections[tetId][triangleId].t_[vertexId];
579 for(
int j = 0; j < 3; j++) {
580 tetIntersections[tetId].back().p_[i][j]
581 = tetIntersections[tetId][triangleId].p_[vertexId][j];
585 tetIntersections[tetId].back().vertexIds_[i] = vertexId;
586 tetIntersections[tetId].back().uv_[i]
587 = tetNewVertices[tetId][(-vertexId) - 1].uv_;
588 tetIntersections[tetId].back().t_[i]
589 = tetNewVertices[tetId][(-vertexId) - 1].t_;
590 for(
int j = 0; j < 3; j++) {
591 tetIntersections[tetId].back().p_[i][j]
592 = tetNewVertices[tetId][(-vertexId) - 1].p_[j];
643 std::vector<std::pair<SimplexId, SimplexId>> &triangles)
const {
651 bool hasFlipped =
false;
661 vector<pair<double, pair<SimplexId, SimplexId>>> localTriangles;
663 std::array<SimplexId, 3> vertexIds{};
675 std::array<double, 3> angles{};
682 for(
int j = 0; j < 3; j++) {
683 if((alpha < 0) || (fabs(angles[j]) < alpha))
684 alpha = fabs(angles[j]);
687 localTriangles.emplace_back(alpha, triangles[i]);
690 const auto FiberSurfaceTriangleCmp
691 = [](
const pair<double, pair<SimplexId, SimplexId>> &t0,
692 const pair<double, pair<SimplexId, SimplexId>> &t1) {
693 return t0.first < t1.first;
696 sort(localTriangles.begin(), localTriangles.end(), FiberSurfaceTriangleCmp);
699 triangles[i] = localTriangles[i].second;
704 std::array<SimplexId, 3> vertexIds{};
716 std::array<double, 3> angles{};
723 for(
int j = 0; j < 3; j++) {
724 if((alpha < 0) || (fabs(angles[j]) < alpha))
725 alpha = fabs(angles[j]);
743 for(
int k = 0; k < 3; k++) {
749 bool isCommon =
false;
751 for(
int l = 0; l < 3; l++) {
752 if(vertexId == vertexIds[l]) {
753 if(commonVertexId0 == -1) {
754 commonVertexId0 = vertexId;
756 commonVertexId1 = vertexId;
762 otherNonCommonVertexId = vertexId;
765 if((commonVertexId0 != -1) && (commonVertexId1 != -1)) {
769 .isIntersectionPoint_)) {
772 for(
int k = 0; k < 3; k++) {
773 if((vertexIds[k] != commonVertexId0)
774 && (vertexIds[k] != commonVertexId1)) {
775 nonCommonVertexId = vertexIds[k];
786 if((nonCommonVertexId != -1) && (otherNonCommonVertexId != -1)) {
788 std::array<double, 3> beta0angles{}, beta1angles{};
797 for(
int k = 0; k < 3; k++) {
798 if((beta0 < 0) || (fabs(beta0angles[j]) < beta0))
799 beta0 = fabs(beta0angles[j]);
809 for(
int k = 0; k < 3; k++) {
810 if((beta1 < 0) || (fabs(beta1angles[j]) < beta1))
811 beta1 = fabs(beta1angles[j]);
814 if((beta0 > alpha) && (beta1 > alpha)) {
819 otherNonCommonVertexId)) {
825 .first])[triangles[i].second]
829 .first])[triangles[i].second]
831 = otherNonCommonVertexId;
833 .first])[triangles[i].second]
841 .first])[triangles[j].second]
845 .first])[triangles[j].second]
847 = otherNonCommonVertexId;
849 .first])[triangles[j].second]
877 const vector<vector<IntersectionTriangle>> &tetIntersections,
878 pair<double, double> &extremity0,
879 pair<double, double> &extremity1)
const {
881 std::array<double, 2> p0{}, p1{}, p{};
882 std::array<double, 2> baryCentrics{};
883 bool isInBetween =
true;
886 for(
int i = 0; i < 3; i++) {
888 p[0] = tetIntersections[tetId][triangleId].uv_[i].first;
889 p[1] = tetIntersections[tetId][triangleId].uv_[i].second;
891 p0[0] = tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].first;
892 p0[1] = tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].second;
894 p1[0] = tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].first;
895 p1[1] = tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].second;
897 if((fabs(p0[0] - p1[0]) < PREC_FLT) && (fabs(p0[1] - p1[1]) < PREC_FLT)) {
899 extremity0.first = p[0];
900 extremity0.second = p[1];
902 extremity1.first = p0[0];
903 extremity1.second = p0[1];
909 for(
int i = 0; i < 3; i++) {
911 p[0] = tetIntersections[tetId][triangleId].uv_[i].first;
912 p[1] = tetIntersections[tetId][triangleId].uv_[i].second;
914 p0[0] = tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].first;
915 p0[1] = tetIntersections[tetId][triangleId].uv_[(i + 1) % 3].second;
917 p1[0] = tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].first;
918 p1[1] = tetIntersections[tetId][triangleId].uv_[(i + 2) % 3].second;
921 p0.data(), p1.data(), p.data(), baryCentrics, 2);
924 for(
int j = 0; j < 2; j++) {
926 if((baryCentrics[j] < -PREC_FLT) || (baryCentrics[j] > 1 + PREC_FLT)) {
932 extremity0.first = p0[0];
933 extremity0.second = p0[1];
935 extremity1.first = p1[0];
936 extremity1.second = p1[1];
1076 SimplexId const initVertexNumber = (*globalVertexList_).size();
1082 vector<vector<SimplexId>> vertexNeighbors((*globalVertexList_).size());
1083 vector<vector<SimplexId>> vertexNeighborsTets((*globalVertexList_).size());
1085 vector<vector<pair<SimplexId, SimplexId>>> vertexTriangleNeighbors(
1086 vertexNeighbors.size());
1092 for(
int k = 0; k < 3; k++) {
1096 vertexTriangleNeighbors[vertexId].resize(
1097 vertexTriangleNeighbors[vertexId].size() + 1);
1098 vertexTriangleNeighbors[vertexId].back().first = -1;
1099 vertexTriangleNeighbors[vertexId].back().second = -1;
1100 vertexNeighborsTets[vertexId].push_back(
1103 for(
int l = 0; l < 3; l++) {
1108 if(vertexTriangleNeighbors[vertexId].back().first == -1) {
1109 vertexTriangleNeighbors[vertexId].back().first = otherVertexId;
1111 vertexTriangleNeighbors[vertexId].back().second = otherVertexId;
1116 m < (
SimplexId)vertexNeighbors[vertexId].size(); m++) {
1117 if(vertexNeighbors[vertexId][m] == otherVertexId) {
1123 vertexNeighbors[vertexId].push_back(otherVertexId);
1131 bool hasMerged =
false;
1133#ifdef TTK_ENABLE_OPENMP
1134#pragma omp parallel for num_threads(threadNumber_)
1142 double minDistance = -1;
1145 for(
int k = 0; k < 3; k++) {
1152 bool areAlreadySnapped =
true;
1153 for(
int l = 0; l < 3; l++) {
1155 != (*globalVertexList_)[vertexId1].p_[l]) {
1157 areAlreadySnapped =
false;
1164 areAlreadySnapped =
true;
1167 if(!areAlreadySnapped) {
1168 double const distance
1172 if((minDistance == -1) || (distance < minDistance)) {
1173 minDistance = distance;
1179 if((minDistance != -1) && (minDistance < distanceThreshold)) {
1183 .vertexIds_[(minimizer + 1) % 3];
1186 vector<SimplexId> commonNeighbors;
1190 l < (
SimplexId)vertexNeighbors[vertexId1].size(); l++) {
1191 if(vertexNeighbors[vertexId0][k]
1192 == vertexNeighbors[vertexId1][l]) {
1193 commonNeighbors.push_back(vertexNeighbors[vertexId0][k]);
1198 if(commonNeighbors.size() == 2) {
1204 SimplexId source = vertexId0, destination = vertexId1;
1208 destination = vertexId0;
1214 bool isCollapsible =
true;
1217 source, destination, commonNeighbors[k],
1218 vertexTriangleNeighbors[commonNeighbors[k]])) {
1219 isCollapsible =
false;
1227 k < (
SimplexId)vertexNeighborsTets[source].size(); k++) {
1228 if((vertexTriangleNeighbors[source][k].first == destination)
1229 || (vertexTriangleNeighbors[source][k].second
1232 tetId0 = vertexNeighborsTets[source][k];
1234 tetId1 = vertexNeighborsTets[source][k];
1239 if(tetId0 == tetId1) {
1240 isCollapsible =
false;
1243#ifdef TTK_ENABLE_OPENMP
1247 for(
int k = 0; k < 3; k++) {
1248 (*globalVertexList_)[destination].p_[k]
1249 = (*globalVertexList_)[source].p_[k];
1268 "Performed edge collapses", 1.0, t.
getElapsedTime(), this->threadNumber_);
1269 this->
printMsg(std::vector<std::vector<std::string>>{
1270 {
"#Vertices removed",
1271 std::to_string(initVertexNumber - (*globalVertexList_).size())}});
1280 vector<Vertex> tmpList = (*globalVertexList_);
1283 tmpList[i].localId_ = i;
1286 const auto FiberSurfaceVertexComparisonX
1288 if(fabs(v0.
p_[0] - v1.p_[0]) < PREC_DBL) {
1290 if(fabs(v0.
p_[1] - v1.p_[1]) < PREC_DBL) {
1292 if(fabs(v0.
p_[2] - v1.p_[2]) < PREC_DBL) {
1297 return v0.
p_[2] < v1.p_[2];
1299 return v0.
p_[1] < v1.p_[1];
1301 return v0.
p_[0] < v1.p_[0];
1305 const auto FiberSurfaceVertexComparisonY
1307 if(fabs(v0.
p_[1] - v1.p_[1]) < PREC_DBL) {
1309 if(fabs(v0.
p_[2] - v1.p_[2]) < PREC_DBL) {
1311 if(fabs(v0.
p_[0] - v1.p_[0]) < PREC_DBL) {
1316 return v0.
p_[0] < v1.p_[0];
1318 return v0.
p_[2] < v1.p_[2];
1320 return v0.
p_[1] < v1.p_[1];
1324 const auto FiberSurfaceVertexComparisonZ
1326 if(fabs(v0.
p_[2] - v1.p_[2]) < PREC_DBL) {
1328 if(fabs(v0.
p_[0] - v1.p_[0]) < PREC_DBL) {
1330 if(fabs(v0.
p_[1] - v1.p_[1]) < PREC_DBL) {
1335 return v0.
p_[1] < v1.p_[1];
1337 return v0.
p_[0] < v1.p_[0];
1339 return v0.
p_[2] < v1.p_[2];
1345 for(
int k = 0; k < 3; k++) {
1349 sort(tmpList.begin(), tmpList.end(), FiberSurfaceVertexComparisonX);
1353 sort(tmpList.begin(), tmpList.end(), FiberSurfaceVertexComparisonY);
1357 sort(tmpList.begin(), tmpList.end(), FiberSurfaceVertexComparisonZ);
1371 uniqueVertexNumber = 0;
1372 double distance = 0;
1375 bool canMerge =
false;
1381 if(distance <= distanceThreshold) {
1409 if((tmpList[i].meshEdge_.first == tmpList[i - 1].meshEdge_.first)
1410 && (tmpList[i].meshEdge_.second
1411 == tmpList[i - 1].meshEdge_.second)) {
1414 if((tmpList[i].meshEdge_.first == tmpList[i - 1].meshEdge_.second)
1415 && (tmpList[i].meshEdge_.second
1416 == tmpList[i - 1].meshEdge_.first)) {
1424 tmpList[i].globalId_ = tmpList[i - 1].globalId_;
1425 if((tmpList[i].isBasePoint_) || (tmpList[i - 1].isBasePoint_)) {
1426 tmpList[i].isBasePoint_ =
true;
1427 tmpList[i - 1].isBasePoint_ =
true;
1429 if((tmpList[i].isIntersectionPoint_)
1430 || (tmpList[i - 1].isIntersectionPoint_)) {
1431 tmpList[i].isIntersectionPoint_ =
true;
1432 tmpList[i - 1].isIntersectionPoint_ =
true;
1434 for(
int j = 0; j < 3; j++) {
1435 tmpList[i].p_[j] = tmpList[i - 1].p_[j];
1439 if((tmpList[i - 1].meshEdge_.first == -1)
1440 && (tmpList[i].meshEdge_.first != -1)) {
1441 tmpList[i - 1].meshEdge_ = tmpList[i].meshEdge_;
1443 if((tmpList[i].meshEdge_.first == -1)
1444 && (tmpList[i - 1].meshEdge_.first != -1)) {
1445 tmpList[i].meshEdge_ = tmpList[i - 1].meshEdge_;
1450 if((!i) || (!canMerge)) {
1451 tmpList[i].globalId_ = uniqueVertexNumber;
1452 uniqueVertexNumber++;
1455 (*globalVertexList_)[tmpList[i].localId_].globalId_
1456 = tmpList[i].globalId_;
1464 for(
int k = 0; k < 3; k++) {
1475 (*globalVertexList_).resize(uniqueVertexNumber);
1483 if((tmpList[lastId].globalId_ == tmpList[i].globalId_)
1484 && (tmpList[i].meshEdge_.first != -1)) {
1486 (*globalVertexList_)[tmpList[lastId].globalId_].meshEdge_
1487 = tmpList[i].meshEdge_;
1488 (*globalVertexList_)[tmpList[lastId].globalId_].isBasePoint_ =
true;
1493 if((!i) || (tmpList[i].globalId_ != tmpList[i - 1].globalId_)) {
1494 (*globalVertexList_)[tmpList[i].globalId_] = tmpList[i];
1507 vector<vector<FiberSurface::Triangle>> tmpTriangleLists(
1514#ifdef TTK_ENABLE_OPENMP
1515#pragma omp parallel for num_threads(threadNumber_)
1519 for(
int k = 0; k < 3; k++) {
1521 && (tmpTriangleLists[i][j].vertexIds_[k]
1522 == tmpTriangleLists[i][j].vertexIds_[(k - 1)])) {
1523 keepTriangle[i][j] =
false;
1526 if(tmpTriangleLists[i][j].vertexIds_[0]
1527 == tmpTriangleLists[i][j].vertexIds_[2]) {
1528 keepTriangle[i][j] =
false;
1538 if(keepTriangle[i][j]) {
1545 "Output made manifold", 1.0, t.
getElapsedTime(), this->threadNumber_);
1618 const std::vector<std::pair<SimplexId, SimplexId>> &triangles)
const {
1625 for(
int j = 0; j < 3; j++) {
1629 double minimum = -DBL_MAX;
1630 std::array<double, 3> minBarycentrics{};
1631 std::array<SimplexId, 3> minimizer{};
1633 for(
int k = 0; k < 2; k++) {
1634 for(
int l = k + 1; l < 3; l++) {
1635 for(
int m = l + 1; m < 4; m++) {
1641 std::array<double, 3> p0{}, p1{}, p2{};
1643 for(
int n = 0; n < 3; n++) {
1649 std::array<double, 3> barycentrics{};
1651 p0.data(), p1.data(), p2.data(),
1654 if((barycentrics[0] != -1.0) && (barycentrics[1] != -1.0)
1655 && (barycentrics[2] != -1.0)) {
1658 double localMin = -1.0;
1659 for(
int n = 0; n < 3; n++) {
1660 if((localMin == -1.0) || (fabs(barycentrics[n]) < localMin)) {
1661 localMin = fabs(barycentrics[n]);
1665 if((minimum == -DBL_MAX) || (localMin < minimum)) {
1667 minBarycentrics = barycentrics;
1668 minimizer[0] = vertexId0;
1669 minimizer[1] = vertexId1;
1670 minimizer[2] = vertexId2;
1677 if((minimum != -DBL_MAX) && (minimum < PREC_FLT_2)) {
1679 int numberOfZeros = 0;
1680 for(
int k = 0; k < 3; k++) {
1681 if(minBarycentrics[k] < PREC_FLT_2) {
1682 minBarycentrics[k] = 0;
1685 sum += minBarycentrics[k];
1688 sum = (1 - sum) / numberOfZeros;
1690 for(
int k = 0; k < 3; k++) {
1691 if(minBarycentrics[k] >= PREC_FLT_2) {
1692 minBarycentrics[k] += sum;
1697#ifdef TTK_ENABLE_OPENMP
1699 for(
int k = 0; k < 3; k++) {
1700 (*globalVertexList_)[vertexId].p_[k]
1701 = minBarycentrics[0] * ((double)
pointSet_[3 * minimizer[0] + k])
1702 + minBarycentrics[1] * ((double)
pointSet_[3 * minimizer[1] + k])
1703 + minBarycentrics[2] * ((double)
pointSet_[3 * minimizer[2] + k]);