65 static int vertexPositionInFace(
int vertexIndex,
const QgsMeshFace &face )
67 return face.indexOf( vertexIndex );
70 static int vertexPositionInFace(
const QgsMesh &mesh,
int vertexIndex,
int faceIndex )
72 if ( faceIndex < 0 || faceIndex >= mesh.
faceCount() )
75 return vertexPositionInFace( vertexIndex, mesh.
face( faceIndex ) );
82 QSet<int> facesToRefine = qgis::listToSet(
mInputFaces );
83 QHash<int, FaceRefinement> facesRefinement;
84 QHash<int, BorderFace> borderFaces;
86 createNewVerticesAndRefinedFaces( meshEditor, facesToRefine, facesRefinement );
87 if ( !createNewBorderFaces( meshEditor, facesToRefine, facesRefinement, borderFaces ) )
112 void QgsMeshEditRefineFaces::createNewVerticesAndRefinedFaces(
QgsMeshEditor *meshEditor,
113 QSet<int> &facesToRefine,
114 QHash<int, FaceRefinement> &facesRefinement )
120 int startingGlobalFaceIndex = mesh.
faceCount();
122 for (
const int faceIndex : std::as_const(
mInputFaces ) )
124 FaceRefinement refinement;
127 int faceSize = face.size();
129 QVector<int> addedVerticesIndex( faceSize, -1 );
131 if ( faceSize == 3 || faceSize == 4 )
133 refinement.newVerticesLocalIndex.reserve( faceSize );
134 refinement.refinedFaceNeighbor.reserve( faceSize );
135 refinement.borderFaceNeighbor.reserve( faceSize );
138 double zValueSum = 0;
140 for (
int positionInFace = 0; positionInFace < faceSize; ++positionInFace )
142 refinement.refinedFaceNeighbor.append(
false );
143 refinement.borderFaceNeighbor.append(
false );
145 int neighborFaceIndex = neighbors.at( positionInFace );
146 bool needCreateVertex =
true;
147 if ( neighborFaceIndex != -1 && facesToRefine.contains( neighborFaceIndex ) )
149 int neighborFaceSize = mesh.
face( neighborFaceIndex ).size();
150 int positionVertexInNeighbor = vertexPositionInFace( mesh, face.at( positionInFace ), neighborFaceIndex );
151 positionVertexInNeighbor = ( positionVertexInNeighbor + neighborFaceSize - 1 ) % neighborFaceSize;
152 refinement.refinedFaceNeighbor[positionInFace] =
true;
153 QHash<int, FaceRefinement>::iterator it = facesRefinement.find( neighborFaceIndex );
154 if ( it != facesRefinement.end() )
156 FaceRefinement &neighborRefinement = it.value();
157 int existingVertexLocalIndex = neighborRefinement.newVerticesLocalIndex.at( positionVertexInNeighbor );
158 refinement.newVerticesLocalIndex.append( existingVertexLocalIndex );
159 needCreateVertex =
false;
164 if ( needCreateVertex )
167 const QgsMeshVertex &vertex2 = mesh.
vertex( face.at( ( positionInFace + 1 ) % faceSize ) );
169 refinement.newVerticesLocalIndex.append(
mVerticesToAdd.count() );
173 ( vertex1.
y() + vertex2.
y() ) / 2,
174 ( vertex1.
z() + vertex2.
z() ) / 2 ) );
182 int faceStartIndex = startingGlobalFaceIndex +
mFacesToAdd.count();
186 for (
int i = 0; i < faceSize; ++i )
189 refinement.newVerticesLocalIndex.at( i ) + startingVertexIndex,
190 refinement.newVerticesLocalIndex.at( ( i + faceSize - 1 ) % faceSize ) + startingVertexIndex} );
191 refinement.newFacesChangesIndex.append(
mFacesToAdd.count() );
196 QgsMeshFace newFace( {refinement.newVerticesLocalIndex.at( 0 ) + startingVertexIndex,
197 refinement.newVerticesLocalIndex.at( 1 ) + startingVertexIndex,
198 refinement.newVerticesLocalIndex.at( ( 2 ) % faceSize ) + startingVertexIndex} );
199 refinement.newFacesChangesIndex.append(
mFacesToAdd.count() );
206 int centerVertexIndex =
mVerticesToAdd.count() + startingVertexIndex;
211 for (
int i = 0; i < faceSize; ++i )
214 refinement.newVerticesLocalIndex.at( i ) + startingVertexIndex,
216 refinement.newVerticesLocalIndex.at( ( i + faceSize - 1 ) % faceSize ) + startingVertexIndex} );
217 refinement.newFacesChangesIndex.append(
mFacesToAdd.count() );
225 refinement.newCenterVertexIndex = -1;
227 facesRefinement.insert( faceIndex, refinement );
232 facesToRefine.remove( faceIndex );
236 for (
int positionInFace = 0; positionInFace < faceSize; ++positionInFace )
238 if ( addedVerticesIndex.at( positionInFace ) != -1 )
241 refinement.newFacesChangesIndex.at( positionInFace ) + startingGlobalFaceIndex;
244 int vertexIndex = face.at( positionInFace );
246 mVerticesToFaceChanges.append( {vertexIndex, faceIndex, refinement.newFacesChangesIndex.at( positionInFace ) + startingGlobalFaceIndex} );
251 for ( QHash<int, FaceRefinement>::iterator it = facesRefinement.begin(); it != facesRefinement.end(); ++it )
253 int faceIndex = it.key();
254 FaceRefinement &faceRefinement = it.value();
256 int faceSize = face.size();
260 for (
int positionInFace = 0; positionInFace < faceSize; ++positionInFace )
262 if ( faceRefinement.refinedFaceNeighbor.at( positionInFace ) )
264 int neighborIndex = neighbors.at( positionInFace );
265 int firstVertexIndex = face.at( positionInFace );
266 int secondVertexIndex = faceRefinement.newVerticesLocalIndex.at( positionInFace ) + startingVertexIndex;
268 const FaceRefinement &otherRefinement = facesRefinement.value( neighborIndex );
270 int otherFaceSize = otherFace.size();
271 int otherPositionInface = ( vertexPositionInFace( firstVertexIndex, otherFace ) + otherFaceSize - 1 ) % otherFaceSize;
273 int newFace1ChangesIndex = faceRefinement.newFacesChangesIndex.at( ( positionInFace ) );
274 const QgsMeshFace &newFace1 = mFacesToAdd.at( newFace1ChangesIndex );
275 int positionInNewface1Index = vertexPositionInFace( firstVertexIndex, newFace1 );
277 int newFace2ChangesIndex = faceRefinement.newFacesChangesIndex.at( ( positionInFace + 1 ) % faceSize );
278 const QgsMeshFace &newFace2 = mFacesToAdd.at( newFace2ChangesIndex );
279 int positionInNewface2Index = vertexPositionInFace( secondVertexIndex, newFace2 );
281 int otherNewFace1ChangesIndex = otherRefinement.newFacesChangesIndex.at( ( otherPositionInface ) % otherFaceSize );
282 int otherNewFace2ChangesIndex = otherRefinement.newFacesChangesIndex.at( ( otherPositionInface + 1 ) % otherFaceSize );
284 mFacesNeighborhoodToAdd[newFace1ChangesIndex][positionInNewface1Index] = otherNewFace2ChangesIndex + startingGlobalFaceIndex;
285 mFacesNeighborhoodToAdd[newFace2ChangesIndex][positionInNewface2Index] = otherNewFace1ChangesIndex + startingGlobalFaceIndex;
291 bool QgsMeshEditRefineFaces::createNewBorderFaces(
QgsMeshEditor *meshEditor,
292 const QSet<int> &facesToRefine,
293 QHash<int, FaceRefinement> &facesRefinement,
294 QHash<int, BorderFace> &borderFaces )
300 int startingFaceChangesGlobalIndex = mesh.
faceCount();
303 for (
int faceIndexToRefine : facesToRefine )
306 int faceToRefineSize = faceToRefine.size();
308 const QVector<int> &neighbors = topology.
neighborsOfFace( faceIndexToRefine );
310 QHash<int, FaceRefinement>::iterator itFace = facesRefinement.find( faceIndexToRefine );
312 if ( itFace == facesRefinement.end() )
315 FaceRefinement &refinement = itFace.value();
317 for (
int posInFaceToRefine = 0; posInFaceToRefine < faceToRefineSize; ++posInFaceToRefine )
319 int neighborFaceIndex = neighbors.at( posInFaceToRefine );
320 if ( neighborFaceIndex != -1 && !facesToRefine.contains( neighborFaceIndex ) )
323 int neighborFaceSize = neighborFace.size();
324 int positionInNeighbor = vertexPositionInFace( mesh, faceToRefine.at( posInFaceToRefine ), neighborFaceIndex );
325 positionInNeighbor = ( positionInNeighbor + neighborFaceSize - 1 ) % neighborFaceSize;
327 QHash<int, BorderFace>::iterator it = borderFaces.find( neighborFaceIndex );
328 if ( it == borderFaces.end() )
330 BorderFace borderFace;
331 for (
int i = 0; i < neighborFaceSize; ++i )
333 borderFace.unchangeFacesNeighbor.append(
false );
334 borderFace.borderFacesNeighbor.append(
false );
335 if ( i == positionInNeighbor )
337 borderFace.refinedFacesNeighbor.append(
true );
338 borderFace.newVerticesLocalIndex.append( refinement.newVerticesLocalIndex.at( posInFaceToRefine ) );
342 borderFace.refinedFacesNeighbor.append(
false );
343 borderFace.newVerticesLocalIndex.append( -1 );
346 borderFaces.insert( neighborFaceIndex, borderFace );
350 BorderFace &borderFace = it.value();
351 for (
int i = 0; i < neighborFaceSize; ++i )
353 if ( i == positionInNeighbor )
355 borderFace.unchangeFacesNeighbor[i] =
false;
356 borderFace.borderFacesNeighbor[i] =
false;
357 borderFace.refinedFacesNeighbor[i] =
true;
358 borderFace.newVerticesLocalIndex[i] = refinement.newVerticesLocalIndex.at( posInFaceToRefine );
367 for ( QHash<int, BorderFace>::iterator it = borderFaces.begin(); it != borderFaces.end(); ++it )
369 int faceIndex = it.key();
370 BorderFace &borderFace = it.value();
373 int faceSize = face.size();
376 for (
int posInFace = 0; posInFace < faceSize; ++posInFace )
378 int neighborIndex = neighbors.at( posInFace );
380 if ( neighborIndex != -1 )
383 int neighborFaceSize = neighborFace.size();
384 int posInNeighbor = vertexPositionInFace( mesh, face.at( posInFace ), neighborIndex );
385 posInNeighbor = ( posInNeighbor - 1 + neighborFaceSize ) % neighborFaceSize;
387 QHash<int, FaceRefinement>::iterator itRefinement = facesRefinement.find( neighborIndex );
388 if ( itRefinement != facesRefinement.end() )
390 FaceRefinement &neighborRefinement = itRefinement.value();
391 neighborRefinement.borderFaceNeighbor[posInNeighbor] =
true;
392 borderFace.refinedFacesNeighbor[posInFace] =
true;
396 QHash<int, BorderFace>::iterator itNeighborBorder = borderFaces.find( neighborIndex );
397 if ( itNeighborBorder == borderFaces.end() )
398 borderFace.unchangeFacesNeighbor[posInFace] =
true;
401 BorderFace &neighborBorderFace = itNeighborBorder.value();
402 neighborBorderFace.borderFacesNeighbor[posInNeighbor] =
true;
403 borderFace.borderFacesNeighbor[posInFace] =
true;
408 borderFace.unchangeFacesNeighbor[posInFace] =
true;
414 for ( QHash<int, BorderFace>::iterator it = borderFaces.begin(); it != borderFaces.end(); ++it )
416 int faceIndex = it.key();
417 BorderFace &borderFace = it.value();
420 int faceSize = face.size();
422 QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
423 std::vector<p2t::Point *> points;
424 for (
int i = 0; i < faceSize; ++i )
427 points.push_back(
new p2t::Point( vert.
x(), vert.
y() ) );
428 mapPoly2TriPointToVertex.insert( points.back(), face.at( i ) );
429 if ( borderFace.refinedFacesNeighbor.at( i ) )
431 int localVertexIndex = borderFace.newVerticesLocalIndex.at( i );
432 const QgsMeshVertex &newVert = mVerticesToAdd.at( localVertexIndex );
433 points.push_back(
new p2t::Point( newVert.
x(), newVert.
y() ) );
434 mapPoly2TriPointToVertex.insert( points.back(), localVertexIndex + startingVertexIndex );
440 std::unique_ptr<p2t::CDT> cdt(
new p2t::CDT( points ) );
442 std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
443 QVector<QgsMeshFace> faces( triangles.size() );
444 for (
size_t i = 0; i < triangles.size(); ++i )
447 triangle.resize( 3 );
448 QVector<QgsMeshVertex> vertices( 3 );
449 for (
int j = 0; j < 3; j++ )
451 int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
453 throw std::exception();;
454 triangle[j] = vertInd;
455 if ( vertInd >= startingVertexIndex )
456 vertices[j] = mVerticesToAdd.at( vertInd - startingVertexIndex );
458 vertices[j] = mesh.
vertex( vertInd );
463 int startingFaceIndex = mesh.
faceCount() + mFacesToAdd.count();
467 QVector<QgsTopologicalMesh::FaceNeighbors> neighborhood = topologicalFaces.
facesNeighborhood();
470 for (
int i = 0; i < neighborhood.count(); ++i )
473 for (
int j = 0; j < neighbors.count(); ++j )
475 if ( neighbors[j] != -1 )
476 neighbors[j] = neighbors[j] + startingFaceIndex;
483 for (
int positionInFace = 0; positionInFace < faceSize; ++positionInFace )
485 if ( borderFace.refinedFacesNeighbor.at( positionInFace ) )
488 QVector<int> vertexIndexes( 2 );
489 QVector<int> localFaceIndex( 2 );
490 vertexIndexes[0] = face.at( positionInFace );
491 vertexIndexes[1] = borderFace.newVerticesLocalIndex.at( positionInFace ) + startingVertexIndex;
493 int refinedFaceIndex = neighborOfFace.at( positionInFace );
494 const FaceRefinement &faceRefinement = facesRefinement.value( refinedFaceIndex );
496 int refinedFaceSize = refinedFace.size();
497 int positionInRefinedFace = ( vertexPositionInFace( vertexIndexes[0], refinedFace ) + refinedFaceSize - 1 ) % refinedFaceSize;
499 for (
int i = 0; i < 2; ++i )
502 circulator.goBoundaryClockwise();
503 localFaceIndex[i] = circulator.currentFaceIndex();
507 const QgsMeshFace newFace = faces.at( localFaceIndex.at( i ) );
508 int positionInNewFace = vertexPositionInFace( vertexIndexes.at( i ), newFace );
509 int newFaceRefinedIndexInChanges = faceRefinement.newFacesChangesIndex.at( ( positionInRefinedFace + ( 1 - i ) ) % refinedFaceSize ) ;
510 neighborsNewFace[positionInNewFace] = newFaceRefinedIndexInChanges + startingFaceChangesGlobalIndex;
513 const QgsMeshFace &newRefinedFace = mFacesToAdd.at( newFaceRefinedIndexInChanges );
514 int newRefinedFaceSize = newRefinedFace.size();
515 int positionInNewRefinedChange = ( vertexPositionInFace( vertexIndexes.at( i ), newRefinedFace ) + newRefinedFaceSize - 1 ) % newRefinedFaceSize;
516 neighborsRefinedFace[positionInNewRefinedChange] = localFaceIndex.at( i ) + startingFaceIndex;
519 borderFace.edgeFace.append( localFaceIndex.at( 0 ) + startingFaceIndex );
522 if ( borderFace.borderFacesNeighbor.at( positionInFace ) )
524 int vertexIndex = face.at( positionInFace );
526 circulator.goBoundaryClockwise();
527 int localFaceIndex = circulator.currentFaceIndex();
530 borderFace.edgeFace.append( localFaceIndex + startingFaceIndex );
533 if ( borderFace.unchangeFacesNeighbor.at( positionInFace ) )
535 int vertexIndex = face.at( positionInFace );
537 circulator.goBoundaryClockwise();
538 int localFaceIndex = circulator.currentFaceIndex();
540 const QgsMeshFace &newFace = faces.at( localFaceIndex );
541 int positionInNewface = vertexPositionInFace( vertexIndex, newFace );
543 int unchangedFaceIndex = neighborOfFace.at( positionInFace );
544 neighborsNewFace[positionInNewface] = unchangedFaceIndex;
546 if ( unchangedFaceIndex != -1 )
549 int unchangedFaceSize = unchangedFace.size();
550 int positionInUnchangedFace = ( vertexPositionInFace( vertexIndex, unchangedFace ) + unchangedFaceSize - 1 ) % unchangedFaceSize;
551 mNeighborhoodChanges.append( {unchangedFaceIndex, positionInUnchangedFace, faceIndex, localFaceIndex + startingFaceIndex} );
554 borderFace.edgeFace.append( localFaceIndex + startingFaceIndex );
558 mFacesToAdd.append( faces );
559 mFacesNeighborhoodToAdd.append( neighborhood );
561 for ( p2t::Point *pt : points )
572 for ( QHash<int, BorderFace>::iterator it = borderFaces.begin(); it != borderFaces.end(); ++it )
574 int faceIndex = it.key();
575 BorderFace &borderFace = it.value();
577 int faceSize = face.size();
581 for (
int positionInFace = 0; positionInFace < faceSize; ++positionInFace )
583 if ( borderFace.borderFacesNeighbor.at( positionInFace ) )
585 int otherIndex = neighbors.at( positionInFace );
587 int otherFaceSize = otherFace.size();
588 int otherPositionInface = ( vertexPositionInFace( face.at( positionInFace ), otherFace ) + otherFaceSize - 1 ) % otherFaceSize;
589 const BorderFace &otherBorderFace = borderFaces.value( otherIndex );
590 int otherNewFaceIndex = otherBorderFace.edgeFace.at( otherPositionInface );
592 int newFaceChangesIndex = borderFace.edgeFace.at( positionInFace ) - startingFaceChangesGlobalIndex;
593 const QgsMeshFace &newFace = mFacesToAdd.at( newFaceChangesIndex );
594 int newFacePositionInFace = vertexPositionInFace( face.at( positionInFace ), newFace );
596 mFacesNeighborhoodToAdd[newFaceChangesIndex][newFacePositionInFace] = otherNewFaceIndex;
600 for (
int positionInFace = 0; positionInFace < faceSize; ++positionInFace )
602 int vertexIndex = face.at( positionInFace );
604 mVerticesToFaceChanges.append( {vertexIndex, faceIndex, borderFace.edgeFace.at( positionInFace ) } );
614 return QObject::tr(
"Refine %n face(s)",
nullptr,
mInputFaces.count() );
626 QSet<int> concernedFaces;
627 mChangingVertexMap = QHash<int, int>();
632 context.
lastScope()->
setVariable( QStringLiteral(
"_mesh_layer" ), QVariant::fromValue( layer ) );
634 QVector<QgsMeshVertex> newVertices;
640 bool calcX = !mExpressionX.isEmpty();
641 bool calcY = !mExpressionY.isEmpty();
642 bool calcZ = !mExpressionZ.isEmpty();
647 expressionX.
prepare( &context );
654 expressionY.
prepare( &context );
657 if ( calcX || calcY )
667 expressionZ.
prepare( &context );
677 mChangingVertexMap[vertexIndex] = i;
678 const QVariant xvar = expressionX.
evaluate( &context );
679 const QVariant yvar = expressionY.
evaluate( &context );
680 const QVariant zvar = expressionZ.
evaluate( &context );
684 if ( calcX || calcY )
690 concernedFaces.unite( qgis::listToSet( facesAround ) );
696 if ( xvar.isValid() )
698 double x = xvar.toDouble( &ok );
714 if ( yvar.isValid() )
716 double y = yvar.toDouble( &ok );
730 double z = std::numeric_limits<double>::quiet_NaN();
731 if ( zvar.isValid() )
733 z = zvar.toDouble( &ok );
735 z = std::numeric_limits<double>::quiet_NaN();
743 auto transformFunction = [
this, layer ](
int vi )->
const QgsMeshVertex
754 return QObject::tr(
"Transform %n vertices by expression",
nullptr,
mInputVertices.count() );
759 mExpressionX = expressionX;
760 mExpressionY = expressionY;
761 mExpressionZ = expressionZ;
763 mChangingVertexMap.clear();
775 int pos = mChangingVertexMap.value( vertexIndex, -1 );
void setVariable(const QString &name, const QVariant &value, bool isStatic=false)
Convenience method for setting a variable in the context scope by name name and value.
static QgsExpressionContextScope * meshExpressionScope(QgsMesh::ElementType elementType)
Creates a new scope which contains functions relating to mesh layer element elementType.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
QgsExpressionContextScope * lastScope()
Returns the last scope added to the context.
void appendScope(QgsExpressionContextScope *scope)
Appends a scope to the end of the context.
Class for parsing and evaluation of expressions (formerly called "search strings").
bool prepare(const QgsExpressionContext *context)
Gets the expression ready for evaluation - find out column indexes.
QVariant evaluate()
Evaluate the feature and return the result.
QString message() const
Returns a message that can be provided by the advanced editing when applying is done.
void setInputVertices(const QList< int > verticesIndexes)
Sets the input vertices indexes that will be used for the editing.
virtual ~QgsMeshAdvancedEditing()
Destructor.
void clear()
Removes all data provided to the editing or created by the editing.
QList< int > mInputVertices
virtual bool isFinished() const
Returns whether the advanced edit is finished, if not, this edit has to be applied again with QgsMesh...
QgsMeshAdvancedEditing()
Constructor.
virtual QString text() const
Returns a short text string describing what this advanced edit does. Default implementation return a ...
void setInputFaces(const QList< int > faceIndexes)
Sets the input faces indexes that will be used for the editing.
QgsMeshEditRefineFaces()
Constructor.
QString text() const override
Returns a short text string describing what this advanced edit does. Default implementation return a ...
Class that represents an error during mesh editing.
Class that makes edit operation on a mesh.
bool canBeTransformed(const QList< int > &facesToCheck, const std::function< const QgsMeshVertex(int)> &transformFunction) const
Returns true if faces with index in transformedFaces can be transformed without obtaining topologic o...
QgsTopologicalMesh & topologicalMesh()
Returns a reference to the topological mesh.
Represents a mesh layer supporting display of data on structured or unstructured meshes.
QgsMeshEditor * meshEditor()
Returns a pointer to the mesh editor own by the mesh layer.
QgsMesh * nativeMesh()
Returns native mesh (nullptr before rendering or calling to updateMesh)
Convenient class that turn around a vertex and provide information about faces and vertices.
A class to represent a 2D point.
Point geometry type, with support for z-dimension and m-values.
Class that contains topological differences between two states of a topological mesh,...
QList< int > mChangeCoordinateVerticesIndexes
void clearChanges()
Clears all changes.
QVector< FaceNeighbors > mFacesNeighborhoodToRemove
QList< QgsPointXY > mNewXYValues
QList< int > mNativeFacesIndexesGeometryChanged
QVector< QgsMeshFace > mFacesToAdd
QVector< FaceNeighbors > mFacesNeighborhoodToAdd
QList< std::array< int, 3 > > mVerticesToFaceChanges
QList< QgsPointXY > mOldXYValues
QList< double > mNewZValues
QVector< QgsMeshVertex > mVerticesToAdd
int mAddedFacesFirstIndex
QVector< int > mVertexToFaceToAdd
QList< int > mFaceIndexesToRemove
QVector< QgsMeshFace > mFacesToRemove
QList< double > mOldZValues
Class that contains independent faces an topological information about this faces.
QVector< FaceNeighbors > facesNeighborhood() const
Returns the face neighborhood of the faces, indexing is local.
Class that wraps a QgsMesh to ensure the consistency of the mesh during editing and help to access to...
void applyChanges(const Changes &changes)
Applies the changes.
int firstFaceLinked(int vertexIndex) const
Returns the index of the first face linked, returns -1 if it is a free vertex or out of range index.
QVector< int > neighborsOfFace(int faceIndex) const
Returns the indexes of neighbor faces of the face with index faceIndex.
QVector< int > FaceNeighbors
QList< int > facesAroundVertex(int vertexIndex) const
Returns the indexes of faces that are around the vertex with index vertexIndex.
QgsMesh * mesh() const
Returns a pointer to the wrapped mesh.
static TopologicalFaces createNewTopologicalFaces(const QVector< QgsMeshFace > &faces, bool uniqueSharedVertexAllowed, QgsMeshEditingError &error)
Creates new topological faces that are not yet included in the mesh.
void setCounterClockwise(QgsMeshFace &triangle, const QgsMeshVertex &v0, const QgsMeshVertex &v1, const QgsMeshVertex &v2)
Checks if the triangle is counter clockwise, if not sets it counter clockwise.
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
QVector< int > QgsMeshFace
List of vertex indexes.
QgsPoint QgsMeshVertex
xyz coords of vertex
Mesh - vertices, edges and faces.
int vertexCount() const
Returns number of vertices.
QVector< QgsMeshVertex > vertices
QgsMeshFace face(int index) const
Returns a face at the index.
int faceCount() const
Returns number of faces.
QgsMeshVertex vertex(int index) const
Returns a vertex at the index.