23
#include "PreCompiled.h"
28
#include <Base/Sequencer.h>
35
using namespace MeshCore;
37
MeshTrimming::MeshTrimming(MeshKernel& rclM,
38
const Base::ViewProjMethod* pclProj,
39
const Base::Polygon2d& rclPoly)
45
void MeshTrimming::SetInnerOrOuter(TMode tMode)
57
void MeshTrimming::CheckFacets(const MeshFacetGrid& rclGrid,
58
std::vector<FacetIndex>& raulFacets) const
60
std::vector<FacetIndex>::iterator it;
61
MeshFacetIterator clIter(myMesh, 0);
65
Base::BoundBox3f clBBox3d;
66
Base::BoundBox2d clViewBBox, clPolyBBox;
67
std::vector<FacetIndex> aulAllElements;
70
clPolyBBox = myPoly.CalcBoundBox();
71
MeshGridIterator clGridIter(rclGrid);
73
for (clGridIter.Init(); clGridIter.More(); clGridIter.Next()) {
74
clBBox3d = clGridIter.GetBoundBox();
75
clViewBBox = clBBox3d.ProjectBox(myProj);
76
if (clViewBBox.Intersect(clPolyBBox)) {
78
clGridIter.GetElements(aulAllElements);
83
std::sort(aulAllElements.begin(), aulAllElements.end());
84
aulAllElements.erase(std::unique(aulAllElements.begin(), aulAllElements.end()),
85
aulAllElements.end());
87
Base::SequencerLauncher seq("Check facets for intersection...", aulAllElements.size());
89
for (it = aulAllElements.begin(); it != aulAllElements.end(); ++it) {
90
MeshGeomFacet clFacet = myMesh.GetFacet(*it);
91
if (HasIntersection(clFacet)) {
92
raulFacets.push_back(*it);
99
Base::SequencerLauncher seq("Check facets for intersection...", myMesh.CountFacets());
100
for (clIter.Init(); clIter.More(); clIter.Next()) {
101
if (HasIntersection(*clIter)) {
102
raulFacets.push_back(clIter.Position());
109
bool MeshTrimming::HasIntersection(const MeshGeomFacet& rclFacet) const
111
Base::Polygon2d clPoly;
112
Base::Line2d clFacLine, clPolyLine;
115
for (auto pnt : rclFacet._aclPoints) {
116
Base::Vector3f clPt2d = myProj->operator()(pnt);
117
if (myPoly.Contains(Base::Vector2d(clPt2d.x, clPt2d.y)) == myInner) {
121
clPoly.Add(Base::Vector2d(clPt2d.x, clPt2d.y));
126
for (size_t j = 0; j < myPoly.GetCtVectors(); j++) {
127
if (clPoly.Contains(myPoly[j])) {
133
for (size_t j = 0; j < myPoly.GetCtVectors(); j++) {
134
clPolyLine.clV1 = myPoly[j];
135
clPolyLine.clV2 = myPoly[(j + 1) % myPoly.GetCtVectors()];
137
for (size_t i = 0; i < 3; i++) {
138
clFacLine.clV1 = clPoly[i];
139
clFacLine.clV2 = clPoly[(i + 1) % 3];
141
if (clPolyLine.IntersectAndContain(clFacLine, S)) {
151
bool MeshTrimming::PolygonContainsCompleteFacet(bool bInner, FacetIndex ulIndex) const
153
const MeshFacet& rclFacet = myMesh._aclFacetArray[ulIndex];
154
for (PointIndex ptIndex : rclFacet._aulPoints) {
155
const MeshPoint& rclFacPt = myMesh._aclPointArray[ptIndex];
156
Base::Vector3f clPt = (*myProj)(rclFacPt);
157
if (myPoly.Contains(Base::Vector2d(clPt.x, clPt.y)) != bInner) {
165
bool MeshTrimming::IsPolygonPointInFacet(FacetIndex ulIndex, Base::Vector3f& clPoint)
167
Base::Vector2d A, B, C, P;
168
float u {}, v {}, w {}, fDetPAC {}, fDetPBC {}, fDetPAB {}, fDetABC {};
169
Base::Polygon2d clFacPoly;
170
const MeshGeomFacet& rclFacet = myMesh.GetFacet(ulIndex);
172
for (auto pnt : rclFacet._aclPoints) {
173
Base::Vector3f clPt = (*myProj)(pnt);
174
clFacPoly.Add(Base::Vector2d(clPt.x, clPt.y));
181
static_cast<float>(A.x * B.y + A.y * C.x + B.x * C.y - (B.y * C.x + A.y * B.x + A.x * C.y));
183
for (size_t j = 0; j < myPoly.GetCtVectors(); j++) {
185
if (clFacPoly.Contains(myPoly[j])) {
187
fDetPAC = static_cast<float>(A.x * P.y + A.y * C.x + P.x * C.y
188
- (P.y * C.x + A.y * P.x + A.x * C.y));
189
fDetPBC = static_cast<float>(P.x * B.y + P.y * C.x + B.x * C.y
190
- (B.y * C.x + P.y * B.x + P.x * C.y));
191
fDetPAB = static_cast<float>(A.x * B.y + A.y * P.x + B.x * P.y
192
- (B.y * P.x + A.y * B.x + A.x * P.y));
193
u = fDetPBC / fDetABC;
194
v = fDetPAC / fDetABC;
195
w = fDetPAB / fDetABC;
198
if (u == 0.0f || v == 0.0f || w == 0.0f || fabs(u + v + w - 1.0f) >= 0.001f) {
202
clPoint = u * rclFacet._aclPoints[0] + v * rclFacet._aclPoints[1]
203
+ w * rclFacet._aclPoints[2];
212
bool MeshTrimming::GetIntersectionPointsOfPolygonAndFacet(
215
std::vector<Base::Vector3f>& raclPoints) const
217
MeshGeomFacet clFac(myMesh.GetFacet(ulIndex));
219
Base::Line2d clFacLine, clPolyLine;
220
int iIntersections = 0;
221
int iIntsctWithEdge0 = 0, iIntsctWithEdge1 = 0, iIntsctWithEdge2 = 0;
226
for (size_t i = 0; i < myPoly.GetCtVectors(); i++) {
228
if (iIntersections == 4) {
232
Base::Vector2d P3(myPoly[i]), P4(myPoly[(i + 1) % myPoly.GetCtVectors()]);
233
clPolyLine.clV1 = P3;
234
clPolyLine.clV2 = P4;
236
for (int j = 0; j < 3; j++) {
237
Base::Vector3f clP1((*myProj)(clFac._aclPoints[j]));
238
Base::Vector3f clP2((*myProj)(clFac._aclPoints[(j + 1) % 3]));
239
Base::Vector2d P1(clP1.x, clP1.y);
240
Base::Vector2d P2(clP2.x, clP2.y);
244
if (clPolyLine.Intersect(P1, double(MESH_MIN_PT_DIST))) {
248
else if (clPolyLine.Intersect(P2, double(MESH_MIN_PT_DIST))) {
252
else if (clPolyLine.Intersect(clFacLine, S)) {
253
bool bPushBack = true;
254
float fP1P2 = static_cast<float>((P2 - P1).Length());
255
float fSP1 = static_cast<float>((P1 - S).Length());
256
float fSP2 = static_cast<float>((P2 - S).Length());
258
float fP3P4 = static_cast<float>((P4 - P3).Length());
259
float fSP3 = static_cast<float>((P3 - S).Length());
260
float fSP4 = static_cast<float>((P4 - S).Length());
262
float l = fSP1 / fP1P2;
263
float m = fSP2 / fP1P2;
265
float r = fSP3 / fP3P4;
266
float s = fSP4 / fP3P4;
269
if ((fabs(l + m - 1.0f) < 0.001f) && (fabs(r + s - 1.0f) < 0.001f)) {
270
Base::Vector3f clIntersection(m * clFac._aclPoints[j]
271
+ l * clFac._aclPoints[(j + 1) % 3]);
277
if (iIntsctWithEdge0 == 2) {
285
if (iIntsctWithEdge1 == 2) {
293
if (iIntsctWithEdge2 == 2) {
302
raclPoints.push_back(clIntersection);
310
if (iIntsctWithEdge0 == 0) {
313
else if (iIntsctWithEdge1 == 0) {
316
else if (iIntsctWithEdge2 == 0) {
321
if (iIntsctWithEdge0 == 0 && iIntsctWithEdge1 == 0) {
324
else if (iIntsctWithEdge0 == 0 && iIntsctWithEdge2 == 0) {
327
else if (iIntsctWithEdge1 == 0 && iIntsctWithEdge2 == 0) {
332
if (iIntsctWithEdge0 * iIntsctWithEdge1 * iIntsctWithEdge2 > 0) {
333
if (iIntsctWithEdge0 == 2) {
336
else if (iIntsctWithEdge1 == 2) {
339
else if (iIntsctWithEdge2 == 2) {
344
return iIntersections > 0;
347
void MeshTrimming::AdjustFacet(MeshFacet& facet, int iInd)
349
unsigned long tmp {};
352
tmp = facet._aulPoints[0];
353
facet._aulPoints[0] = facet._aulPoints[1];
354
facet._aulPoints[1] = facet._aulPoints[2];
355
facet._aulPoints[2] = tmp;
356
tmp = facet._aulNeighbours[0];
357
facet._aulNeighbours[0] = facet._aulNeighbours[1];
358
facet._aulNeighbours[1] = facet._aulNeighbours[2];
359
facet._aulNeighbours[2] = tmp;
361
else if (iInd == 2) {
362
tmp = facet._aulPoints[0];
363
facet._aulPoints[0] = facet._aulPoints[2];
364
facet._aulPoints[2] = facet._aulPoints[1];
365
facet._aulPoints[1] = tmp;
366
tmp = facet._aulNeighbours[0];
367
facet._aulNeighbours[0] = facet._aulNeighbours[2];
368
facet._aulNeighbours[2] = facet._aulNeighbours[1];
369
facet._aulNeighbours[1] = tmp;
373
bool MeshTrimming::CreateFacets(FacetIndex ulFacetPos,
375
const std::vector<Base::Vector3f>& raclPoints,
376
std::vector<MeshGeomFacet>& aclNewFacets)
386
if (raclPoints.empty()) {
387
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
390
Base::Vector3f clFacPnt;
391
Base::Vector2d clProjPnt;
392
for (PointIndex ptIndex : facet._aulPoints) {
393
clFacPnt = (*myProj)(myMesh._aclPointArray[ptIndex]);
394
clProjPnt = Base::Vector2d(clFacPnt.x, clFacPnt.y);
395
if (myPoly.Intersect(clProjPnt, double(MESH_MIN_PT_DIST))) {
398
else if (myPoly.Contains(clProjPnt) == myInner) {
404
if (iCtPtsIn != (3 - iCtPtsOn)) {
405
aclNewFacets.push_back(myMesh.GetFacet(ulFacetPos));
409
else if (raclPoints.size() == 1) {
410
Base::Vector3f clP(raclPoints[0]);
411
clP = ((*myProj)(clP));
412
Base::Vector2d P(clP.x, clP.y);
413
MeshGeomFacet clFac(myMesh.GetFacet(ulFacetPos));
416
Base::Line2d clFacLine;
417
for (int j = 0; j < 3; j++) {
418
Base::Vector3f clP1((*myProj)(clFac._aclPoints[j]));
419
Base::Vector3f clP2((*myProj)(clFac._aclPoints[(j + 1) % 3]));
420
Base::Vector2d P1(clP1.x, clP1.y);
421
Base::Vector2d P2(clP2.x, clP2.y);
425
if (clFacLine.Intersect(P, double(MESH_MIN_PT_DIST))) {
426
if (myPoly.Contains(P1) == myInner) {
428
clNew._aclPoints[0] = raclPoints[0];
429
clNew._aclPoints[1] = clFac._aclPoints[(j + 1) % 3];
430
clNew._aclPoints[2] = clFac._aclPoints[(j + 2) % 3];
431
aclNewFacets.push_back(clNew);
434
else if (myPoly.Contains(P2) == myInner) {
436
clNew._aclPoints[0] = raclPoints[0];
437
clNew._aclPoints[1] = clFac._aclPoints[(j + 2) % 3];
438
clNew._aclPoints[2] = clFac._aclPoints[j];
439
aclNewFacets.push_back(clNew);
446
else if (raclPoints.size() == 2) {
447
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
448
AdjustFacet(facet, iSide);
449
Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]);
453
clP1 = raclPoints[1];
454
clP2 = raclPoints[0];
459
Base::Vector3f clFacPnt;
460
Base::Vector2d clProjPnt;
461
for (PointIndex ptIndex : facet._aulPoints) {
462
clFacPnt = (*myProj)(myMesh._aclPointArray[ptIndex]);
463
clProjPnt = Base::Vector2d(clFacPnt.x, clFacPnt.y);
464
if (myPoly.Contains(clProjPnt) == myInner) {
471
clFac._aclPoints[0] = clP1;
472
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[2]];
473
clFac._aclPoints[2] = clP2;
474
aclNewFacets.push_back(clFac);
476
else if (iCtPts == 1) {
478
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
479
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
480
clFac._aclPoints[2] = clP2;
481
aclNewFacets.push_back(clFac);
483
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[1]];
484
clFac._aclPoints[1] = clP1;
485
clFac._aclPoints[2] = clP2;
486
aclNewFacets.push_back(clFac);
493
else if (raclPoints.size() == 4) {
494
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
495
AdjustFacet(facet, iSide);
497
clFac = myMesh.GetFacet(ulFacetPos);
499
Base::Vector3f clP1(raclPoints[0]), clP2(raclPoints[1]), clP3(raclPoints[2]),
504
Base::Vector3f clFacPnt;
505
Base::Vector2d clProjPnt;
506
for (PointIndex ptIndex : facet._aulPoints) {
507
clFacPnt = (*myProj)(myMesh._aclPointArray[ptIndex]);
508
clProjPnt = Base::Vector2d(clFacPnt.x, clFacPnt.y);
509
if (myPoly.Contains(clProjPnt) == myInner) {
515
if (iCtPts == 0 || iCtPts == 3) {
519
clP2 = raclPoints[0];
521
clP4 = raclPoints[2];
524
if ((clP1 - clFac._aclPoints[1]).Length() > (clP3 - clFac._aclPoints[1]).Length()) {
526
Base::Vector3f tmp(clP1);
530
if ((clP2 - clFac._aclPoints[0]).Length() > (clP4 - clFac._aclPoints[0]).Length()) {
532
Base::Vector3f tmp(clP2);
539
Base::Vector3f clNormal(clFac.GetNormal());
540
MeshGeomFacet clTmpFac;
541
clTmpFac._aclPoints[0] = clFac._aclPoints[1];
542
clTmpFac._aclPoints[1] = clP2;
543
clTmpFac._aclPoints[2] = clP1;
544
if (clTmpFac.GetNormal() * clNormal > 0) {
545
Base::Vector3f tmp(clP1);
550
Base::Vector3f tmp(clP1);
557
else if (iSide == 1) {
558
if ((clP2 - clFac._aclPoints[1]).Length() > (clP4 - clFac._aclPoints[1]).Length()) {
559
Base::Vector3f tmp(clP1);
567
Base::Vector3f tmp(clP1);
576
if ((clP1 - clFac._aclPoints[1]).Length() > (clP3 - clFac._aclPoints[1]).Length()) {
577
Base::Vector3f tmp(clP1);
590
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
591
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
592
clFac._aclPoints[2] = clP1;
593
aclNewFacets.push_back(clFac);
595
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
596
clFac._aclPoints[1] = clP1;
597
clFac._aclPoints[2] = clP2;
598
aclNewFacets.push_back(clFac);
600
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
601
clFac._aclPoints[1] = clP4;
602
clFac._aclPoints[2] = clP3;
603
aclNewFacets.push_back(clFac);
605
else if (iCtPts == 1) {
607
clFac._aclPoints[0] = clP1;
608
clFac._aclPoints[1] = clP2;
609
clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[1]];
610
aclNewFacets.push_back(clFac);
612
clFac._aclPoints[0] = clP4;
613
clFac._aclPoints[1] = clP3;
614
clFac._aclPoints[2] = myMesh._aclPointArray[facet._aulPoints[2]];
615
aclNewFacets.push_back(clFac);
617
else if (iCtPts == 2) {
619
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
620
clFac._aclPoints[1] = clP2;
621
clFac._aclPoints[2] = clP4;
622
aclNewFacets.push_back(clFac);
624
clFac._aclPoints[0] = clP1;
625
clFac._aclPoints[1] = clP4;
626
clFac._aclPoints[2] = clP2;
627
aclNewFacets.push_back(clFac);
629
clFac._aclPoints[0] = clP1;
630
clFac._aclPoints[1] = clP3;
631
clFac._aclPoints[2] = clP4;
632
aclNewFacets.push_back(clFac);
636
clFac._aclPoints[0] = clP1;
637
clFac._aclPoints[1] = clP3;
638
clFac._aclPoints[2] = clP4;
639
aclNewFacets.push_back(clFac);
641
clFac._aclPoints[0] = clP1;
642
clFac._aclPoints[1] = clP4;
643
clFac._aclPoints[2] = clP2;
644
aclNewFacets.push_back(clFac);
654
bool MeshTrimming::CreateFacets(FacetIndex ulFacetPos,
656
const std::vector<Base::Vector3f>& raclPoints,
657
Base::Vector3f& clP3,
658
std::vector<MeshGeomFacet>& aclNewFacets)
661
if (iSide == -1 || raclPoints.size() < 2) {
665
Base::Vector3f clP1(raclPoints[0]);
666
Base::Vector3f clP2(raclPoints[1]);
668
MeshFacet& facet = myMesh._aclFacetArray[ulFacetPos];
669
AdjustFacet(facet, iSide);
673
float fDistEdgeP1 = clP1.DistanceToLineSegment(myMesh._aclPointArray[facet._aulPoints[1]],
674
myMesh._aclPointArray[facet._aulPoints[2]])
676
float fDistEdgeP2 = clP2.DistanceToLineSegment(myMesh._aclPointArray[facet._aulPoints[1]],
677
myMesh._aclPointArray[facet._aulPoints[2]])
681
if (fDistEdgeP2 < fDistEdgeP1) {
682
Base::Vector3f tmp(clP1);
689
Base::Vector3f clFacPnt;
690
Base::Vector2d clProjPnt;
691
for (PointIndex ptIndex : facet._aulPoints) {
692
clFacPnt = (*myProj)(myMesh._aclPointArray[ptIndex]);
693
clProjPnt = Base::Vector2d(clFacPnt.x, clFacPnt.y);
694
if (myPoly.Contains(clProjPnt) == myInner) {
699
clFac = myMesh.GetFacet(ulFacetPos);
700
if ((clP1 - clFac._aclPoints[1]).Length() > (clP2 - clFac._aclPoints[1]).Length()) {
701
Base::Vector3f tmp(clP1);
706
clFac._aclPoints[0] = clP1;
707
clFac._aclPoints[1] = clP2;
708
clFac._aclPoints[2] = clP3;
709
aclNewFacets.push_back(clFac);
711
else if (iCtPts == 2) {
713
clFac._aclPoints[0] = clP1;
714
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[2]];
715
clFac._aclPoints[2] = clP3;
716
aclNewFacets.push_back(clFac);
718
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
719
clFac._aclPoints[1] = clP2;
720
clFac._aclPoints[2] = clP3;
721
aclNewFacets.push_back(clFac);
723
else if (iCtPts == 1) {
725
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
726
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
727
clFac._aclPoints[2] = clP3;
728
aclNewFacets.push_back(clFac);
730
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[1]];
731
clFac._aclPoints[1] = clP1;
732
clFac._aclPoints[2] = clP3;
733
aclNewFacets.push_back(clFac);
735
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
736
clFac._aclPoints[1] = clP3;
737
clFac._aclPoints[2] = clP2;
738
aclNewFacets.push_back(clFac);
740
else if (iCtPts == 0) {
741
clFac = myMesh.GetFacet(ulFacetPos);
742
if ((clP1 - clFac._aclPoints[1]).Length() > (clP2 - clFac._aclPoints[1]).Length()) {
743
Base::Vector3f tmp(clP1);
748
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
749
clFac._aclPoints[1] = clP3;
750
clFac._aclPoints[2] = clP2;
751
aclNewFacets.push_back(clFac);
753
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[2]];
754
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[0]];
755
clFac._aclPoints[2] = clP3;
756
aclNewFacets.push_back(clFac);
758
clFac._aclPoints[0] = myMesh._aclPointArray[facet._aulPoints[0]];
759
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
760
clFac._aclPoints[2] = clP3;
761
aclNewFacets.push_back(clFac);
763
clFac._aclPoints[0] = clP3;
764
clFac._aclPoints[1] = myMesh._aclPointArray[facet._aulPoints[1]];
765
clFac._aclPoints[2] = clP1;
766
aclNewFacets.push_back(clFac);
772
void MeshTrimming::TrimFacets(const std::vector<FacetIndex>& raulFacets,
773
std::vector<MeshGeomFacet>& aclNewFacets)
776
std::vector<Base::Vector3f> clIntsct;
779
Base::SequencerLauncher seq("trimming facets...", raulFacets.size());
780
for (FacetIndex index : raulFacets) {
782
if (!IsPolygonPointInFacet(index, clP)) {
784
if (!PolygonContainsCompleteFacet(myInner, index)) {
786
if (GetIntersectionPointsOfPolygonAndFacet(index, iSide, clIntsct)) {
787
CreateFacets(index, iSide, clIntsct, myTriangles);
794
if (GetIntersectionPointsOfPolygonAndFacet(index, iSide, clIntsct)) {
795
CreateFacets(index, iSide, clIntsct, clP, myTriangles);
801
aclNewFacets = myTriangles;