23 static int edges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
24 static int efaces[6][2] = {{0, 2}, {0, 1}, {1, 2}, {0, 3}, {2, 3}, {1, 3}};
27 static int faces[4][3] = {{0, 1, 2}, {0, 2, 3}, {0, 1, 3}, {1, 2, 3}};
29 static int vFac[4][3] = {{0, 1, 2}, {0, 2, 3}, {0, 1, 3}, {1, 2, 3}};
36 std::vector<MTet4 *> &outside)
39 for(std::size_t i = 0; i < cavity.size(); i++) {
40 for(
int j = 0; j < 4; j++) {
44 for(std::size_t k = 0; k < outside.size(); k++) {
45 if(outside[k] == neigh) {
51 for(std::size_t k = 0; k < cavity.size(); k++) {
52 if(cavity[k] == neigh) { found =
true; }
55 if(!found) outside.push_back(neigh);
62 std::vector<MTet4 *> &cavity,
63 std::vector<MTet4 *> &outside,
64 std::vector<MVertex *> &ring)
74 ring.push_back(lastinring);
80 int K = ov1 == lastinring ? 1 : 0;
81 lastinring = ov1 == lastinring ? ov2 : ov1;
85 int iFace1 =
efaces[iLocalEdge][0];
86 int iFace2 =
efaces[iLocalEdge][1];
87 if(
faces[iFace1][0] ==
edges[5 - iLocalEdge][K] ||
88 faces[iFace1][1] ==
edges[5 - iLocalEdge][K] ||
91 else if(
faces[iFace2][0] ==
edges[5 - iLocalEdge][K] ||
92 faces[iFace2][1] ==
edges[5 - iLocalEdge][K] ||
105 if(t == cavity[0])
break;
106 ring.push_back(lastinring);
109 for(
int i = 0; i < 6; i++) {
112 if((a == *v1 && b == *v2) || (a == *v2 && b == *v1)) {
117 if(iLocalEdge == -1) {
118 Msg::Warning(
"Strange edge cavity (local edge not found)");
122 if(cavity.size() > 1000) {
134 static int trgl[][3] = {{0, 1, 2}};
135 static int trgul[][5] = {{0, -1, -1, -1, -1}};
157 static int trgl[][3] = {{0, 1, 2}, {2, 3, 0}, {1, 2, 3}, {3, 0, 1}};
158 static int trgul[][5] = {{0, 1, -1, -1, -1}, {2, 3, -1, -1, -1}};
169 static int trgl[][3] = {{0, 1, 2}, {0, 2, 3}, {0, 3, 4}, {0, 1, 4},
170 {1, 3, 4}, {1, 2, 3}, {2, 3, 4}, {0, 2, 4},
171 {0, 1, 3}, {1, 2, 4}};
172 static int trgul[][5] = {{0, 1, 2, -1, -1},
187 static int trgl[][3] = {
188 {0, 1, 2}, {0, 2, 3}, {0, 3, 4}, {0, 4, 5}, {0, 2, 5}, {2, 4, 5}, {2, 3, 4},
189 {0, 3, 5}, {3, 4, 5}, {0, 2, 4}, {2, 3, 5}, {1, 2, 3}, {0, 1, 3}, {0, 1, 5},
190 {1, 4, 5}, {1, 3, 4}, {0, 1, 4}, {1, 3, 5}, {1, 2, 4}, {1, 2, 5}};
191 static int trgul[][5] = {
192 {0, 1, 2, 3, -1}, {0, 4, 5, 6, -1}, {0, 1, 7, 8, -1},
193 {0, 3, 6, 9, -1}, {0, 4, 8, 10, -1}, {2, 3, 11, 12, -1},
194 {11, 13, 14, 15, -1}, {7, 8, 11, 12, -1}, {3, 11, 15, 16, -1},
195 {8, 11, 13, 17, -1}, {6, 13, 14, 18, -1}, {3, 6, 16, 18, -1},
196 {5, 6, 13, 19, -1}, {8, 10, 13, 19, -1}};
207 static int trgl[][3] = {
208 {0, 1, 2}, {0, 2, 3}, {0, 3, 4}, {0, 4, 5}, {0, 5, 6}, {0, 3, 6},
209 {3, 5, 6}, {3, 4, 5}, {0, 4, 6}, {4, 5, 6}, {0, 3, 5}, {3, 4, 6},
210 {0, 2, 4}, {2, 3, 4}, {0, 2, 6}, {2, 5, 6}, {2, 4, 5}, {0, 2, 5},
211 {2, 4, 6}, {2, 3, 5}, {2, 3, 6}, {0, 1, 3}, {1, 2, 3}, {0, 1, 4},
212 {1, 3, 4}, {0, 1, 6}, {1, 5, 6}, {1, 4, 5}, {0, 1, 5}, {1, 4, 6},
213 {1, 3, 5}, {1, 3, 6}, {1, 2, 4}, {1, 2, 5}, {1, 2, 6}};
214 static int trgul[][5] = {
215 {0, 1, 2, 3, 4}, {0, 1, 5, 6, 7}, {0, 1, 2, 8, 9},
216 {0, 1, 4, 7, 10}, {0, 1, 5, 9, 11}, {0, 3, 4, 12, 13},
217 {0, 13, 14, 15, 16}, {0, 8, 9, 12, 13}, {0, 4, 13, 16, 17},
218 {0, 9, 13, 14, 18}, {0, 7, 14, 15, 19}, {0, 4, 7, 17, 19},
219 {0, 6, 7, 14, 20}, {0, 9, 11, 14, 20}, {2, 3, 4, 21, 22},
220 {5, 6, 7, 21, 22}, {2, 8, 9, 21, 22}, {4, 7, 10, 21, 22},
221 {5, 9, 11, 21, 22}, {3, 4, 22, 23, 24}, {22, 24, 25, 26, 27},
222 {8, 9, 22, 23, 24}, {4, 22, 24, 27, 28}, {9, 22, 24, 25, 29},
223 {7, 22, 25, 26, 30}, {4, 7, 22, 28, 30}, {6, 7, 22, 25, 31},
224 {9, 11, 22, 25, 31}, {3, 4, 13, 23, 32}, {13, 25, 26, 27, 32},
225 {8, 9, 13, 23, 32}, {4, 13, 27, 28, 32}, {9, 13, 25, 29, 32},
226 {13, 16, 25, 26, 33}, {4, 13, 16, 28, 33}, {13, 15, 16, 25, 34},
227 {9, 13, 18, 25, 34}, {7, 19, 25, 26, 33}, {4, 7, 19, 28, 33},
228 {7, 15, 19, 25, 34}, {6, 7, 20, 25, 34}, {9, 11, 20, 25, 34}};
239 const std::set<MFace, MFaceLessThan> &embeddedFaces)
242 int permut[6] = {0, 3, 1, 2, 5, 4};
243 iLocalEdge = permut[iLocalEdge];
245 std::vector<MTet4 *> cavity;
246 std::vector<MTet4 *> outside;
247 std::vector<MVertex *> ring;
255 if(!closed)
return false;
257 double volumeRef = 0.0;
258 double tetQualityRef = 1;
259 for(std::size_t i = 0; i < cavity.size(); i++) {
260 double vol = fabs(cavity[i]->tet()->getVolume());
261 tetQualityRef = std::min(tetQualityRef, cavity[i]->getQuality());
268 switch(ring.size()) {
274 default:
return false;
278 double tetQuality1[100], tetQuality2[100];
279 double volume1[100], volume2[100];
292 double minQuality[100];
300 minQuality[i] = std::min(minQuality[i], tetQuality1[iT]);
301 minQuality[i] = std::min(minQuality[i], tetQuality2[iT]);
302 volume += (volume1[iT] + volume2[iT]);
305 if(fabs(volume - volumeRef) > 1.e-10 * (volume + volumeRef))
312 if(minQuality[i] > best) {
313 best = minQuality[i];
319 if(best <= tetQualityRef + 1e-20)
return false;
342 outside.push_back(t41);
343 outside.push_back(t42);
344 newTets.push_back(t41);
345 newTets.push_back(t42);
348 for(std::size_t i = 0; i < cavity.size(); i++) cavity[i]->setDeleted(
true);
358 std::vector<MTet4 *> cavity;
359 std::vector<MTet4 *> outside;
360 std::vector<MVertex *> ring;
365 if(!closed)
return false;
367 for(std::size_t j = 0; j < ring.size(); j++) {
369 MVertex *pv2 = ring[(j + 1) % ring.size()];
376 outside.push_back(t41);
377 outside.push_back(t42);
378 newTets.push_back(t41);
379 newTets.push_back(t42);
382 for(std::size_t i = 0; i < cavity.size(); i++) cavity[i]->setDeleted(
true);
392 const std::set<MFace, MFaceLessThan> &embeddedFaces)
395 if(!t2)
return false;
403 for(
int i = 0; i < 4; i++) {
405 if(v != f1 && v != f2 && v != f3) {
429 if(fabs(vol1 + vol2 - vol3 - vol4 - vol5) > 1.e-10 * (vol1 + vol2))
431 if(std::min(q1, q2) > std::min(std::min(q3, q4), q5))
return false;
435 std::vector<MTet4 *> outside;
436 for(
int i = 0; i < 4; i++) {
439 for(std::size_t j = 0; j < outside.size(); j++) {
445 if(!found) outside.push_back(t1->
getNeigh(i));
448 for(
int i = 0; i < 4; i++) {
451 for(std::size_t j = 0; j < outside.size(); j++) {
457 if(!found) outside.push_back(t2->
getNeigh(i));
475 outside.push_back(t41);
476 outside.push_back(t42);
477 outside.push_back(t43);
478 newTets.push_back(t41);
479 newTets.push_back(t42);
480 newTets.push_back(t43);
488 Msg::Warning(
"A deleted tet is a neighbor of a non deleted tet"
489 " - skipping cavity");
493 for(
int i = 0; i < 4; i++) {
500 Msg::Warning(
"Trying to build a cavity of tets for a node that does not "
501 "belong to this tet - skipping cavity");
504 for(
int i = 0; i < 3; i++) {
508 for(std::size_t j = 0; j < cavity.size(); j++) {
509 if(cavity[j] == neigh) {
515 cavity.push_back(neigh);
542 if(tg->
onWhat()->
dim() < 3)
return false;
544 std::vector<MTet4 *> cavity_v;
545 std::vector<MTet4 *> outside;
546 cavity_v.push_back(t);
549 std::vector<MTet4 *> toDelete;
550 std::vector<MTet4 *> toUpdate;
553 for(std::size_t i = 0; i < cavity_v.size(); i++) {
555 volume += fabs(cavity_v[i]->tet()->getVolume());
556 double q = cavity_v[i]->getQuality();
557 worst = std::min(worst, q);
558 for(
int j = 0; j < 4; j++) {
559 if(cavity_v[i]->tet()->getVertex(j) == tg) found =
true;
562 toDelete.push_back(cavity_v[i]);
564 toUpdate.push_back(cavity_v[i]);
574 double volume_update = 0;
576 double worstAfter = 1.0;
577 std::vector<double> newQuals(toUpdate.size());
578 for(std::size_t i = 0; i < toUpdate.size(); i++) {
581 worstAfter = std::min(worstAfter, newQuals[i]);
588 if(fabs(volume - volume_update) > 1.e-10 * volume || worstAfter < worst) {
595 *minQual = worstAfter;
600 for(std::size_t i = 0; i < toUpdate.size(); i++) {
602 toUpdate[i]->tet()->getVertex(0) == v ? tg :
603 toUpdate[i]->tet()->getVertex(0),
604 toUpdate[i]->tet()->getVertex(1) == v ? tg :
605 toUpdate[i]->tet()->getVertex(1),
606 toUpdate[i]->tet()->getVertex(2) == v ? tg :
607 toUpdate[i]->tet()->getVertex(2),
608 toUpdate[i]->tet()->getVertex(3) == v ? tg :
609 toUpdate[i]->tet()->getVertex(3));
613 outside.push_back(t41);
614 newTets.push_back(t41);
616 for(std::size_t i = 0; i < cavity_v.size(); i++)
617 cavity_v[i]->setDeleted(
true);
632 std::vector<MTet4 *> cavity;
637 double xcg = 0, ycg = 0, zcg = 0;
641 for(std::size_t i = 0; i < cavity.size(); i++) {
642 double volume = fabs(cavity[i]->tet()->getVolume());
643 double q = cavity[i]->getQuality();
644 worst = std::min(worst, q);
646 (cavity[i]->tet()->getVertex(0)->x() +
647 cavity[i]->tet()->getVertex(1)->x() +
648 cavity[i]->tet()->getVertex(2)->x() +
649 cavity[i]->tet()->getVertex(3)->x()) *
652 (cavity[i]->tet()->getVertex(0)->y() +
653 cavity[i]->tet()->getVertex(1)->y() +
654 cavity[i]->tet()->getVertex(2)->y() +
655 cavity[i]->tet()->getVertex(3)->y()) *
658 (cavity[i]->tet()->getVertex(0)->z() +
659 cavity[i]->tet()->getVertex(1)->z() +
660 cavity[i]->tet()->getVertex(2)->z() +
661 cavity[i]->tet()->getVertex(3)->z()) *
668 double volumeAfter = 0.0;
677 double worstAfter = 1.0;
678 std::vector<double> newQuals(cavity.size());
679 for(std::size_t i = 0; i < cavity.size(); i++) {
682 volumeAfter += volume;
683 worstAfter = std::min(worstAfter, newQuals[i]);
686 if(fabs(volumeAfter - vTot) > 1.e-10 * vTot || worstAfter < worst) {
694 for(std::size_t i = 0; i < cavity.size(); i++) {
695 cavity[i]->setQuality(newQuals[i]);
703 std::vector<MTet4 *>
ts;
708 std::vector<MTet4 *> &ts)
710 const double oldX = v->
x();
711 const double oldY = v->
y();
712 const double oldZ = v->
z();
717 auto it = ts.begin();
719 double qMin = 1, vol;
736 const double LARGE = svd->
LC * 1.e5;
737 const double SMALL = 1. / LARGE;
745 dF[0] = (F_X -
F) * LARGE;
746 dF[1] = (F_Y -
F) * LARGE;
747 dF[2] = (F_Z -
F) * LARGE;
769 double xyzopti[3] = {vd.
v->
x(), vd.
v->
y(), vd.
v->
z()};
772 Msg::Error(
"Fletcher-Reeves minimizer routine must be reimplemented");
778 for(std::size_t i = 0; i < vd.
ts.size(); i++) {
779 double volume = fabs(vd.
ts[i]->tet()->getVolume());
783 double volumeAfter = 0.0;
793 std::vector<double> newQuals(vd.
ts.size());
794 for(std::size_t i = 0; i < vd.
ts.size(); i++) {
797 volumeAfter += volume;
800 if(fabs(volumeAfter - vTot) > 1.e-10 * vTot) {
808 for(std::size_t i = 0; i < vd.
ts.size(); i++) {
809 vd.
ts[i]->setQuality(newQuals[i]);
815 template <
class ITERATOR>
816 void fillv_(std::multimap<MVertex *, MElement *> &vertexToElement,
817 ITERATOR it_beg, ITERATOR it_end)
819 for(ITERATOR IT = it_beg; IT != it_end; ++IT) {
823 vertexToElement.insert(std::make_pair(e, el));
830 std::multimap<MVertex *, MElement *> vertexToElement;
831 fillv_(vertexToElement, (gr)->tetrahedra.begin(), (gr)->tetrahedra.end());
832 fillv_(vertexToElement, (gr)->hexahedra.begin(), (gr)->hexahedra.end());
833 fillv_(vertexToElement, (gr)->prisms.begin(), (gr)->prisms.end());
834 fillv_(vertexToElement, (gr)->pyramids.begin(), (gr)->pyramids.end());
838 auto it = vertexToElement.lower_bound(v);
840 auto it_up = vertexToElement.upper_bound(v);
841 double minQual = 1.e22;
843 double xold = v->
x(), yold = v->
y(), zold = v->
z();
845 for(; it != it_up; ++it) {
846 minQual = std::min(minQual, it->second->minSICNShapeMeasure());
847 double vol = fabs(it->second->getVolume());
848 SPoint3 cog = it->second->barycenter();
852 pNew *= (1. / volTot);
854 double minQual2 = 1.e22;
855 for(it = it_low; it != it_up; ++it) {
856 minQual2 = std::min(minQual2, it->second->minSICNShapeMeasure());
857 if(minQual2 < minQual) {
858 v->
setXYZ(xold, yold, zold);
862 if(minQual < minQual2) N++;