28 static int vertexPositionInFace(
int vertexIndex,
const QgsMeshFace &face )
30 return face.indexOf( vertexIndex );
33 static int vertexPositionInFace(
const QgsMesh &mesh,
int vertexIndex,
int faceIndex )
35 if ( faceIndex < 0 || faceIndex >= mesh.
faceCount() )
38 return vertexPositionInFace( vertexIndex, mesh.
face( faceIndex ) );
41 bool QgsMeshEditForceByLine::edgeIntersection(
44 int &closestSnappedVertex,
51 closestSnappedVertex = -1;
58 double epsilon = std::numeric_limits<double>::epsilon() * mTolerance * mTolerance;
61 bool snapV1 = sqrt( v1.sqrDistToSegment( pt1.x(), pt1.y(), pt2.x(), pt2.y(), minDistPoint, epsilon ) ) < mTolerance;
62 bool snapV2 = sqrt( v2.sqrDistToSegment( pt1.x(), pt1.y(), pt2.x(), pt2.y(), minDistPoint, epsilon ) ) < mTolerance;
64 bool intersectLine =
false;
66 mCurrentPointPosition,
68 triangularMesh->
vertices().at( vertex1 ),
69 triangularMesh->
vertices().at( vertex2 ),
72 outAllowed ? mTolerance : 0,
true );
74 if ( snapV1 == snapV2 )
76 double distance1FromIntersection = v1.distance( intersectionPoint );
77 double distance2FromIntersection = v2.distance( intersectionPoint );
78 if ( distance1FromIntersection <= distance2FromIntersection )
90 if ( isIntersect && snapV1 )
92 closestSnappedVertex = vertex1;
93 intersectionPoint = triangularMesh->
vertices().at( vertex1 );
96 else if ( isIntersect && snapV2 )
98 closestSnappedVertex = vertex2;
99 intersectionPoint = triangularMesh->
vertices().at( vertex2 );
107 static void buildHolesWithOneFace(
QgsMeshEditor *meshEditor,
111 QList<int> &holeOnLeft,
112 QList<int> &neighborsOnLeft,
113 QList<int> &holeOnRight,
114 QList<int> &neighborsOnRight )
118 const int faceSize = face.size();
120 int beginPos = vertexPositionInFace( firstVertex, face );
121 int endPos = vertexPositionInFace( secondVertex, face );
124 for (
int i = 0; i < faceSize; ++i )
126 int currentPos = ( beginPos + i ) % faceSize;
127 holeOnRight.append( face.at( currentPos ) );
128 if ( currentPos == endPos )
130 neighborsOnRight.append( neighbors.at( currentPos ) );
134 for (
int i = 0; i < faceSize; ++i )
136 int currentPos = ( beginPos + faceSize - i ) % faceSize;
137 holeOnLeft.append( face.at( currentPos ) );
138 if ( currentPos == endPos )
140 int neighborPos = ( currentPos + faceSize - 1 ) % faceSize;
141 neighborsOnLeft.append( neighbors.at( neighborPos ) );
147 static int cutEdgeFromSnappedVertex(
QgsMeshEditor *meshEditor,
149 int startingSnappedVertex,
151 QList<int> &newVerticesOnLeftHole,
152 QList<int> &newNeighborsOnLeftHole,
153 QList<int> &newVerticesOnRightHole,
154 QList<int> &newNeighborsOnRightHole )
158 const int faceSize = face.size();
160 const int beginPos = vertexPositionInFace( startingSnappedVertex, face );
162 const int endPosOnLeft = ( edgePosition + 1 ) % faceSize;
163 const int endPosOnRight = edgePosition;
166 for (
int i = 0; i < faceSize; ++i )
168 int currentPos = ( beginPos + faceSize - i ) % faceSize;
169 newVerticesOnLeftHole.append( face.at( currentPos ) );
170 if ( currentPos == endPosOnLeft )
172 int neighborPos = ( currentPos + faceSize - 1 ) % faceSize;
173 newNeighborsOnLeftHole.append( neighbors.at( neighborPos ) );
177 for (
int i = 0; i < faceSize; ++i )
179 int currentPos = ( beginPos + i ) % faceSize;
180 newVerticesOnRightHole.append( face.at( currentPos ) );
181 if ( currentPos == endPosOnRight )
183 newNeighborsOnRightHole.append( neighbors.at( currentPos ) );
186 return neighbors.at( edgePosition );
195 mTolerance = tolerance;
196 mNewVertexOnIntersection = newVertexOnIntersection;
197 mFirstPointChecked =
false;
198 mSecondPointChecked =
false;
199 mCurrentSnappedVertex = -1;
201 mCurrentPointPosition = mPoint1;
202 mRemovedFaces.clear();
204 mNeighborOnLeft.clear();
205 mHoleOnRight.clear();
206 mNeighborOnRight.clear();
207 mNewVerticesIndexesOnLine.clear();
208 mEndOnPoint2 =
false;
209 mPoint2VertexIndex = -1;
215 mEditor = meshEditor;
217 if ( ! mFirstPointChecked )
219 mFirstPointChecked =
true;
221 if ( mInterpolateZValueOnMesh )
222 interpolateZValueOnMesh( mPoint1 );
226 int faceCloseEdge = -1;
227 if ( meshEditor->
edgeIsClose( mPoint1, mTolerance, faceCloseEdge, closeEdge ) )
231 int vertexIndex1 = face.at( closeEdge );
232 int vertexIndex2 = face.at( ( closeEdge + 1 ) % face.size() );
241 if ( includdingFace != -1 )
248 if ( ! mSecondPointChecked )
250 mSecondPointChecked =
true;
251 if ( mInterpolateZValueOnMesh )
252 interpolateZValueOnMesh( mPoint2 );
256 int faceCloseEdge = -1;
257 if ( meshEditor->
edgeIsClose( mPoint2, mTolerance, faceCloseEdge, closeEdge ) )
261 int vertexIndex1 = face.at( closeEdge );
262 int vertexIndex2 = face.at( ( closeEdge + 1 ) % face.size() );
264 bool snap1 = meshEditor->
triangularMesh()->
vertices().at( vertexIndex1 ).distance( mPoint2 ) <= mTolerance ;
265 bool snap2 = meshEditor->
triangularMesh()->
vertices().at( vertexIndex2 ).distance( mPoint2 ) <= mTolerance ;
270 mPoint2VertexIndex = vertexIndex1;
276 mPoint2VertexIndex = vertexIndex2;
294 if ( includdingFace != -1 )
308 if ( buildForcedElements() )
317 void QgsMeshEditForceByLine::finish()
322 void QgsMeshEditForceByLine::interpolateZValueOnMesh(
QgsPoint &point )
const
327 if ( includdingFace != -1 )
330 if ( triangleFaceIndex != -1 )
336 double z = QgsMeshLayerUtils::interpolateFromVerticesData( tv1, tv2, tv3, tv1.
z(), tv2.
z(), tv3.
z(), point );
344 double distPoint = point.
distance( otherPoint1 );
345 double totalDistance = otherPoint1.
distance( otherPoint2 );
347 point.
setZ( otherPoint1.
z() + ( otherPoint2.
z() - otherPoint1.
z() )*distPoint / totalDistance );
350 bool QgsMeshEditForceByLine::buildForcedElements()
355 QSet<int> treatedFaces;
357 int startingVertexIndex = mesh->
vertices.count();
359 int currentFaceIndex = -1;
360 bool searchOutside =
false;
361 QPair<int, int> currentEdge{-1, -1};
363 int currentAddedVertex = -1;
364 int nextCutFace = -1;
369 if ( mCurrentSnappedVertex == -1 )
372 if ( currentFaceIndex == leftFace )
373 currentFaceIndex = -1;
375 if ( mCurrentSnappedVertex != -1 && !searchOutside )
378 currentFaceIndex = -1;
379 int previousSnappedVertex = -1;
380 int intersectionFaceIndex = -1;
381 QgsPoint intersectionPoint( 0, 0, 0 );
382 int edgePosition = -1;
384 bool result = searchIntersectionEdgeFromSnappedVertex(
385 intersectionFaceIndex,
386 previousSnappedVertex,
387 mCurrentSnappedVertex,
395 if ( mCurrentSnappedVertex != -1 &&
396 mPoint2.
distance( triangularMesh->
vertices().at( mCurrentSnappedVertex ) ) < mTolerance )
400 searchOutside =
true;
404 if ( mEndOnPoint2 && mCurrentSnappedVertex == mPoint2VertexIndex )
410 if ( mCurrentSnappedVertex != -1 )
414 buildHolesWithOneFace( mEditor,
415 intersectionFaceIndex,
416 previousSnappedVertex,
417 mCurrentSnappedVertex,
423 mRemovedFaces.append( intersectionFaceIndex );
425 if ( finishForcingLine() )
434 nextCutFace = cutEdgeFromSnappedVertex( mEditor,
435 intersectionFaceIndex,
436 previousSnappedVertex,
443 mRemovedFaces.append( intersectionFaceIndex );
445 int iv1 = mHoleOnLeft.last();
446 int iv2 = mHoleOnRight.last();
448 if ( mNewVertexOnIntersection )
450 currentAddedVertex = startingVertexIndex +
mVerticesToAdd.count();
452 if ( mInterpolateZValueOnMesh )
453 interpolateZValue( intersectionPoint,
454 triangularMesh->
vertices().at( iv1 ),
455 triangularMesh->
vertices().at( iv2 ) );
457 interpolateZValue( intersectionPoint, mPoint1, mPoint2 );
461 if ( nextCutFace != -1 )
463 mCurrentSnappedVertex = -1;
464 currentFaceIndex = nextCutFace;
465 currentEdge = {mHoleOnLeft.last(), mHoleOnRight.last()};
470 if ( !mNewVertexOnIntersection )
472 currentAddedVertex = startingVertexIndex +
mVerticesToAdd.count();
473 if ( mInterpolateZValueOnMesh )
474 interpolateZValue( intersectionPoint,
475 triangularMesh->
vertices().at( iv1 ),
476 triangularMesh->
vertices().at( iv2 ) );
478 interpolateZValue( intersectionPoint, mPoint1, mPoint2 );
482 mNewVerticesIndexesOnLine.removeLast();
484 mHoleOnLeft.append( currentAddedVertex );
485 mNeighborOnLeft.append( -1 );
486 mHoleOnRight.append( currentAddedVertex );
487 mNeighborOnRight.append( -1 );
489 if ( finishForcingLine() )
494 leftFace = intersectionFaceIndex;
497 mCurrentPointPosition = intersectionPoint;
501 else if ( nextCutFace != -1 )
505 int faceSize = face.size();
507 currentFaceIndex = nextCutFace;
509 mRemovedFaces.append( nextCutFace );
511 int edgePositionOnLeft = vertexPositionInFace( currentEdge.first, face );
512 int edgePositionOnRight = vertexPositionInFace( currentEdge.second, face );
513 int firstEdgeToTest = vertexPositionInFace( currentEdge.second, face );
515 bool foundSomething =
false;
517 for (
int fi = 0; fi < faceSize; ++fi )
519 int iv1 = face.at( ( firstEdgeToTest + fi ) % faceSize );
520 int iv2 = face.at( ( firstEdgeToTest + fi + 1 ) % faceSize );
522 if ( iv1 == currentEdge.first && iv2 == currentEdge.second )
527 if ( edgeIntersection( iv1, iv2, snapVertex, intersection,
false ) ||
530 foundSomething =
true;
532 int endPositionOnRight;
533 int endPositionOnLeft;
535 if ( snapVertex != -1 )
538 endPositionOnRight = vertexPositionInFace( snapVertex, face );
539 endPositionOnLeft = vertexPositionInFace( snapVertex, face );
542 currentEdge = {-1, -1};
543 mCurrentSnappedVertex = snapVertex;
548 endPositionOnLeft = vertexPositionInFace( iv2, face );
549 endPositionOnRight = vertexPositionInFace( iv1, face );
551 nextCutFace = neighbors.at( endPositionOnRight );
553 if ( mNewVertexOnIntersection )
555 currentAddedVertex = startingVertexIndex +
mVerticesToAdd.count();
557 if ( mInterpolateZValueOnMesh )
558 interpolateZValue( intersection,
559 triangularMesh->
vertices().at( iv1 ),
560 triangularMesh->
vertices().at( iv2 ) );
562 interpolateZValue( intersection, mPoint1, mPoint2 );
567 int currentPos = edgePositionOnLeft;
568 while ( currentPos != endPositionOnLeft )
570 int nextPos = ( currentPos - 1 + faceSize ) % faceSize;
571 mHoleOnLeft.append( face.at( nextPos ) );
572 int neighborPos = nextPos;
573 mNeighborOnLeft.append( neighbors.at( neighborPos ) );
574 currentPos = nextPos;
577 currentPos = edgePositionOnRight;
578 while ( currentPos != endPositionOnRight )
580 int nextPos = ( currentPos + 1 ) % faceSize;
581 mHoleOnRight.append( face.at( nextPos ) );
582 int neighborPos = ( nextPos + faceSize - 1 ) % faceSize;
583 mNeighborOnRight.append( neighbors.at( neighborPos ) );
584 currentPos = nextPos;
587 mCurrentPointPosition = intersection;
589 if ( snapVertex != -1 )
591 currentEdge = {-1, -1};
593 if ( finishForcingLine() )
595 mIsFinished = mEndOnPoint2 && mPoint2VertexIndex == snapVertex;
604 else if ( nextCutFace == -1 )
607 if ( !mNewVertexOnIntersection )
609 currentAddedVertex = startingVertexIndex +
mVerticesToAdd.count();
610 if ( mInterpolateZValueOnMesh )
611 interpolateZValue( intersection,
612 triangularMesh->
vertices().at( iv1 ),
613 triangularMesh->
vertices().at( iv2 ) );
615 interpolateZValue( intersection, mPoint1, mPoint2 );
619 mNewVerticesIndexesOnLine.removeLast();
621 mHoleOnLeft.append( currentAddedVertex );
622 mNeighborOnLeft.append( -1 );
623 mHoleOnRight.append( currentAddedVertex );
624 mNeighborOnRight.append( -1 );
626 if ( finishForcingLine() )
635 currentEdge = {mHoleOnLeft.last(), mHoleOnRight.last()};
641 if ( ! foundSomething )
647 else if ( currentFaceIndex == -1 || searchOutside )
650 const QgsRectangle bbox( mCurrentPointPosition, mPoint2 );
652 int closestFaceIndex = -1;
653 int closestEdge = -1;
654 int closestSnapVertex = -1;
655 double minimalDistance = std::numeric_limits<double>::max();
656 QgsPoint closestIntersectionPoint( 0, 0, 0 );
657 for (
const int candidateFaceIndex : candidateFacesIndexes )
659 if ( candidateFaceIndex == leftFace )
662 if ( treatedFaces.contains( candidateFaceIndex ) )
666 const int faceSize = candidateFace.size();
668 for (
int i = 0; i < faceSize; ++i )
670 int iv1 = candidateFace.at( i );
671 int iv2 = candidateFace.at( ( i + 1 ) % faceSize );
673 if ( iv1 == mCurrentSnappedVertex || iv2 == mCurrentSnappedVertex )
678 bool isIntersect = edgeIntersection( iv1, iv2, snapVertex, intersectionPoint,
true );
682 double distance = intersectionPoint.
distance( mCurrentPointPosition );
683 if ( distance < minimalDistance )
685 closestFaceIndex = candidateFaceIndex;
686 closestEdge = candidateFace.at( i );
687 closestSnapVertex = snapVertex;
688 closestIntersectionPoint = intersectionPoint;
689 minimalDistance = distance;
695 if ( closestFaceIndex < 0 || closestEdge < 0 )
702 mCurrentSnappedVertex = closestSnapVertex;
703 treatedFaces.insert( closestFaceIndex );
704 searchOutside =
false;
705 if ( mCurrentSnappedVertex == -1 )
709 currentAddedVertex = startingVertexIndex +
mVerticesToAdd.count();
711 nextCutFace = closestFaceIndex;
713 mHoleOnRight.append( currentAddedVertex );
714 mHoleOnRight.append( face.at( ( vertexPositionInFace( closestEdge, face ) + 1 ) % face.size() ) );
715 mNeighborOnRight.append( -1 );
718 mHoleOnLeft.append( currentAddedVertex );
719 mHoleOnLeft.append( closestEdge ) ;
720 mNeighborOnLeft.append( -1 );
722 currentEdge = {mHoleOnLeft.last(), mHoleOnRight.last()};
724 if ( mInterpolateZValueOnMesh )
725 interpolateZValue( closestIntersectionPoint,
726 triangularMesh->
vertices().at( mHoleOnLeft.last() ),
727 triangularMesh->
vertices().at( mHoleOnRight.last() ) );
729 interpolateZValue( closestIntersectionPoint, mPoint1, mPoint2 );
736 else if ( mCurrentSnappedVertex == -1 )
739 double minimalDistance = std::numeric_limits<double>::max();
741 for (
int i = 0; i < face.size(); ++i )
744 const double distance = mCurrentPointPosition.
distance( vertex );
745 if ( distance < mTolerance && distance < minimalDistance )
747 minimalDistance = distance;
748 mCurrentSnappedVertex = face.at( i );
751 searchOutside =
false;
753 if ( mCurrentSnappedVertex == -1 )
759 if ( mCurrentSnappedVertex != -1 )
761 if ( mCurrentSnappedVertex == mPoint2VertexIndex )
766 mCurrentPointPosition = triangularMesh->
vertices().at( mCurrentSnappedVertex );
775 bool QgsMeshEditForceByLine::searchIntersectionEdgeFromSnappedVertex
776 (
int &intersectionFaceIndex,
777 int &previousSnappedVertex,
778 int ¤tSnappedVertexIndex,
781 QSet<int> &treatedFaces )
783 previousSnappedVertex = currentSnappedVertexIndex;
784 QSet<int> treatedVertices;
788 treatedVertices.insert( currentSnappedVertexIndex );
791 bool foundSomething =
false;
792 for (
const int faceIndex : std::as_const( facesAround ) )
795 int faceSize = face.size();
796 int vertexPos = vertexPositionInFace( currentSnappedVertexIndex, face );
798 int newSnapVertex = -1;
799 for (
int i = 1; i < faceSize - 1; ++i )
801 edgePosition = ( vertexPos + i ) % faceSize ;
802 foundSomething = edgeIntersection( face.at( edgePosition ),
803 face.at( ( edgePosition + 1 ) % faceSize ),
808 if ( mEndOnPoint2 && newSnapVertex == mPoint2VertexIndex )
810 mCurrentSnappedVertex = newSnapVertex;
814 if ( newSnapVertex != -1 )
815 foundSomething = ( newSnapVertex != previousSnappedVertex &&
816 !treatedVertices.contains( newSnapVertex ) );
818 if ( foundSomething )
822 if ( foundSomething )
824 treatedFaces.insert( faceIndex );
825 if ( newSnapVertex != -1 )
827 previousSnappedVertex = currentSnappedVertexIndex;
828 currentSnappedVertexIndex = newSnapVertex;
829 if ( newSnapVertex == face.at( ( vertexPos + 1 ) % faceSize ) || newSnapVertex == face.at( ( vertexPos - 1 + faceSize ) % faceSize ) )
837 intersectionFaceIndex = faceIndex;
843 intersectionFaceIndex = faceIndex;
844 previousSnappedVertex = currentSnappedVertexIndex;
845 currentSnappedVertexIndex = -1;
851 if ( !foundSomething )
858 bool QgsMeshEditForceByLine::triangulateHoles(
859 const QList<int> &hole,
860 const QList<int> &neighbors,
862 QList<std::array<int, 2>> &newFacesOnLine,
863 std::array<int, 2> &extremeFaces )
868 for (
int i = 0; i < hole.count(); ++i )
870 for (
int j = i + 1; j < hole.count(); ++j )
872 if ( hole.at( i ) == hole.at( j ) )
883 std::vector<p2t::Point *> holeToFill;
886 QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
887 holeToFill.resize( hole.count() + mNewVerticesIndexesOnLine.count() );
888 for (
int i = 0; i < hole.count(); ++i )
890 int vertexIndex = hole.at( i );
892 if ( vertexIndex < mesh->vertexCount() )
893 vertex = mesh->
vertex( vertexIndex );
897 holeToFill[i] =
new p2t::Point( vertex.
x(), vertex.
y() );
898 mapPoly2TriPointToVertex.insert( holeToFill[i], vertexIndex );
901 const int verticesOnLineCount = mNewVerticesIndexesOnLine.count();
902 for (
int i = 0; i < verticesOnLineCount; ++i )
904 int vertexLocalIndex = mNewVerticesIndexesOnLine.at( verticesOnLineCount - i - 1 );
906 holeToFill[i + hole.count()] =
new p2t::Point( vertex.
x(), vertex.
y() );
907 mapPoly2TriPointToVertex.insert( holeToFill[i + hole.count()], vertexLocalIndex + mesh->
vertexCount() );
910 std::unique_ptr<p2t::CDT> cdt(
new p2t::CDT( holeToFill ) );
912 std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
913 QVector<QgsMeshFace> newFaces( triangles.size() );
914 for (
size_t i = 0; i < triangles.size(); ++i )
918 for (
int j = 0; j < 3; j++ )
920 int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
922 throw std::exception();
930 throw std::exception();
932 const QVector<QgsMeshFace> &facesToAdd = topologicalFaces.
meshFaces();
936 for (
const int vtc : hole )
939 if ( mRemovedFaces.contains( firstLinkedFace ) )
944 for (
int i = 0; i < facesToAdd.count(); ++i )
948 for (
int n = 0; n < faceNeighbors.count(); ++n )
950 if ( faceNeighbors.at( n ) != -1 )
951 faceNeighbors[n] += startingFaceGlobalIndex;
956 for (
int i = 0 ; i < hole.count() - 1; ++i )
958 int vertexHoleIndex = hole.at( i );
959 int meshFaceBoundaryIndex = neighbors.at( i );
963 throw std::exception();
971 int newFaceBoundaryIndexInMesh = circulator.
currentFaceIndex() + startingFaceGlobalIndex;
973 int positionInNewFaces = vertexPositionInFace( vertexHoleIndex, newFace );
975 positionInNewFaces = ( positionInNewFaces - 1 + newFace.size() ) % newFace.size();
977 if ( meshFaceBoundaryIndex != -1 )
981 int positionInMeshFaceBoundary = vertexPositionInFace( *mesh, vertexHoleIndex, meshFaceBoundaryIndex );
983 positionInMeshFaceBoundary = ( positionInMeshFaceBoundary - 1 + meshFace.size() ) % meshFace.size();
986 mNeighborhoodChanges.append( {meshFaceBoundaryIndex, positionInMeshFaceBoundary, oldNeighbor, newFaceBoundaryIndexInMesh} );
989 mFacesNeighborhoodToAdd[newFaceBoundaryLocalIndex + startingFaceLocalIndex][positionInNewFaces] = meshFaceBoundaryIndex;
993 int vertexOnLine = hole.at( 0 );
994 while ( vertexOnLine != hole.last() )
1000 circulatorOnLine.goBoundaryClockwise();
1001 nextVertex = circulatorOnLine.oppositeVertexClockwise();
1005 circulatorOnLine.goBoundaryCounterClockwise();
1006 nextVertex = circulatorOnLine.oppositeVertexCounterClockwise();
1008 const QgsMeshFace &faceOnLine = circulatorOnLine.currentFace();
1009 int positionOnFaceOnTheLine = vertexPositionInFace( vertexOnLine, faceOnLine );
1011 positionOnFaceOnTheLine = ( positionOnFaceOnTheLine - 1 + faceOnLine.size() ) % faceOnLine.size();
1013 newFacesOnLine.append( {circulatorOnLine.currentFaceIndex() + startingFaceLocalIndex, positionOnFaceOnTheLine} );
1014 vertexOnLine = nextVertex;
1019 circulatorOnStart.goBoundaryCounterClockwise();
1021 circulatorOnStart.goBoundaryClockwise();
1025 circulatorOnEnd.goBoundaryClockwise();
1027 circulatorOnEnd.goBoundaryCounterClockwise();
1030 extremeFaces = {circulatorOnStart.currentFaceIndex() + startingFaceLocalIndex,
1031 circulatorOnEnd.currentFaceIndex() + startingFaceLocalIndex
1033 qDeleteAll( holeToFill );
1037 qDeleteAll( holeToFill );
1046 bool QgsMeshEditForceByLine::finishForcingLine()
1050 QList<std::array<int, 2>> newLeftFacesOnLine;
1051 QList<std::array<int, 2>> newRightFacesOnLine;
1053 std::array<int, 2> extremeFacesOnLeft;
1054 std::array<int, 2> extremeFacesOnRight;
1056 if ( !triangulateHoles( mHoleOnLeft, mNeighborOnLeft,
true, newLeftFacesOnLine, extremeFacesOnLeft ) )
1058 if ( !triangulateHoles( mHoleOnRight, mNeighborOnRight,
false, newRightFacesOnLine, extremeFacesOnRight ) )
1062 if ( newLeftFacesOnLine.count() != newRightFacesOnLine.count() )
1065 for (
int i = 0; i < newLeftFacesOnLine.count(); ++i )
1067 int leftFaceLocalIndex = newLeftFacesOnLine.at( i ).at( 0 );
1068 int leftPositionInFace = newLeftFacesOnLine.at( i ).at( 1 );
1069 int rightFaceLocalIndex = newRightFacesOnLine.at( i ).at( 0 );
1070 int rightPositionInFace = newRightFacesOnLine.at( i ).at( 1 );
1078 const int firstVertexIndex = mHoleOnLeft.first();
1081 const int firstVertexLocalIndex = firstVertexIndex - mesh->
vertexCount();
1085 const int lastVertexIndex = mHoleOnLeft.last();
1088 const int lastVertexLocalIndex = lastVertexIndex - mesh->
vertexCount();
1092 for (
int i = 0; i < mNewVerticesIndexesOnLine.count(); ++i )
1097 for (
const int fi : std::as_const( mRemovedFaces ) )
1104 mRemovedFaces.clear();
1105 mHoleOnLeft.clear();
1106 mNeighborOnLeft.clear();
1107 mHoleOnRight.clear();
1108 mNeighborOnRight.clear();
1109 mNewVerticesIndexesOnLine.clear();
1116 return QObject::tr(
"Force mesh by polyline" );
1126 if ( mPolylines.isEmpty() )
1132 if ( mCurrentPolyline == 0 && mCurrentSegment == 0 )
1135 mPolylines.at( 0 ).at( 1 ),
1136 mTolerance, mNewVertexOnIntersection );
1139 return QgsMeshEditForceByLine::apply( meshEditor );
1144 setInputLine( mPolylines.at( mCurrentPolyline ).at( mCurrentSegment ),
1145 mPolylines.at( mCurrentPolyline ).at( mCurrentSegment + 1 ),
1146 mTolerance, mNewVertexOnIntersection );
1150 return QgsMeshEditForceByLine::apply( meshEditor );
1155 std::vector<const QgsCurve *> curves;
1158 std::vector< const QgsCurvePolygon * > polygons;
1163 polygons.emplace_back( qgsgeometry_cast< const QgsCurvePolygon * >( ms->
geometryN( i ) ) );
1166 polygons.emplace_back( qgsgeometry_cast< const QgsCurvePolygon * >( geom.
constGet() ) );
1173 if ( polygon->exteriorRing() )
1174 curves.emplace_back( polygon->exteriorRing() );
1176 for (
int i = 0; i < polygon->numInteriorRings(); ++i )
1177 curves.emplace_back( polygon->interiorRing( i ) );
1186 curves.emplace_back( qgsgeometry_cast< const QgsCurve * >( mc->
geometryN( i ) ) );
1189 curves.emplace_back( qgsgeometry_cast< const QgsCurve * >( geom.
constGet() ) );
1192 for (
const QgsCurve *curve : curves )
1198 curve->points( linePoints );
1199 if ( linePoints.count() < 2 )
1201 if ( !curve->is3D() )
1203 for (
int i = 0; i < linePoints.count(); ++i )
1205 const QgsPoint &point = linePoints.at( i );
1206 linePoints[i] =
QgsPoint( point.
x(), point.
y(), mDefaultZValue );
1209 mPolylines.append( linePoints );
1221 mTolerance = tolerance;
1226 mNewVertexOnIntersection = addVertex;
1231 mDefaultZValue = defaultZValue;
1236 mInterpolateZValueOnMesh = interpolateZValueOnMesh;
1239 void QgsMeshEditForceByPolylines::incrementSegment()
1242 if ( mCurrentSegment >= mPolylines.at( mCurrentPolyline ).count() - 1 )
1244 mCurrentSegment = 0;