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 static double crossProduct(
int centralVertex,
int vertex1,
int vertex2,
const QgsMesh &mesh )
47 double ux1 = v1.
x() - vc.
x();
48 double uy1 = v1.
y() - vc.
y();
49 double vx1 = v2.
x() - vc.
x();
50 double vy1 = v2.
y() - vc.
y();
52 return ux1 * vy1 - uy1 * vx1;
57 : mFaces( topologicalMesh.mMesh->faces )
58 , mFacesNeighborhood( topologicalMesh.mFacesNeighborhood )
59 , mVertexIndex( vertexIndex )
61 if ( vertexIndex >= 0 && vertexIndex < topologicalMesh.mMesh->vertexCount() )
63 mCurrentFace = topologicalMesh.mVertexToFace[vertexIndex];
64 mIsValid = vertexPositionInFace( *topologicalMesh.
mesh(), vertexIndex, mCurrentFace ) != -1;
72 mLastValidFace = mCurrentFace;
76 : mFaces( topologicalFaces.mFaces )
77 , mFacesNeighborhood( topologicalFaces.mFacesNeighborhood )
78 , mVertexIndex( vertexIndex )
80 const QgsMeshFace &face = topologicalFaces.mFaces.at( faceIndex );
81 mIsValid = vertexPositionInFace( vertexIndex, face ) != -1;
83 mCurrentFace = faceIndex;
84 mLastValidFace = mCurrentFace;
88 : mFaces( topologicalFaces.mFaces )
89 , mFacesNeighborhood( topologicalFaces.mFacesNeighborhood )
90 , mVertexIndex( vertexIndex )
92 if ( topologicalFaces.mVerticesToFace.contains( vertexIndex ) )
93 mCurrentFace = topologicalFaces.mVerticesToFace.values( vertexIndex ).first();
94 mLastValidFace = mCurrentFace;
95 mIsValid = mCurrentFace != -1;
100 if ( mCurrentFace == -1 )
101 mCurrentFace = mLastValidFace;
104 int currentPos = positionInCurrentFace();
105 Q_ASSERT( currentPos != -1 );
109 mLastValidFace = mCurrentFace;
110 mCurrentFace = mFacesNeighborhood.at( mCurrentFace ).at( ( currentPos + faceSize - 1 ) %
currentFace.count() );
118 if ( mCurrentFace == -1 )
119 mCurrentFace = mLastValidFace;
122 int currentPos = positionInCurrentFace();
123 Q_ASSERT( currentPos != -1 );
127 mLastValidFace = mCurrentFace;
128 mCurrentFace = mFacesNeighborhood.at( mCurrentFace ).at( ( currentPos ) % faceSize );
141 if ( mCurrentFace != -1 )
142 return mFaces.at( mCurrentFace );
152 if ( mCurrentFace == -1 )
153 mCurrentFace = mLastValidFace;
155 int firstFace = mCurrentFace;
158 if ( mCurrentFace == firstFace )
169 if ( mCurrentFace == -1 )
170 mCurrentFace = mLastValidFace;
172 int firstFace = mCurrentFace;
175 if ( mCurrentFace == firstFace )
183 if ( mCurrentFace == -1 )
188 if ( face.isEmpty() )
191 int vertexPosition = vertexPositionInFace( mVertexIndex,
currentFace() );
193 if ( vertexPosition == -1 )
196 return face.at( ( vertexPosition + 1 ) % face.count() );
201 if ( mCurrentFace == -1 )
206 if ( face.isEmpty() )
209 int vertexPosition = vertexPositionInFace( mVertexIndex,
currentFace() );
211 if ( vertexPosition == -1 )
214 return face.at( ( vertexPosition - 1 + face.count() ) % face.count() );
228 if ( mCurrentFace != -1 )
229 ret.append( mCurrentFace );
274 int QgsMeshVertexCirculator::positionInCurrentFace()
const
276 if ( mCurrentFace < 0 || mCurrentFace > mFaces.count() )
279 return vertexPositionInFace( mVertexIndex, mFaces.at( mCurrentFace ) );
289 for (
int i = 0; i < changes.
mFacesToAdd.count(); ++i )
292 for (
int boundary : topologicalFaces.mBoundaries )
295 if ( mVertexToFace.at( boundary ) == -1 )
298 const QList<int> &linkedFaces = topologicalFaces.mVerticesToFace.values( boundary );
299 for (
int linkedFace : linkedFaces )
305 if ( mVertexToFace.at( oppositeVertexForNewFace ) == -1 )
313 int boundaryPositionInNewFace = vertexPositionInFace( boundary, newFaceBoundary );
315 if ( oppositeVertexForMeshFace != oppositeVertexForNewFace )
327 boundaryPositionInMeshFace,
337 for (
int f = 0; f < changes.
mFacesToAdd.count(); ++f )
338 for (
int n = 0; n < changes.
mFacesToAdd.at( f ).count(); ++n )
340 changes.
mFacesNeighborhoodToAdd[f][n] = changes.addedFaceIndexInMesh( topologicalFaces.mFacesNeighborhood.at( f ).at( n ) );
342 const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
343 for (
const int vtc : verticesToFaceToChange )
344 if ( mVertexToFace.at( vtc ) == -1 )
346 mVertexToFace.at( vtc ),
347 changes.addedFaceIndexInMesh( topologicalFaces.mVerticesToFace.values( vtc ).first() ) } );
356 int initialVerticesCount = mMesh->
vertices.count();
361 mVertexToFace.resize( newSize );
367 mMesh->
faces.resize( newSize );
368 mFacesNeighborhood.resize( newSize );
374 mFacesNeighborhood[changes.removedFaceIndexInMesh( i )] =
FaceNeighbors();
380 if ( mVertexToFace.at( vertexIndex ) == -1 )
381 dereferenceAsFreeVertex( vertexIndex );
383 mVertexToFace[vertexIndex] = -1;
391 referenceAsFreeVertex( initialVerticesCount + i );
394 for (
int i = 0; i < changes.
mFacesToAdd.count(); ++i )
396 mMesh->
faces[changes.addedFaceIndexInMesh( i )] = changes.
mFacesToAdd.at( i );
402 const int faceIndex = neigborChange.at( 0 );
403 const int positionInFace = neigborChange.at( 1 );
404 const int valueToApply = neigborChange.at( 3 );
405 mFacesNeighborhood[faceIndex][positionInFace] = valueToApply;
410 int vertexIndex = vertexToFaceChange.at( 0 );
411 mVertexToFace[vertexToFaceChange.at( 0 )] = vertexToFaceChange.at( 2 );
413 if ( vertexToFaceChange.at( 2 ) == -1 &&
414 vertexToFaceChange.at( 1 ) != -1 &&
415 !mMesh->
vertices.at( vertexIndex ).isEmpty() )
416 referenceAsFreeVertex( vertexIndex );
418 if ( vertexToFaceChange.at( 1 ) == -1 && vertexToFaceChange.at( 2 ) != -1 )
419 dereferenceAsFreeVertex( vertexIndex );
430 mMesh->
vertices[vertexIndex].setX( pt.
x() );
431 mMesh->
vertices[vertexIndex].setY( pt.
y() );
440 const int faceIndex = neigborChange.at( 0 );
441 const int positionInFace = neigborChange.at( 1 );
442 const int valueToApply = neigborChange.at( 2 );
443 mFacesNeighborhood[faceIndex][positionInFace] = valueToApply;
457 if ( mVertexToFace.at( vertexIndex ) == -1 )
458 referenceAsFreeVertex( vertexIndex );
462 for (
int i = 0; i < verticesToFaceChangesCount; ++i )
464 const std::array<int, 3> vertexToFaceChange = changes.
mVerticesToFaceChanges.at( verticesToFaceChangesCount - i - 1 );
465 int vertexIndex = vertexToFaceChange.at( 0 );
466 mVertexToFace[vertexIndex] = vertexToFaceChange.at( 1 );
468 if ( vertexToFaceChange.at( 2 ) == -1 && vertexToFaceChange.at( 1 ) != -1 )
469 dereferenceAsFreeVertex( vertexIndex );
471 if ( vertexToFaceChange.at( 1 ) == -1 &&
472 vertexToFaceChange.at( 2 ) != -1 &&
474 referenceAsFreeVertex( vertexIndex );
480 mMesh->
faces.resize( newSize );
481 mFacesNeighborhood.resize( newSize );
488 for (
int i = newSize; i < mMesh->
vertexCount(); ++i )
489 if ( mVertexToFace.at( i ) == -1 )
490 dereferenceAsFreeVertex( i );
493 mVertexToFace.resize( newSize );
504 mMesh->
vertices[vertexIndex].setX( pt.
x() );
505 mMesh->
vertices[vertexIndex].setY( pt.
y() );
515 QSet<int> QgsTopologicalMesh::concernedFacesBy(
const QList<int> faceIndexes )
const
518 for (
const int faceIndex : faceIndexes )
521 for (
int i = 0; i < face.count(); ++i )
527 void QgsTopologicalMesh::dereferenceAsFreeVertex(
int vertexIndex )
529 mFreeVertices.remove( vertexIndex );
532 void QgsTopologicalMesh::referenceAsFreeVertex(
int vertexIndex )
536 mFreeVertices.insert( vertexIndex );
541 for (
int faceIndex = 0 ; faceIndex < mMesh->
faces.count( ); ++faceIndex )
544 const FaceNeighbors &neighborhood = mFacesNeighborhood.at( faceIndex );
545 if ( face.count() != neighborhood.count() )
547 for (
int i = 0; i < face.count(); ++i )
549 int vertexIndex = face.at( i );
551 if ( mVertexToFace.at( vertexIndex ) == -1 )
554 int neighborIndex = neighborhood.at( i );
555 if ( neighborIndex != -1 )
558 if ( neighborFace.isEmpty() )
560 int neighborSize = neighborFace.size();
561 const FaceNeighbors &neighborhoodOfNeighbor = mFacesNeighborhood.at( neighborIndex );
562 int posInNeighbor = vertexPositionInFace( *mMesh, vertexIndex, neighborIndex );
563 if ( neighborhoodOfNeighbor.isEmpty() || neighborhoodOfNeighbor.at( ( posInNeighbor + neighborSize - 1 ) % neighborSize ) != faceIndex )
569 for (
int vertexIndex = 0; vertexIndex < mMesh->
vertexCount(); ++vertexIndex )
571 if ( mVertexToFace.at( vertexIndex ) != -1 )
573 if ( !mMesh->
face( mVertexToFace.at( vertexIndex ) ).contains( vertexIndex ) )
599 if ( vertexIndex < 0 || vertexIndex >= mMesh->
vertexCount() )
601 return mVertexToFace.at( vertexIndex );
616 if ( vertexIndex < 0 || vertexIndex >= mMesh->
vertexCount() )
619 if ( mMesh->
vertices.at( vertexIndex ).isEmpty() )
622 return mVertexToFace.at( vertexIndex ) == -1;
627 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
628 return mFreeVertices.values();
630 return QList<int>( mFreeVertices.begin(), mFreeVertices.end() );
638 int faceSize = face.count();
643 for (
int i = 0; i < faceSize; ++i )
646 int iv1 = face[( i + 1 ) % faceSize];
647 int iv2 = face[( i + 2 ) % faceSize];
671 double crossProd = crossProduct( iv1, iv0, iv2, *
mesh );
672 if ( direction != 0 && crossProd * direction < 0 )
674 else if ( crossProd == 0 )
676 else if ( direction == 0 && crossProd != 0 )
677 direction = crossProd / std::fabs( crossProd );
682 for (
int i = 0; i < faceSize / 2; ++i )
685 face[i] = face.at( faceSize - i - 1 );
686 face[faceSize - i - 1] = temp;
695 QVector<int> oldToNewIndex( mMesh->
vertices.count(), -1 );
699 while ( oldIndex < verticesTotalCount )
707 oldToNewIndex[oldIndex] = newIndex;
708 if ( oldIndex != newIndex )
710 oldToNewIndex[oldIndex] = newIndex;
720 int facesTotalCount = mMesh->
faceCount();
721 while ( oldIndex < facesTotalCount )
723 if ( mMesh->
face( oldIndex ).isEmpty() )
727 if ( oldIndex != newIndex )
728 mMesh->
faces[newIndex] = mMesh->
faces[oldIndex];
730 for (
int i = 0; i < face.count(); ++i )
731 face[i] = oldToNewIndex[face.at( i )];
737 mMesh->
faces.resize( newIndex );
739 mVertexToFace.clear();
740 mFacesNeighborhood.clear();
745 QVector<int> oldToNewVerticesIndexes;
746 if ( !renumberVertices( oldToNewVerticesIndexes ) )
750 QVector<int> oldToNewFacesIndexes;
752 if ( !renumberFaces( oldToNewFacesIndexes ) )
757 QVector<QgsMeshVertex> tempVertices( mMesh->
vertices.count() );
758 for (
int i = 0; i < oldToNewVerticesIndexes.count(); ++i )
760 tempVertices[oldToNewVerticesIndexes.at( i )] = mMesh->
vertex( i );
764 QVector<QgsMeshFace> tempFaces( mMesh->
faces.count() );
765 for (
int i = 0; i < oldToNewFacesIndexes.count(); ++i )
767 tempFaces[oldToNewFacesIndexes.at( i )] = mMesh->
face( i );
769 QgsMeshFace &face = tempFaces[oldToNewFacesIndexes.at( i )];
771 for (
int fi = 0; fi < face.count(); ++fi )
773 face[fi] = oldToNewVerticesIndexes.at( face.at( fi ) );
777 mMesh->
faces = tempFaces;
783 bool QgsTopologicalMesh::renumberVertices( QVector<int> &oldToNewIndex )
const
785 std::vector<QgsMeshVertexCirculator> circulators;
786 circulators.reserve( mMesh->
vertices.count() );
787 int minDegree = std::numeric_limits<int>::max();
788 int minDegreeVertex = -1;
791 QSet<int> nonThreadedVertex;
792 oldToNewIndex = QVector<int> ( mMesh->
vertexCount(), -1 );
795 circulators.emplace_back( *
this, i );
797 if ( circulators.back().degree() < minDegree )
799 minDegreeVertex = circulators.size() - 1;
800 minDegree = circulator.
degree();
802 nonThreadedVertex.insert( i );
805 auto sortedNeighbor = [ = ]( QList<int> &neighbors,
int index )
819 int degree = circulators.at( neighborIndex ).degree();
820 QList<int>::Iterator it = neighbors.begin();
821 while ( it != neighbors.end() )
823 if ( degree <= circulators.at( *it ).degree() )
825 neighbors.insert( it, neighborIndex );
830 if ( it == neighbors.end() )
831 neighbors.append( neighborIndex );
837 int currentVertex = minDegreeVertex;
838 nonThreadedVertex.remove( minDegreeVertex );
840 while ( newIndex < mMesh->vertexCount() )
842 if ( oldToNewIndex[currentVertex] == -1 )
843 oldToNewIndex[currentVertex] = newIndex++;
845 if ( circulators.at( currentVertex ).isValid() )
847 QList<int> neighbors;
848 sortedNeighbor( neighbors, currentVertex );
850 for (
const int i : std::as_const( neighbors ) )
851 if ( oldToNewIndex.at( i ) == -1 && nonThreadedVertex.contains( i ) )
854 nonThreadedVertex.remove( i );
858 if ( queue.isEmpty() )
860 if ( nonThreadedVertex.isEmpty() && newIndex < mMesh->vertexCount() )
863 const QList<int> remainingVertex = qgis::setToList( nonThreadedVertex );
864 int minRemainingDegree = std::numeric_limits<int>::max();
865 int minRemainingVertex = -1;
866 for (
const int i : remainingVertex )
868 int degree = circulators.at( i ).degree();
869 if ( degree < minRemainingDegree )
871 minRemainingDegree = degree;
872 minRemainingVertex = i;
875 currentVertex = minRemainingVertex;
876 nonThreadedVertex.remove( currentVertex );
880 currentVertex = queue.dequeue();
887 bool QgsTopologicalMesh::renumberFaces( QVector<int> &oldToNewIndex )
const
890 QSet<int> nonThreadedFaces;
892 oldToNewIndex = QVector<int>( mMesh->
faceCount(), -1 );
894 QVector<int> faceDegrees( mMesh->
faceCount(), 0 );
896 int minDegree = std::numeric_limits<int>::max();
897 int minDegreeFace = -1;
898 for (
int faceIndex = 0; faceIndex < mMesh->
faceCount(); ++faceIndex )
900 const FaceNeighbors &neighbors = mFacesNeighborhood.at( faceIndex );
903 for (
int n = 0; n < neighbors.size(); ++n )
905 if ( neighbors.at( n ) != -1 )
909 if ( degree < minDegree )
912 minDegreeFace = faceIndex;
915 faceDegrees[faceIndex] = degree;
916 nonThreadedFaces.insert( faceIndex );
920 int currentFace = minDegreeFace;
921 nonThreadedFaces.remove( minDegreeFace );
923 auto sortedNeighbor = [ = ]( QList<int> &neighbors,
int index )
925 const FaceNeighbors &neighborhood = mFacesNeighborhood.at( index );
927 for (
int i = 0; i < neighborhood.count(); ++i )
929 int neighborIndex = neighborhood.at( i );
930 if ( neighborIndex == -1 )
933 int degree = faceDegrees.at( neighborIndex );
934 if ( neighbors.isEmpty() )
935 neighbors.append( neighborIndex );
938 QList<int>::Iterator it = neighbors.begin();
939 while ( it != neighbors.end() )
941 if ( degree <= faceDegrees.at( *it ) )
943 neighbors.insert( it, neighborIndex );
948 if ( it == neighbors.end() )
949 neighbors.append( neighborIndex );
954 while ( newIndex < mMesh->faceCount() )
956 if ( oldToNewIndex[currentFace] == -1 )
957 oldToNewIndex[currentFace] = newIndex++;
959 QList<int> neighbors;
960 sortedNeighbor( neighbors, currentFace );
962 for (
const int i : std::as_const( neighbors ) )
963 if ( oldToNewIndex.at( i ) == -1 && nonThreadedFaces.contains( i ) )
966 nonThreadedFaces.remove( i );
969 if ( queue.isEmpty() )
971 if ( nonThreadedFaces.isEmpty() && newIndex < mMesh->faceCount() )
974 const QList<int> remainingFace = qgis::setToList( nonThreadedFaces );
975 int minRemainingDegree = std::numeric_limits<int>::max();
976 int minRemainingFace = -1;
977 for (
const int i : remainingFace )
979 int degree = faceDegrees.at( i );
980 if ( degree < minRemainingDegree )
982 minRemainingDegree = degree;
983 minRemainingFace = i;
986 currentFace = minRemainingFace;
987 nonThreadedFaces.remove( currentFace );
991 currentFace = queue.dequeue();
1006 return mFacesToRemove;
1011 return mFaceIndexesToRemove;
1016 return mVerticesToAdd;
1021 return mChangeCoordinateVerticesIndexes;
1031 return mNewXYValues;
1036 return mOldXYValues;
1041 return mNativeFacesIndexesGeometryChanged;
1046 return ( mFaceIndexesToRemove.isEmpty() &&
1047 mFacesToAdd.isEmpty() &&
1048 mFacesNeighborhoodToAdd.isEmpty() &&
1049 mFacesToRemove.isEmpty() &&
1050 mFacesNeighborhoodToRemove.isEmpty() &&
1051 mNeighborhoodChanges.isEmpty() &&
1052 mVerticesToAdd.isEmpty() &&
1053 mVertexToFaceToAdd.isEmpty() &&
1054 mVerticesToRemoveIndexes.isEmpty() &&
1055 mRemovedVertices.isEmpty() &&
1056 mVerticesToFaceRemoved.isEmpty() &&
1057 mVerticesToFaceChanges.isEmpty() &&
1058 mChangeCoordinateVerticesIndexes.isEmpty() &&
1059 mNewZValues.isEmpty() &&
1060 mOldZValues.isEmpty() &&
1061 mNewXYValues.isEmpty() &&
1062 mOldXYValues.isEmpty() &&
1063 mNativeFacesIndexesGeometryChanged.isEmpty() );
1068 return mVerticesToRemoveIndexes;
1071 int QgsTopologicalMesh::Changes::addedFaceIndexInMesh(
int internalIndex )
const
1073 if ( internalIndex == -1 )
1076 return internalIndex + mAddedFacesFirstIndex;
1079 int QgsTopologicalMesh::Changes::removedFaceIndexInMesh(
int internalIndex )
const
1081 if ( internalIndex == -1 )
1084 return mFaceIndexesToRemove.at( internalIndex );
1089 mAddedFacesFirstIndex = 0;
1090 mFaceIndexesToRemove.clear();
1091 mFacesToAdd.clear();
1092 mFacesNeighborhoodToAdd.clear();
1093 mFacesToRemove.clear();
1094 mFacesNeighborhoodToRemove.clear();
1095 mNeighborhoodChanges.clear();
1097 mVerticesToAdd.clear();
1098 mVertexToFaceToAdd.clear();
1099 mVerticesToRemoveIndexes.clear();
1100 mRemovedVertices.clear();
1101 mVerticesToFaceRemoved.clear();
1102 mVerticesToFaceChanges.clear();
1104 mChangeCoordinateVerticesIndexes.clear();
1105 mNewZValues.clear();
1106 mOldZValues.clear();
1107 mNewXYValues.clear();
1108 mOldXYValues.clear();
1109 mNativeFacesIndexesGeometryChanged.clear();
1119 mVertexToFace.append( -1 );
1120 referenceAsFreeVertex( mMesh->
vertices.count() - 1 );
1126 static double vertexPolygonOrientation(
const QgsMesh &
mesh,
const QList<int> &vertexIndexes )
1128 if ( vertexIndexes.count() < 3 )
1131 int hullDomainVertexPos = -1;
1132 double xMin = std::numeric_limits<double>::max();
1133 double yMin = std::numeric_limits<double>::max();
1134 for (
int i = 0; i < vertexIndexes.count(); ++i )
1137 if ( xMin >= vertex.
x() && yMin > vertex.
y() )
1139 hullDomainVertexPos = i;
1145 if ( hullDomainVertexPos >= 0 )
1147 int iv1 = vertexIndexes.at( ( hullDomainVertexPos - 1 + vertexIndexes.count() ) % vertexIndexes.count() );
1148 int iv2 = vertexIndexes.at( ( hullDomainVertexPos + 1 ) % vertexIndexes.count() );
1149 int ivc = vertexIndexes.at( ( hullDomainVertexPos ) );
1150 double cp = crossProduct( ivc, iv1, iv2,
mesh );
1159 if ( vertexIndex >= mVertexToFace.count() )
1162 if ( mVertexToFace.at( vertexIndex ) == -1 )
1168 dereferenceAsFreeVertex( vertexIndex );
1176 QList<int> boundariesVertexIndex;
1177 QList<int> associateFaceToBoundaries;
1178 QList<int> removedFacesIndexes;
1179 QSet<int> boundaryInGlobalMesh;
1185 Q_ASSERT( !mMesh->
vertices.at( boundariesVertexIndex.last() ).isEmpty() );
1187 associateFaceToBoundaries.append( mFacesNeighborhood.at( circulator.
currentFaceIndex() ).at(
1188 vertexPositionInFace( boundariesVertexIndex.last(), currentFace ) ) );
1190 if ( currentFace.count() > 3 )
1192 int posInface = vertexPositionInFace( vertexIndex, currentFace );
1193 for (
int i = 2; i < currentFace.count() - 1; ++i )
1195 boundariesVertexIndex.append( currentFace.at( ( posInface + i ) % currentFace.count() ) );
1196 Q_ASSERT( !mMesh->
vertices.at( boundariesVertexIndex.last() ).isEmpty() );
1197 associateFaceToBoundaries.append( mFacesNeighborhood.at( circulator.
currentFaceIndex() ).at(
1198 vertexPositionInFace( boundariesVertexIndex.last(), currentFace ) ) );
1204 bool boundaryFill =
false;
1207 boundaryFill =
true;
1211 boundariesVertexIndex.append( lastVertexIndex );
1220 boundaryFill =
false;
1223 associateFaceToBoundaries.append( -1 );
1225 for (
const int index : std::as_const( boundariesVertexIndex ) )
1228 boundaryInGlobalMesh.insert( index );
1232 int currentVertexToFace = mVertexToFace.at( vertexIndex );
1236 QList<QList<int>> holes;
1237 QList<QList<int>> associateMeshFacesToHoles;
1239 bool cancelOperation =
false;
1247 int finalPos = boundariesVertexIndex.count() - 1;
1248 QList<int> uncoveredVertex;
1250 QList<int> partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
1251 QList<int> associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
1252 while ( startPos < finalPos && !partToCheck.isEmpty() )
1255 int secondPos = partToCheck.count() - 1;
1256 const QgsPoint &closingSegmentExtremety1 = mMesh->
vertex( partToCheck.at( 0 ) );
1257 const QgsPoint &closingSegmentExtremety2 = mMesh->
vertex( partToCheck.last() );
1258 bool isEdgeIntersect =
false;
1259 for (
int i = 1; i < secondPos - 1; ++i )
1263 bool isLineIntersection;
1266 if ( isEdgeIntersect )
1270 int index = partToCheck.at( 0 );
1271 if ( boundaryInGlobalMesh.contains( index ) && index != boundariesVertexIndex.at( 0 ) )
1273 cancelOperation =
true;
1279 if ( isEdgeIntersect || vertexPolygonOrientation( *mMesh, partToCheck ) >= 0 )
1281 partToCheck.removeLast();
1282 associateFacePart.removeAt( associateFacePart.count() - 2 );
1283 if ( partToCheck.count() == 1 )
1285 uncoveredVertex.append( index );
1286 startPos = startPos + 1;
1287 partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
1288 associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
1294 holes.append( partToCheck );
1295 associateMeshFacesToHoles.append( associateFacePart );
1297 startPos = startPos + partToCheck.count() - 1;
1298 uncoveredVertex.append( partToCheck.at( 0 ) );
1299 partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
1300 associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
1306 holes.append( boundariesVertexIndex );
1307 associateMeshFacesToHoles.append( associateFaceToBoundaries );
1310 if ( cancelOperation )
1316 Q_ASSERT( holes.count() == associateMeshFacesToHoles.count() );
1322 dereferenceAsFreeVertex( vertexIndex );
1324 mVertexToFace[vertexIndex] = -1;
1327 for (
int h = 0; h < holes.count(); ++h )
1329 const QList<int> &holeVertices = holes.at( h );
1330 const QList<int> &associateMeshFacesToHole = associateMeshFacesToHoles.at( h );
1331 QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
1332 std::vector<p2t::Point *> holeToFill( holeVertices.count() );
1335 for (
int i = 0; i < holeVertices.count(); ++i )
1338 holeToFill[i] =
new p2t::Point( vertex.
x(), vertex.
y() );
1339 mapPoly2TriPointToVertex.insert( holeToFill[i], holeVertices.at( i ) );
1342 std::unique_ptr<p2t::CDT> cdt(
new p2t::CDT( holeToFill ) );
1345 std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
1346 QVector<QgsMeshFace> newFaces( triangles.size() );
1347 for (
size_t i = 0; i < triangles.size(); ++i )
1351 for (
int j = 0; j < 3; j++ )
1353 int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
1354 if ( vertInd == -1 )
1355 throw std::exception();
1356 Q_ASSERT( !mMesh->
vertices.at( vertInd ).isEmpty() );
1364 throw std::exception();
1365 int newFaceIndexStartIndex = mMesh->
faceCount();
1372 const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
1373 for (
const int vtc : verticesToFaceToChange )
1374 if ( mVertexToFace.at( vtc ) == -1 )
1376 mVertexToFace.at( vtc ),
1377 addChanges.addedFaceIndexInMesh( topologicalFaces.mVerticesToFace.values( vtc ).first() ) } );
1381 for (
int i = 0; i < topologicalFaces.mFaces.count(); ++i )
1384 faceNeighbors = topologicalFaces.mFacesNeighborhood.at( i );
1385 for (
int n = 0; n < faceNeighbors.count(); ++n )
1387 if ( faceNeighbors.at( n ) != -1 )
1388 faceNeighbors[n] += newFaceIndexStartIndex;
1393 for (
int i = 0 ; i < holeVertices.count(); ++i )
1395 int vertexHoleIndex = holeVertices.at( i );
1396 int meshFaceBoundaryIndex = associateMeshFacesToHole.at( i );
1401 int newFaceBoundaryIndexInMesh = circulator.
currentFaceIndex() + newFaceIndexStartIndex;
1403 int positionInNewFaces = vertexPositionInFace( vertexHoleIndex, newFace );
1405 if ( meshFaceBoundaryIndex != -1 )
1408 int positionInMeshFaceBoundary = vertexPositionInFace( *mMesh, vertexHoleIndex, meshFaceBoundaryIndex );
1409 positionInMeshFaceBoundary = ( positionInMeshFaceBoundary - 1 + meshFace.count() ) % meshFace.count();
1411 addChanges.
mNeighborhoodChanges.append( {meshFaceBoundaryIndex, positionInMeshFaceBoundary, -1, newFaceBoundaryIndexInMesh} );
1422 for (
const std::array<int, 4> &neighborChangeToAdd : std::as_const( addChanges.
mNeighborhoodChanges ) )
1424 bool merged =
false;
1427 if ( existingNeighborChange.at( 0 ) == neighborChangeToAdd.at( 0 ) &&
1428 existingNeighborChange.at( 1 ) == neighborChangeToAdd.at( 1 ) )
1431 Q_ASSERT( existingNeighborChange.at( 3 ) == neighborChangeToAdd.at( 2 ) );
1432 existingNeighborChange[3] = neighborChangeToAdd.at( 3 );
1439 for (
const std::array<int, 3> &verticesToFaceToAdd : std::as_const( addChanges.
mVerticesToFaceChanges ) )
1441 bool merged =
false;
1444 if ( existingVerticesToFace.at( 0 ) == verticesToFaceToAdd.at( 0 ) )
1447 Q_ASSERT( existingVerticesToFace.at( 2 ) == verticesToFaceToAdd.at( 1 ) );
1448 existingVerticesToFace[2] = verticesToFaceToAdd.at( 2 );
1455 qDeleteAll( holeToFill );
1459 qDeleteAll( holeToFill );
1474 QSet<int> facesIndex;
1476 for (
int vertexIndex : vertices )
1483 for (
int vertexIndex : vertices )
1485 int currentVertexToFace = mVertexToFace.at( vertexIndex );
1491 dereferenceAsFreeVertex( vertexIndex );
1493 mVertexToFace[vertexIndex] = -1;
1501 QList<int> boundariesToCheckClockwiseInNewFaces = topologicFaces.mBoundaries;
1502 QList<std::array<int, 2>> boundariesToCheckCounterClockwiseInNewFaces;
1503 QList<int> uniqueSharedVertexBoundary;
1511 while ( !boundariesToCheckClockwiseInNewFaces.isEmpty() )
1513 int boundary = boundariesToCheckClockwiseInNewFaces.takeLast();
1515 const QList<int> &linkedFaces = topologicFaces.mVerticesToFace.values( boundary );
1517 for (
int const linkedFace : linkedFaces )
1521 if ( mVertexToFace.at( boundary ) == -1 )
1527 if ( !newFacescirculator.
isValid() )
1541 if ( oppositeVertexCCWInMesh == oppositeVertexInNewFaces )
1547 int faceSize = newFaceOnBoundary.size();
1548 int posInNewFace = vertexPositionInFace( boundary, newFaceOnBoundary );
1549 int previousVertexIndex = ( posInNewFace + faceSize - 1 ) % faceSize;
1550 if ( newFaceOnBoundary.at( previousVertexIndex ) == oppositeVertexCCWInMesh )
1558 if ( oppositeVertexCWInMesh == oppositeVertexInNewFaces )
1562 boundariesToCheckCounterClockwiseInNewFaces.append( {boundary, linkedFace} );
1567 while ( !boundariesToCheckCounterClockwiseInNewFaces.isEmpty() )
1569 std::array<int, 2> boundaryLinkedface = boundariesToCheckCounterClockwiseInNewFaces.takeLast();
1570 int boundary = boundaryLinkedface.at( 0 );
1571 int linkedFace = boundaryLinkedface.at( 1 );
1586 if ( oppositeVertexCWInMesh == oppositeVertexInNewFaces )
1593 if ( oppositeVertexCCWInMesh == oppositeVertexInNewFaces )
1596 uniqueSharedVertexBoundary.append( boundary );
1599 if ( !uniqueSharedVertexBoundary.isEmpty() )
1603 QSet<int> boundaryVertices = qgis::listToSet( topologicFaces.mBoundaries );
1604 for (
const QgsMeshFace &newFace : std::as_const( topologicFaces.mFaces ) )
1606 for (
const int vertexIndex : newFace )
1608 if ( boundaryVertices.contains( vertexIndex ) )
1610 if ( mVertexToFace.at( vertexIndex ) != -1 )
1621 mFacesNeighborhood.clear();
1622 mVerticesToFace.clear();
1623 mBoundaries.clear();
1628 return mFacesNeighborhood;
1633 if ( mVerticesToFace.contains( vertexIndex ) )
1634 return mVerticesToFace.values( vertexIndex ).at( 0 );
1642 topologicMesh.mMesh =
mesh;
1643 topologicMesh.mVertexToFace = QVector<int>(
mesh->
vertexCount(), -1 );
1644 topologicMesh.mMaximumVerticesPerFace = maxVerticesPerFace;
1651 if ( maxVerticesPerFace != 0 &&
mesh->
face( i ).count() > maxVerticesPerFace )
1669 topologicMesh.mFacesNeighborhood = subMesh.mFacesNeighborhood;
1671 for (
int i = 0; i < topologicMesh.mMesh->
vertexCount(); ++i )
1673 if ( topologicMesh.mVertexToFace.at( i ) == -1 )
1674 topologicMesh.mFreeVertices.insert( i );
1678 return topologicMesh;
1683 return createTopologicalFaces( faces,
nullptr, error, uniqueSharedVertexAllowed );
1688 const QVector<QgsMeshFace> &faces,
1689 QVector<int> *globalVertexToFace,
1691 bool allowUniqueSharedVertex )
1693 int facesCount = faces.count();
1694 QVector<FaceNeighbors> faceTopologies;
1695 QMultiHash<int, int> verticesToFace;
1698 TopologicalFaces ret;
1702 QMap<int, QMap<int, int>> verticesToNeighbor;
1704 for (
int faceIndex = 0; faceIndex < facesCount; ++faceIndex )
1707 int faceSize = face.count();
1709 for (
int i = 0; i < faceSize; ++i )
1711 int v1 = face[i % faceSize];
1712 int v2 = face[( i + 1 ) % faceSize];
1713 if ( verticesToNeighbor[v2].contains( v1 ) )
1719 verticesToNeighbor[v2].insert( v1, faceIndex );
1723 faceTopologies = QVector<FaceNeighbors>( faces.count() );
1725 QSet<int> boundaryVertices;
1727 for (
int faceIndex = 0; faceIndex < facesCount; ++faceIndex )
1730 int faceSize = face.size();
1732 faceTopology.resize( faceSize );
1734 for (
int i = 0; i < faceSize; ++i )
1736 int v1 = face.at( i );
1737 int v2 = face.at( ( i + 1 ) % faceSize );
1739 if ( globalVertexToFace )
1741 if ( ( *globalVertexToFace )[v1] == -1 )
1742 ( *globalVertexToFace )[v1] = faceIndex ;
1746 if ( allowUniqueSharedVertex || !verticesToFace.contains( v1 ) )
1747 verticesToFace.insert( v1, faceIndex ) ;
1750 QMap<int, int> &edges = verticesToNeighbor[v1];
1751 if ( edges.contains( v2 ) )
1752 faceTopology[i] = edges.value( v2 );
1755 faceTopology[i] = -1;
1757 if ( !allowUniqueSharedVertex )
1759 if ( boundaryVertices.contains( v1 ) )
1765 boundaryVertices.insert( v1 );
1771 ret.mFacesNeighborhood = faceTopologies;
1772 ret.mBoundaries = boundaryVertices.values();
1773 ret.mVerticesToFace = verticesToFace;
1779 return mFacesNeighborhood.at( faceIndex );
1791 QSet<int> removedFaces = qgis::listToSet( facesIndexes );
1792 QSet<int> concernedFaces = concernedFacesBy( facesIndexes );
1794 for (
const int f : std::as_const( removedFaces ) )
1795 concernedFaces.remove( f );
1797 QVector<QgsMeshFace> remainingFaces;
1798 remainingFaces.reserve( concernedFaces.count() );
1799 for (
const int f : std::as_const( concernedFaces ) )
1800 remainingFaces.append( mMesh->
face( f ) );
1803 createTopologicalFaces( remainingFaces,
nullptr, error,
false );
1815 QSet<int> indexSet = qgis::listToSet( facesIndexesToRemove );
1816 QSet<int> threatedVertex;
1818 for (
int i = 0; i < facesIndexesToRemove.count(); ++i )
1820 const int faceIndex = facesIndexesToRemove.at( i );
1823 const FaceNeighbors &neighborhood = mFacesNeighborhood.at( faceIndex );
1825 for (
int j = 0; j < face.count(); ++j )
1828 int neighborIndex = neighborhood.at( j );
1829 if ( neighborIndex != -1 && !indexSet.contains( neighborIndex ) )
1831 int positionInNeighbor = mFacesNeighborhood.at( neighborIndex ).indexOf( faceIndex );
1836 int vertexIndex = face.at( j );
1837 if ( !threatedVertex.contains( vertexIndex ) && indexSet.contains( mVertexToFace.at( vertexIndex ) ) )
1839 int oldValue = mVertexToFace.at( vertexIndex );
1842 if ( neighborIndex != -1 && !indexSet.contains( neighborIndex ) )
1843 refValue = neighborIndex;
1847 aroundFaces.removeOne( faceIndex );
1848 if ( !aroundFaces.isEmpty() )
1850 while ( !aroundFaces.isEmpty() && refValue == -1 )
1852 if ( !indexSet.contains( aroundFaces.first() ) )
1853 refValue = aroundFaces.first();
1855 aroundFaces.removeFirst();
1860 threatedVertex.insert( vertexIndex );
1870 bool QgsTopologicalMesh::eitherSideFacesAndVertices(
int vertexIndex1,
1874 int &neighborVertex1InFace1,
1875 int &neighborVertex1InFace2,
1876 int &neighborVertex2inFace1,
1877 int &neighborVertex2inFace2 )
const
1919 int oppositeVertexFace1;
1920 int oppositeVertexFace2;
1921 int supposedOppositeVertexFace1;
1922 int supposedoppositeVertexFace2;
1924 bool result = eitherSideFacesAndVertices(
1929 oppositeVertexFace1,
1930 supposedoppositeVertexFace2,
1931 supposedOppositeVertexFace1,
1932 oppositeVertexFace2 );
1937 oppositeVertexFace1 < 0 ||
1938 oppositeVertexFace2 < 0 ||
1939 supposedOppositeVertexFace1 != oppositeVertexFace1 ||
1940 supposedoppositeVertexFace2 != oppositeVertexFace2 )
1947 if ( face1.count() != 3 || face2.count() != 3 )
1950 double crossProduct1 = crossProduct( vertexIndex1, oppositeVertexFace1, oppositeVertexFace2, *mMesh );
1951 double crossProduct2 = crossProduct( vertexIndex2, oppositeVertexFace1, oppositeVertexFace2, *mMesh );
1953 return crossProduct1 * crossProduct2 < 0;
1960 int oppositeVertexFace1;
1961 int oppositeVertexFace2;
1962 int supposedOppositeVertexFace1;
1963 int supposedoppositeVertexFace2;
1965 bool result = eitherSideFacesAndVertices(
1970 oppositeVertexFace1,
1971 supposedoppositeVertexFace2,
1972 supposedOppositeVertexFace1,
1973 oppositeVertexFace2 );
1978 oppositeVertexFace1 < 0 ||
1979 oppositeVertexFace2 < 0 ||
1980 supposedOppositeVertexFace1 != oppositeVertexFace1 ||
1981 supposedoppositeVertexFace2 != oppositeVertexFace2 )
1990 Q_ASSERT( face1.count() == 3 );
1991 Q_ASSERT( face2.count() == 3 );
1993 int pos1 = vertexPositionInFace( vertexIndex1, face1 );
1994 int pos2 = vertexPositionInFace( vertexIndex2, face2 );
1996 int neighborFace1 = mFacesNeighborhood.at( faceIndex1 ).at( pos1 );
1997 int posInNeighbor1 = vertexPositionInFace( *mMesh, oppositeVertexFace1, neighborFace1 );
1998 int neighborFace2 = mFacesNeighborhood.at( faceIndex1 ).at( ( pos1 + 1 ) % 3 );
1999 int posInNeighbor2 = vertexPositionInFace( *mMesh, vertexIndex2, neighborFace2 );
2000 int neighborFace3 = mFacesNeighborhood.at( faceIndex2 ).at( pos2 );
2001 int posInNeighbor3 = vertexPositionInFace( *mMesh, oppositeVertexFace2, neighborFace3 );
2002 int neighborFace4 = mFacesNeighborhood.at( faceIndex2 ).at( ( pos2 + 1 ) % 3 );
2003 int posInNeighbor4 = vertexPositionInFace( *mMesh, vertexIndex1, neighborFace4 );
2013 changes.
mFacesToAdd.append( {oppositeVertexFace1, oppositeVertexFace2, vertexIndex1} );
2014 changes.
mFacesToAdd.append( {oppositeVertexFace2, oppositeVertexFace1, vertexIndex2} );
2016 mFacesNeighborhood.at( faceIndex2 ).at( ( pos2 + 1 ) % 3 ),
2017 mFacesNeighborhood.at( faceIndex1 ).at( pos1 )} );
2019 mFacesNeighborhood.at( faceIndex1 ).at( ( pos1 + 1 ) % 3 ),
2020 mFacesNeighborhood.at( faceIndex2 ).at( pos2 )} );
2022 if ( neighborFace1 >= 0 )
2023 changes.
mNeighborhoodChanges.append( {neighborFace1, posInNeighbor1, faceIndex1, startIndex} );
2024 if ( neighborFace2 >= 0 )
2025 changes.
mNeighborhoodChanges.append( {neighborFace2, posInNeighbor2, faceIndex1, startIndex + 1} );
2026 if ( neighborFace3 >= 0 )
2027 changes.
mNeighborhoodChanges.append( {neighborFace3, posInNeighbor3, faceIndex2, startIndex + 1} );
2028 if ( neighborFace4 >= 0 )
2029 changes.
mNeighborhoodChanges.append( {neighborFace4, posInNeighbor4, faceIndex2, startIndex} );
2032 if ( mVertexToFace.at( vertexIndex1 ) == faceIndex1 || mVertexToFace.at( vertexIndex1 ) == faceIndex2 )
2034 if ( mVertexToFace.at( vertexIndex2 ) == faceIndex1 || mVertexToFace.at( vertexIndex2 ) == faceIndex2 )
2035 changes.
mVerticesToFaceChanges.append( {vertexIndex2, mVertexToFace.at( vertexIndex2 ), startIndex + 1} );
2037 if ( mVertexToFace.at( oppositeVertexFace1 ) == faceIndex1 )
2040 if ( mVertexToFace.at( oppositeVertexFace2 ) == faceIndex2 )
2052 int neighborVertex1InFace1;
2053 int neighborVertex1InFace2;
2054 int neighborVertex2inFace1;
2055 int neighborVertex2inFace2;
2057 bool result = eitherSideFacesAndVertices(
2062 neighborVertex1InFace1,
2063 neighborVertex1InFace2,
2064 neighborVertex2inFace1,
2065 neighborVertex2inFace2 );
2075 if ( face1.count() + face2.count() - 2 > mMaximumVerticesPerFace )
2085 double crossProduct1 = crossProduct( vertexIndex1, neighborVertex1InFace1, neighborVertex1InFace2, *mMesh );
2086 double crossProduct2 = crossProduct( vertexIndex2, neighborVertex2inFace1, neighborVertex2inFace2, *mMesh );
2088 return crossProduct1 * crossProduct2 < 0;
2095 int neighborVertex1InFace1;
2096 int neighborVertex1InFace2;
2097 int neighborVertex2inFace1;
2098 int neighborVertex2inFace2;
2100 bool result = eitherSideFacesAndVertices(
2105 neighborVertex1InFace1,
2106 neighborVertex1InFace2,
2107 neighborVertex2inFace1,
2108 neighborVertex2inFace2 );
2119 int faceSize1 = face1.count();
2120 int faceSize2 = face2.count();
2122 int pos1 = vertexPositionInFace( vertexIndex1, face1 );
2123 int pos2 = vertexPositionInFace( vertexIndex2, face2 );
2136 for (
int i = 0; i < faceSize1 - 1; ++i )
2138 int currentPos = ( pos1 + i ) % faceSize1;
2139 newface.append( face1.at( currentPos ) );
2141 int currentNeighbor = mFacesNeighborhood.at( faceIndex1 ).at( currentPos );
2142 newNeighborhood.append( currentNeighbor );
2144 if ( currentNeighbor != -1 )
2146 int currentPosInNeighbor = vertexPositionInFace( *mMesh, face1.at( ( currentPos + 1 ) % faceSize1 ), currentNeighbor );
2147 changes.
mNeighborhoodChanges.append( {currentNeighbor, currentPosInNeighbor, faceIndex1, startIndex} );
2150 for (
int i = 0; i < faceSize2 - 1; ++i )
2152 int currentPos = ( pos2 + i ) % faceSize2;
2153 newface.append( face2.at( currentPos ) );
2155 int currentNeighbor = mFacesNeighborhood.at( faceIndex2 ).at( currentPos );
2156 newNeighborhood.append( currentNeighbor );
2158 if ( currentNeighbor != -1 )
2160 int currentPosInNeighbor = vertexPositionInFace( *mMesh, face2.at( ( currentPos + 1 ) % faceSize2 ), currentNeighbor );
2161 changes.
mNeighborhoodChanges.append( {currentNeighbor, currentPosInNeighbor, faceIndex2, startIndex} );
2165 for (
int i = 0; i < faceSize1; ++i )
2166 if ( mVertexToFace.at( face1.at( i ) ) == faceIndex1 )
2169 for (
int i = 0; i < faceSize2; ++i )
2170 if ( mVertexToFace.at( face2.at( i ) ) == faceIndex2 )
2185 return face.count() == 4;
2192 int faceSize = face.count();
2194 Q_ASSERT( faceSize == 4 );
2196 double maxAngle = 0;
2197 int splitVertexPos = -1;
2198 for (
int i = 0; i < faceSize; ++i )
2200 QgsVector vect1( mMesh->
vertex( face.at( i ) ) - mMesh->
vertex( face.at( ( i + 1 ) % faceSize ) ) );
2201 QgsVector vect2( mMesh->
vertex( face.at( ( i + 2 ) % faceSize ) ) - mMesh->
vertex( face.at( ( i + 1 ) % faceSize ) ) );
2203 double angle = std::abs( vect1.
angle( vect2 ) );
2205 if (
angle > maxAngle )
2208 splitVertexPos = ( i + 1 ) % faceSize;
2214 const QgsMeshFace newFace1 = {face.at( splitVertexPos ),
2215 face.at( ( splitVertexPos + 1 ) % faceSize ),
2216 face.at( ( splitVertexPos + 2 ) % faceSize )
2219 const QgsMeshFace newFace2 = {face.at( splitVertexPos ),
2220 face.at( ( splitVertexPos + 2 ) % faceSize ),
2221 face.at( ( splitVertexPos + 3 ) % faceSize )
2224 QVector<int> neighborIndex( faceSize );
2225 QVector<int> posInNeighbor( faceSize );
2227 for (
int i = 0; i < faceSize; ++i )
2229 neighborIndex[i] = mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + i ) % faceSize );
2230 posInNeighbor[i] = vertexPositionInFace( *mMesh, face.at( ( splitVertexPos + i + 1 ) % faceSize ), neighborIndex[i] );
2242 mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 1 ) % faceSize ),
2245 mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 2 ) % faceSize ),
2246 mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 3 ) % faceSize )} );
2248 for (
int i = 0; i < faceSize; ++i )
2250 if ( neighborIndex[i] >= 0 )
2251 changes.
mNeighborhoodChanges.append( {neighborIndex[i], posInNeighbor[i], faceIndex, startIndex + int( i / 2 )} );
2253 int vertexIndex = face.at( ( splitVertexPos + i ) % faceSize );
2254 if ( mVertexToFace.at( vertexIndex ) == faceIndex )
2271 mVertexToFace.append( -1 );
2275 const FaceNeighbors includingFaceNeighborhood = mFacesNeighborhood.at( includingFaceIndex );
2276 int includingFaceSize = includingFace.count();
2278 for (
int i = 0; i < includingFaceSize; ++i )
2283 face[1] = includingFace.at( i );
2284 face[2] = includingFace.at( ( i + 1 ) % includingFaceSize );
2285 mMesh->
faces.append( face );
2288 int currentVertexIndex = includingFace.at( i );
2289 if ( mVertexToFace.at( currentVertexIndex ) == includingFaceIndex )
2291 int newFaceIndex = mMesh->
faceCount() - 1;
2292 mVertexToFace[currentVertexIndex] = newFaceIndex;
2296 int includingFaceNeighbor = includingFaceNeighborhood.at( i );
2300 includingFaceNeighbor,
2303 mFacesNeighborhood.append( neighbors );
2306 if ( includingFaceNeighbor != -1 )
2308 int indexInNeighbor = vertexPositionInFace( *mMesh, includingFace.at( ( i + 1 ) % includingFaceSize ), includingFaceNeighbor );
2309 int oldValue = mFacesNeighborhood[includingFaceNeighbor][indexInNeighbor];
2321 mVertexToFace[mVertexToFace.count() - 1] = mMesh->
faceCount() - 1;
2336 int newVertexPositionInFace1 = position + 1;
2338 auto triangulate = [
this, &changes](
int removedFaceIndex,
const QgsMeshVertex & newVertex,
int newVertexPosition, QVector<int> &edgeFacesIndexes )->
bool
2344 const int addedVertexIndex = mMesh->
vertexCount();
2347 int localStartIndex = changes.
mFacesToAdd.count();
2349 QVector<int> newBoundary = initialFace;
2350 newBoundary.insert( newVertexPosition, addedVertexIndex );
2354 QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
2355 std::vector<p2t::Point *> faceToFill( newBoundary.count() );
2356 for (
int i = 0; i < newBoundary.count(); ++i )
2360 if ( newBoundary.at( i ) == addedVertexIndex )
2363 vert = mMesh->
vertex( newBoundary.at( i ) );
2365 faceToFill[i] =
new p2t::Point( vert.
x(), vert.
y() );
2366 mapPoly2TriPointToVertex.insert( faceToFill[i], newBoundary.at( i ) );
2369 std::unique_ptr<p2t::CDT> cdt(
new p2t::CDT( faceToFill ) );
2371 std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
2372 QVector<QgsMeshFace> newFaces( triangles.size() );
2373 for (
size_t i = 0; i < triangles.size(); ++i )
2377 for (
int j = 0; j < 3; j++ )
2379 int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
2380 if ( vertInd == -1 )
2381 throw std::exception();
2389 throw std::exception();
2395 const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
2396 for (
const int vtc : verticesToFaceToChange )
2397 if ( vtc != addedVertexIndex && mVertexToFace.at( vtc ) == removedFaceIndex )
2402 topologicalFaces.
vertexToFace( vtc ) + faceStartGlobalIndex
2406 for (
int i = 0; i < topologicalFaces.mFaces.count(); ++i )
2409 for (
int n = 0; n < faceNeighbors.count(); ++n )
2411 if ( faceNeighbors.at( n ) != -1 )
2412 faceNeighbors[n] += faceStartGlobalIndex;
2416 edgeFacesIndexes.resize( 2 );
2418 for (
int i = 0 ; i < newBoundary.count(); ++i )
2420 int vertexIndex = newBoundary.at( i );
2423 int newFaceBoundaryLocalIndex = localStartIndex + circulator.
currentFaceIndex();
2425 int newFaceBoundaryIndexInMesh = faceStartGlobalIndex;
2427 int meshFaceBoundaryIndex;
2428 if ( i == newVertexPosition )
2430 meshFaceBoundaryIndex = -1;
2431 edgeFacesIndexes[0] = newFaceBoundaryLocalIndex;
2433 else if ( i == ( newVertexPosition + newBoundary.count() - 1 ) % newBoundary.count() )
2435 meshFaceBoundaryIndex = -1;
2436 edgeFacesIndexes[1] = newFaceBoundaryLocalIndex;
2439 meshFaceBoundaryIndex = mFacesNeighborhood.at( removedFaceIndex ).at( vertexPositionInFace( vertexIndex, initialFace ) );
2442 int positionInNewFaces = vertexPositionInFace( vertexIndex, newFace );
2444 if ( meshFaceBoundaryIndex != -1 )
2447 int positionInMeshFaceBoundary = vertexPositionInFace( *mMesh, vertexIndex, meshFaceBoundaryIndex );
2448 positionInMeshFaceBoundary = ( positionInMeshFaceBoundary - 1 + meshFace.count() ) % meshFace.count();
2451 positionInMeshFaceBoundary,
2453 newFaceBoundaryIndexInMesh +
2460 qDeleteAll( faceToFill );
2470 QVector<int> edgeFacesIndexes;
2471 if ( !triangulate( faceIndex, vertexToInsert, newVertexPositionInFace1, edgeFacesIndexes ) )
2479 int face2Index = mFacesNeighborhood.at( faceIndex ).at( position );
2480 if ( face2Index != -1 )
2483 int vertexPositionInFace2 = vertexPositionInFace( face1.at( position ), face2 );
2484 QVector<int> edgeFacesIndexesFace2;
2485 if ( !triangulate( face2Index, vertexToInsert, vertexPositionInFace2, edgeFacesIndexesFace2 ) )
2490 int pos1InFaceSide1 = vertexPositionInFace( addedVertexIndex, firstFaceSide1 );
2493 int pos2InFaceSide1 = vertexPositionInFace( addedVertexIndex, secondFaceSide1 );
2494 pos2InFaceSide1 = ( pos2InFaceSide1 + secondFaceSide1.size() - 1 ) % secondFaceSide1.size();
2497 int pos1InFaceSide2 = vertexPositionInFace( addedVertexIndex, firstFaceSide2 );
2500 int pos2InFaceSide2 = vertexPositionInFace( addedVertexIndex, secondFaceSide2 );
2501 pos2InFaceSide2 = ( pos2InFaceSide2 + secondFaceSide1.size() - 1 ) % secondFaceSide1.size();
2515 Q_ASSERT( verticesIndexes.count() == newValues.count() );
2518 changes.
mNewZValues.reserve( verticesIndexes.count() );
2519 changes.
mOldZValues.reserve( verticesIndexes.count() );
2520 for (
int i = 0; i < verticesIndexes.count(); ++i )
2534 Q_ASSERT( verticesIndexes.count() == newValues.count() );
2537 changes.
mNewXYValues.reserve( verticesIndexes.count() );
2538 changes.
mOldXYValues.reserve( verticesIndexes.count() );
2539 QSet<int> concernedFace;
2540 for (
int i = 0; i < verticesIndexes.count(); ++i )
2545 concernedFace.unite( qgis::listToSet(
facesAroundVertex( verticesIndexes.at( i ) ) ) );