19#include "moc_qgsmesheditor.cpp" 
   35  : QObject( meshLayer )
 
   36  , mMesh( meshLayer ? meshLayer->nativeMesh() : nullptr )
 
   37  , mTriangularMesh( meshLayer ? meshLayer->triangularMeshByLodIndex( 0 ) : nullptr )
 
   38  , mUndoStack( meshLayer ? meshLayer->undoStack() : nullptr )
 
 
   50  , mTriangularMesh( triangularMesh )
 
   52  mUndoStack = 
new QUndoStack( 
this );
 
 
   58  std::unique_ptr<QgsMeshDatasetGroup> zValueDatasetGroup = std::make_unique<QgsMeshVerticesElevationDatasetGroup>( tr( 
"vertices Z value" ), mMesh );
 
   64  mZValueDatasetGroup = zValueDatasetGroup.get();
 
   66  return zValueDatasetGroup.release();
 
 
   81    for ( 
int vi : freeVertices )
 
 
  109    mTriangularMesh->
update( mMesh );
 
 
  136      auto faceIt = mMesh->
faces.begin();
 
  137      while ( faceIt != mMesh->
faces.end() )
 
  140          faceIt = mMesh->
faces.erase( faceIt );
 
 
  166  Q_ASSERT( vertexIndexes.count() == vertices.count() );
 
  168  QVector<QgsPoint> ring;
 
  169  for ( 
int i = 0; i < vertices.size(); ++i )
 
  171    const QgsPoint &vertex = vertices[i];
 
  172    ring.append( vertex );
 
  174  auto polygon = std::make_unique< QgsPolygon >();
 
  176  const QgsGeometry newFaceGeom( polygon.release() );
 
  178  geomEngine->prepareGeometry();
 
  180  const QgsRectangle boundingBox = newFaceGeom.boundingBox();
 
  181  int newFaceSize = vertexIndexes.count();
 
  183  if ( !concernedFaceIndex.isEmpty() )
 
  187    for ( 
const int faceIndex : concernedFaceIndex )
 
  190      int existingFaceSize = existingFace.count();
 
  191      bool shareVertex = 
false;
 
  192      for ( 
int i = 0; i < existingFaceSize; ++i )
 
  194        if ( vertexIndexes.contains( existingFace.at( i ) ) )
 
  203        for ( 
int i = 0; i < existingFaceSize; ++i )
 
  205          int index1 = existingFace.at( i );
 
  206          int index2 = existingFace.at( ( i + 1 ) % existingFaceSize );
 
  211          if ( ! vertexIndexes.contains( index1 )  && !vertexIndexes.contains( index2 ) )
 
  214            if ( geomEngine->intersects( edgeGeom.
constGet() ) )
 
  219            for ( 
int vi = 0; vi < vertexIndexes.count(); ++vi )
 
  221              int vertInNewFace1 = vertexIndexes.at( vi );
 
  222              int vertInNewFace2 = vertexIndexes.at( ( vi + 1 ) % newFaceSize );
 
  223              bool hasToBeTest = 
false;
 
  225              if ( vertInNewFace1 != -1 && vertInNewFace2 != -1 )
 
  227                hasToBeTest = vertInNewFace1 != index1 &&
 
  228                              vertInNewFace2 != index2 &&
 
  229                              vertInNewFace1 != index2 &&
 
  230                              vertInNewFace2 != index1;
 
  234                if ( vertInNewFace1 == -1 )
 
  235                  hasToBeTest &= vertInNewFace2 != index1 && vertInNewFace2 != index2;
 
  238                if ( vertInNewFace2 == -1 )
 
  239                  hasToBeTest &= vertInNewFace1 != index1 && vertInNewFace1 != index2;
 
  245                const QgsMeshVertex &nv2 = vertices.at( ( vi + 1 ) % newFaceSize );
 
  258        if ( geomEngine->intersects( existingFaceGeom.
constGet() ) )
 
  266  for ( 
const int freeVertexIndex : freeVertices )
 
  268    if ( vertexIndexes.contains( freeVertexIndex ) )
 
  272    if ( geomEngine->contains( &vertex ) )
 
  281  const QList<int> newFaceVerticesIndexes( face.toList() );
 
  282  QList<QgsMeshVertex> allVertices;
 
  283  allVertices.reserve( face.count() );
 
  285    allVertices.append( mTriangularMesh->
vertices().at( i ) );
 
 
  297  QVector<QgsMeshFace> facesToAdd = prepareFaces( {face}, error );
 
 
  320  const QList<int> face = prepareFaceWithNewVertices( verticesIndex, newVertices, error );
 
  322  if ( face.isEmpty() )
 
  331  int size = face.size();
 
  332  QList<QgsMeshVertex> allVertices;
 
  333  allVertices.reserve( verticesIndex.size() );
 
  335  for ( 
int i = 0; i < size; ++i )
 
  337    int index = face.at( i );
 
  340      if ( newVertPos >= newVertices.count() )
 
  342      allVertices.append( newVertices.at( newVertPos++ ) );
 
  346    allVertices.append( mTriangularMesh->
vertices().at( index ) );
 
  351    int prevIndex = face.at( ( i - 1 + size ) % size );
 
  352    int nextIndex = face.at( ( i + 1 ) % size );
 
  359    if ( prevOppVertex == nextIndex ) 
 
  366    if ( nextOppVertex == prevIndex ) 
 
  369    if ( nextIndex != nextOppVertex && prevIndex != prevOppVertex ) 
 
 
  376void QgsMeshEditor::applyEdit( QgsMeshEditor::Edit &edit )
 
  378  mTopologicalMesh.
applyChanges( edit.topologicalChanges );
 
  379  mTriangularMesh->
applyChanges( edit.triangularMeshChanges );
 
  381  if ( mZValueDatasetGroup &&
 
  382       ( !edit.topologicalChanges.newVerticesZValues().isEmpty() ||
 
  383         !edit.topologicalChanges.verticesToRemoveIndexes().isEmpty() ||
 
  384         !edit.topologicalChanges.addedVertices().isEmpty() ) )
 
  387  updateElementsCount( edit.topologicalChanges );
 
  390void QgsMeshEditor::reverseEdit( QgsMeshEditor::Edit &edit )
 
  393  mTriangularMesh->
reverseChanges( edit.triangularMeshChanges, *mMesh );
 
  395  if ( mZValueDatasetGroup &&
 
  396       ( !edit.topologicalChanges.newVerticesZValues().isEmpty() ||
 
  397         !edit.topologicalChanges.verticesToRemoveIndexes().isEmpty() ||
 
  398         !edit.topologicalChanges.addedVertices().isEmpty() ) )
 
  401  updateElementsCount( edit.topologicalChanges, 
false );
 
  404void QgsMeshEditor::applyAddVertex( QgsMeshEditor::Edit &edit, 
const QgsMeshVertex &vertex, 
double tolerance )
 
  409  int faceEdgeIntersect = -1;
 
  410  int edgePosition = -1;
 
  414  if ( 
edgeIsClose( vertexInTriangularCoordinate, tolerance, faceEdgeIntersect, edgePosition ) )
 
  422    if ( includingFaceIndex != -1 )
 
  423      topologicChanges = mTopologicalMesh.
addVertexInFace( includingFaceIndex, vertex );
 
  428  applyEditOnTriangularMesh( edit, topologicChanges );
 
  430  if ( mZValueDatasetGroup )
 
  433  updateElementsCount( edit.topologicalChanges );
 
  436bool QgsMeshEditor::applyRemoveVertexFillHole( QgsMeshEditor::Edit &edit, 
int vertexIndex )
 
  442    applyEditOnTriangularMesh( edit, changes );
 
  444    if ( mZValueDatasetGroup )
 
  447    updateElementsCount( edit.topologicalChanges );
 
  454void QgsMeshEditor::applyRemoveVerticesWithoutFillHole( QgsMeshEditor::Edit &edit, 
const QList<int> &verticesIndexes )
 
  456  applyEditOnTriangularMesh( edit, mTopologicalMesh.
removeVertices( verticesIndexes ) );
 
  458  if ( mZValueDatasetGroup )
 
  461  updateElementsCount( edit.topologicalChanges );
 
  466  applyEditOnTriangularMesh( edit,  mTopologicalMesh.
addFaces( faces ) );
 
  468  updateElementsCount( edit.topologicalChanges );
 
  471void QgsMeshEditor::applyRemoveFaces( QgsMeshEditor::Edit &edit, 
const QList<int> &faceToRemoveIndex )
 
  473  applyEditOnTriangularMesh( edit, mTopologicalMesh.
removeFaces( faceToRemoveIndex ) );
 
  475  updateElementsCount( edit.topologicalChanges );
 
  478void QgsMeshEditor::applyChangeZValue( QgsMeshEditor::Edit &edit, 
const QList<int> &verticesIndexes, 
const QList<double> &newValues )
 
  480  applyEditOnTriangularMesh( edit, mTopologicalMesh.
changeZValue( verticesIndexes, newValues ) );
 
  482  if ( mZValueDatasetGroup )
 
  486void QgsMeshEditor::applyChangeXYValue( QgsMeshEditor::Edit &edit, 
const QList<int> &verticesIndexes, 
const QList<QgsPointXY> &newValues )
 
  488  applyEditOnTriangularMesh( edit, mTopologicalMesh.
changeXYValue( verticesIndexes, newValues ) );
 
  491void QgsMeshEditor::applyFlipEdge( QgsMeshEditor::Edit &edit, 
int vertexIndex1, 
int vertexIndex2 )
 
  493  applyEditOnTriangularMesh( edit, mTopologicalMesh.
flipEdge( vertexIndex1, vertexIndex2 ) );
 
  495  updateElementsCount( edit.topologicalChanges );
 
  498void QgsMeshEditor::applyMerge( QgsMeshEditor::Edit &edit, 
int vertexIndex1, 
int vertexIndex2 )
 
  500  applyEditOnTriangularMesh( edit, mTopologicalMesh.
merge( vertexIndex1, vertexIndex2 ) );
 
  502  updateElementsCount( edit.topologicalChanges );
 
  505void QgsMeshEditor::applySplit( QgsMeshEditor::Edit &edit, 
int faceIndex )
 
  507  applyEditOnTriangularMesh( edit, mTopologicalMesh.
splitFace( faceIndex ) );
 
  509  updateElementsCount( edit.topologicalChanges );
 
  514  applyEditOnTriangularMesh( edit, editing->
apply( 
this ) );
 
  516  updateElementsCount( edit.topologicalChanges );
 
  518  if ( mZValueDatasetGroup )
 
  527  edit.topologicalChanges = topologicChanges;
 
  528  edit.triangularMeshChanges = triangularChanges;
 
  574                              point.
y() - tolerance,
 
  575                              point.
x() + tolerance,
 
  576                              point.
y() + tolerance );
 
  579  double minDist = std::numeric_limits<double>::max();
 
  581  double epsilon = std::numeric_limits<double>::epsilon() * tolerance;
 
  582  for ( 
const int nativeFaceIndex : nativeFaces )
 
  585    const int faceSize = face.size();
 
  586    for ( 
int i = 0; i < faceSize; ++i )
 
  602      if ( dist < tolerance && dist < minDist )
 
  604        faceIndex = nativeFaceIndex;
 
  611  if ( edgePosition != -1 )
 
 
  620  return mValidFacesCount;
 
 
  625  return mValidVerticesCount;
 
 
  630  return mMaximumVerticesPerFace;
 
 
  647  if ( triangleIndex == -1 )
 
 
  668  return mTopologicalMesh.
canBeMerged( vertexIndex1, vertexIndex2 );
 
 
  681  return mTopologicalMesh.
canBeSplit( faceIndex );
 
 
  686  QList<int> faceIndexesSplittable;
 
  688  for ( 
const int faceIndex : faceIndexes )
 
  690      faceIndexesSplittable.append( faceIndex );
 
  692  if ( faceIndexesSplittable.isEmpty() )
 
  697  return faceIndexesSplittable.count();
 
 
  700QVector<QgsMeshFace> QgsMeshEditor::prepareFaces( 
const QVector<QgsMeshFace> &faces, 
QgsMeshEditingError &error )
 const 
  702  QVector<QgsMeshFace> treatedFaces = faces;
 
  706  for ( 
int i = 0; i < treatedFaces.count(); ++i )
 
  709    if ( mMaximumVerticesPerFace != 0 && face.count() > mMaximumVerticesPerFace )
 
  723QList<int> QgsMeshEditor::prepareFaceWithNewVertices( 
const QList<int> &face, 
const QList<QgsMeshVertex> &newVertices, 
QgsMeshEditingError &error )
 const 
  725  if ( mMaximumVerticesPerFace != 0 && face.count() > mMaximumVerticesPerFace )
 
  731  int faceSize = face.count();
 
  732  QVector<QgsMeshVertex> vertices( faceSize );
 
  733  int newVertexPos = 0;
 
  734  for ( 
int i = 0; i < faceSize; ++i )
 
  736    if ( face.at( i ) == -1 )
 
  738      if ( newVertexPos >= newVertices.count() )
 
  740      vertices[i] = newVertices.at( newVertexPos++ );
 
  742    else if ( face.at( i ) >= 0 )
 
  744      if ( face.at( i ) >= mTriangularMesh->
vertices().count() )
 
  749      vertices[i] = mTriangularMesh->
vertices().at( face.at( i ) );
 
  761  bool clockwise = 
false;
 
  767    QList<int> newFace = face;
 
  768    for ( 
int i = 0; i < faceSize / 2; ++i )
 
  770      int temp = newFace[i];
 
  771      newFace[i] = face.at( faceSize - i - 1 );
 
  772      newFace[faceSize - i - 1] = temp;
 
  784  QVector<QgsMeshFace> facesToAdd = prepareFaces( faces, error );
 
 
  808  mUndoStack->beginMacro( tr( 
"Add a face with new %n vertices", 
nullptr, newVertices.count() ) );
 
  812  for ( 
int i = 0; i < vertexIndexes.count(); ++i )
 
  814    int index = vertexIndexes.at( i );
 
  816      face[i] = newVertexIndex++;
 
  822  mUndoStack->endMacro();
 
 
  829  QVector<QgsMeshVertex> verticesInLayerCoordinate( vertices.count() );
 
  830  int ignoredVertex = 0;
 
  831  for ( 
int i = 0; i < vertices.count(); ++i )
 
  833    const QgsPointXY &pointInTriangularMesh = vertices.at( i );
 
  834    bool isTooClose = 
false;
 
  836    if ( triangleIndex != -1 )
 
  839      for ( 
int j = 0; j < 3; ++j )
 
  842        double dist = pointInTriangularMesh.
distance( facePoint );
 
  843        if ( dist < tolerance )
 
  856    if ( verticesInLayerCoordinate.at( i ).isEmpty() )
 
  860  if ( ignoredVertex < vertices.count() )
 
  865  int effectivlyAddedVertex = vertices.count() - ignoredVertex;
 
  867  return effectivlyAddedVertex;
 
 
  879  QList<int> verticesIndexes = verticesToRemoveIndexes;
 
  881  QSet<int> concernedNativeFaces;
 
  882  for ( 
const int vi : std::as_const( verticesIndexes ) )
 
  885    concernedNativeFaces.unite( QSet< int >( faces.begin(), faces.end() ) );
 
 
  899  QList<int> remainingVertices;
 
  902  return remainingVertices;
 
 
  913  for ( 
const int faceIndex : facesToCheck )
 
  916    int faceSize = face.count();
 
  917    QVector<QgsPointXY> pointsInTriangularMeshCoordinate( faceSize );
 
  918    QVector<QgsPointXY> points( faceSize );
 
  919    for ( 
int i = 0; i < faceSize; ++i )
 
  922      int ip1 = face[( i + 1 ) % faceSize];
 
  923      int ip2 = face[( i + 2 ) % faceSize];
 
  929      double ux = p0.x() - p1.
x();
 
  930      double uy = p0.y() - p1.
y();
 
  931      double vx = p2.
x() - p1.
x();
 
  932      double vy = p2.
y() - p1.
y();
 
  934      double crossProduct = ux * vy - uy * vx;
 
  935      if ( crossProduct >= 0 ) 
 
  944    QList<int> otherFaceIndexes =
 
  947    for ( 
const int otherFaceIndex : otherFaceIndexes )
 
  950      int existingFaceSize = otherFace.count();
 
  951      bool shareVertex = 
false;
 
  952      for ( 
int i = 0; i < existingFaceSize; ++i )
 
  954        if ( face.contains( otherFace.at( i ) ) )
 
  963        for ( 
int i = 0; i < existingFaceSize; ++i )
 
  965          int index1 = otherFace.at( i );
 
  966          int index2 = otherFace.at( ( i + 1 ) % existingFaceSize );
 
  967          if ( ! face.contains( index1 )  && !face.contains( index2 ) )
 
  969            const QgsPointXY &v1 = transformFunction( index1 );
 
  970            const QgsPointXY &v2 =  transformFunction( index2 );
 
  979        QVector<QgsPointXY> otherPoints( existingFaceSize );
 
  980        for ( 
int i = 0; i < existingFaceSize; ++i )
 
  981          otherPoints[i] = transformFunction( otherFace.at( i ) );
 
  983        if ( deformedFace.
intersects( existingFaceGeom ) )
 
  989    for ( 
const int vertexIndex : freeVerticesIndex )
 
  991      const QgsPointXY &mapPoint = transformFunction( vertexIndex ); 
 
  992      if ( deformedFace.
contains( &mapPoint ) )
 
  999  for ( 
const int vertexIndex : freeVerticesIndex )
 
 1001    const QgsMeshVertex &newFreeVertexPosition = transformFunction( vertexIndex ); 
 
 1005    if ( originalIncludingFace != -1 )
 
 1010      int faceSize = face.count();
 
 1011      QVector<QgsPointXY> points( faceSize );
 
 1012      for ( 
int i = 0; i < faceSize; ++i )
 
 1013        points[i] = transformFunction( face.at( i ) );
 
 1016      const QgsPointXY ptXY( newFreeVertexPosition );
 
 1017      if ( deformedFace.
contains( &ptXY ) )
 
 
 1044  mUndoStack->clear();
 
 
 1048  : mMeshEditor( meshEditor )
 
 
 1057  for ( 
int i = 
mEdits.count() - 1; i >= 0; --i )
 
 
 1066  for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1072  , mVertices( vertices )
 
 1073  , mTolerance( tolerance )
 
 1075  setText( QObject::tr( 
"Add %n vertices", 
nullptr, mVertices.count() ) );
 
 
 1080  if ( !mVertices.isEmpty() )
 
 1082    for ( 
int i = 0; i < mVertices.count(); ++i )
 
 1087      QgsMeshEditor::Edit edit;
 
 1088      mMeshEditor->applyAddVertex( edit, vertex, mTolerance );
 
 1095    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1102  const QList<int> &verticesToRemoveIndexes,
 
 1103  QList<int> *remainingVerticesPointer )
 
 1105  , mVerticesToRemoveIndexes( verticesToRemoveIndexes )
 
 1106  , mRemainingVerticesPointer( remainingVerticesPointer )
 
 1108  setText( QObject::tr( 
"Remove %n vertices filling holes", 
nullptr, verticesToRemoveIndexes.count() ) );
 
 
 1113  int initialVertexCount = mVerticesToRemoveIndexes.count();
 
 1114  if ( !mVerticesToRemoveIndexes.isEmpty() )
 
 1116    QgsMeshEditor::Edit edit;
 
 1117    QList<int> vertexToRetry;
 
 1118    while ( !mVerticesToRemoveIndexes.isEmpty() )
 
 1121      for ( 
const int &vertex : std::as_const( mVerticesToRemoveIndexes ) )
 
 1123        if ( 
mMeshEditor->applyRemoveVertexFillHole( edit, vertex ) )
 
 1126          vertexToRetry.append( vertex );
 
 1129      if ( vertexToRetry.count() == mVerticesToRemoveIndexes.count() )
 
 1132        mVerticesToRemoveIndexes = vertexToRetry;
 
 1135    if ( initialVertexCount == mVerticesToRemoveIndexes.count() )
 
 1136      setObsolete( 
true );
 
 1138    if ( mRemainingVerticesPointer )
 
 1139      *mRemainingVerticesPointer = mVerticesToRemoveIndexes;
 
 1141    mRemainingVerticesPointer = 
nullptr;
 
 1143    mVerticesToRemoveIndexes.clear(); 
 
 1147    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1155  const QList<int> &verticesToRemoveIndexes )
 
 1157  , mVerticesToRemoveIndexes( verticesToRemoveIndexes )
 
 1159  setText( QObject::tr( 
"Remove %n vertices without filling holes", 
nullptr, verticesToRemoveIndexes.count() ) ) ;
 
 
 1164  if ( !mVerticesToRemoveIndexes.isEmpty() )
 
 1166    QgsMeshEditor::Edit edit;
 
 1168    mMeshEditor->applyRemoveVerticesWithoutFillHole( edit, mVerticesToRemoveIndexes );
 
 1171    mVerticesToRemoveIndexes.clear(); 
 
 1175    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1184  setText( QObject::tr( 
"Add %n face(s)", 
nullptr, faces.
meshFaces().count() ) );
 
 
 1191    QgsMeshEditor::Edit edit;
 
 1199    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1206  , mfacesToRemoveIndexes( facesToRemoveIndexes )
 
 1208  setText( QObject::tr( 
"Remove %n face(s)", 
nullptr, facesToRemoveIndexes.count() ) );
 
 
 1213  if ( !mfacesToRemoveIndexes.isEmpty() )
 
 1215    QgsMeshEditor::Edit edit;
 
 1216    mMeshEditor->applyRemoveFaces( edit, mfacesToRemoveIndexes );
 
 1219    mfacesToRemoveIndexes.clear(); 
 
 1223    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1240    return !mUndoStack->isClean();
 
 
 1248  mUndoStack->clear();
 
 1258    if ( !mTopologicalMesh.
renumber() )
 
 
 1293  return mTopologicalMesh;
 
 
 1298  return mTriangularMesh;
 
 
 1303  , mVerticesIndexes( verticesIndexes )
 
 1304  , mNewValues( newValues )
 
 1306  setText( QObject::tr( 
"Change %n vertices Z Value", 
nullptr, verticesIndexes.count() ) );
 
 
 1311  if ( !mVerticesIndexes.isEmpty() )
 
 1313    QgsMeshEditor::Edit edit;
 
 1314    mMeshEditor->applyChangeZValue( edit, mVerticesIndexes, mNewValues );
 
 1316    mVerticesIndexes.clear();
 
 1321    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1328  , mVerticesIndexes( verticesIndexes )
 
 1329  , mNewValues( newValues )
 
 1331  setText( QObject::tr( 
"Move %n vertices", 
nullptr, verticesIndexes.count() ) );
 
 
 1336  if ( !mVerticesIndexes.isEmpty() )
 
 1338    QgsMeshEditor::Edit edit;
 
 1339    mMeshEditor->applyChangeXYValue( edit, mVerticesIndexes, mNewValues );
 
 1341    mVerticesIndexes.clear();
 
 1346    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1354  , mVerticesIndexes( verticesIndexes )
 
 1355  , mNewCoordinates( newCoordinates )
 
 1357  setText( QObject::tr( 
"Transform %n vertices coordinates", 
nullptr, verticesIndexes.count() ) );
 
 
 1362  if ( !mVerticesIndexes.isEmpty() )
 
 1364    QgsMeshEditor::Edit editXY;
 
 1365    QList<QgsPointXY> newXY;
 
 1366    newXY.reserve( mNewCoordinates.count() );
 
 1367    QgsMeshEditor::Edit editZ;
 
 1369    newZ.reserve( mNewCoordinates.count() );
 
 1371    for ( 
const QgsPoint &pt : std::as_const( mNewCoordinates ) )
 
 1374      newZ.append( pt.z() );
 
 1377    mMeshEditor->applyChangeXYValue( editXY, mVerticesIndexes, newXY );
 
 1379    mMeshEditor->applyChangeZValue( editZ, mVerticesIndexes, newZ );
 
 1381    mVerticesIndexes.clear();
 
 1382    mNewCoordinates.clear();
 
 1386    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1395  , mVertexIndex1( vertexIndex1 )
 
 1396  , mVertexIndex2( vertexIndex2 )
 
 1398  setText( QObject::tr( 
"Flip edge" ) );
 
 
 1403  if ( mVertexIndex1 >= 0 && mVertexIndex2 >= 0 )
 
 1405    QgsMeshEditor::Edit edit;
 
 1406    mMeshEditor->applyFlipEdge( edit, mVertexIndex1, mVertexIndex2 );
 
 1413    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1420  , mVertexIndex1( vertexIndex1 )
 
 1421  , mVertexIndex2( vertexIndex2 )
 
 1423  setText( QObject::tr( 
"Merge faces" ) );
 
 
 1428  if ( mVertexIndex1 >= 0 && mVertexIndex2 >= 0 )
 
 1430    QgsMeshEditor::Edit edit;
 
 1431    mMeshEditor->applyMerge( edit, mVertexIndex1, mVertexIndex2 );
 
 1438    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1445  , mFaceIndexes( faceIndexes )
 
 1447  setText( QObject::tr( 
"Split %n face(s)", 
nullptr, faceIndexes.count() ) );
 
 
 1452  if ( !mFaceIndexes.isEmpty() )
 
 1454    for ( 
int faceIndex : std::as_const( mFaceIndexes ) )
 
 1456      QgsMeshEditor::Edit edit;
 
 1460    mFaceIndexes.clear();
 
 1464    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1471  , mAdvancedEditing( advancdEdit )
 
 1473  setText( advancdEdit->
text() );
 
 
 1478  if ( mAdvancedEditing )
 
 1480    QgsMeshEditor::Edit edit;
 
 1483      mMeshEditor->applyAdvancedEdit( edit, mAdvancedEditing );
 
 1487    mAdvancedEditing = 
nullptr;
 
 1491    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1502  , mTolerance( tolerance )
 
 1504  setText( QObject::tr( 
"Add vertex inside face with Delaunay refinement" ) );
 
 
 1511    QgsMeshEditor::Edit edit;
 
 1513    mMeshEditor->applyAddVertex( edit, mVertex, mTolerance );
 
 1516    QList<std::pair<int, int>> sharedEdges = innerEdges( secondNeighboringTriangularFaces() );
 
 1518    for ( std::pair<int, int> edge : sharedEdges )
 
 1520      if ( 
mMeshEditor->edgeCanBeFlipped( edge.first, edge.second ) && !
mMeshEditor->topologicalMesh().delaunayConditionForEdge( edge.first, edge.second ) )
 
 1522        mMeshEditor->applyFlipEdge( edit, edge.first, edge.second );
 
 1531    for ( QgsMeshEditor::Edit &edit : 
mEdits )
 
 
 1536QSet<int> QgsMeshLayerUndoCommandAddVertexInFaceWithDelaunayRefinement::secondNeighboringTriangularFaces()
 
 1538  const int vIndex = 
mMeshEditor->topologicalMesh().mesh()->vertexCount() - 1;
 
 1539  const QList<int> firstNeighborFaces = 
mMeshEditor->topologicalMesh().facesAroundVertex( vIndex );
 
 1540  QSet<int> firstNeighborVertices;
 
 1541  for ( 
int face : firstNeighborFaces )
 
 1544    for ( 
int vertex : meshFace )
 
 1546      firstNeighborVertices.insert( vertex );
 
 1550  QSet<int> secondNeighboringFaces;
 
 1551  for ( 
int vertex : firstNeighborVertices )
 
 1553    const QList<int> faces = 
mMeshEditor->topologicalMesh().facesAroundVertex( vertex );
 
 1554    for ( 
int face : faces )
 
 1556      if ( 
mMeshEditor->topologicalMesh().mesh()->face( face ).count() == 3 )
 
 1557        secondNeighboringFaces.insert( face );
 
 1560  return secondNeighboringFaces;
 
 1563QList<std::pair<int, int>> QgsMeshLayerUndoCommandAddVertexInFaceWithDelaunayRefinement::innerEdges( 
const QSet<int> &faces )
 
 1566  QMap<std::pair<int, int>, 
int> edges;
 
 1568  for ( 
int faceIndex : faces )
 
 1572    for ( 
int i = 0; i < face.size(); i++ )
 
 1575      if ( next == face.size() )
 
 1580      int minIndex = std::min( face.at( i ), face.at( next ) );
 
 1581      int maxIndex = std::max( face.at( i ), face.at( next ) );
 
 1582      std::pair<int, int> edge = std::pair<int, int>( minIndex, maxIndex );
 
 1585      if ( edges.contains( edge ) )
 
 1587        count = edges.take( edge );
 
 1591      edges.insert( edge, count );
 
 1595  QList<std::pair<int, int>> sharedEdges;
 
 1597  for ( 
auto it = edges.begin(); it != edges.end(); it++ )
 
 1599    if ( it.value() == 2 )
 
 1601      sharedEdges.push_back( it.key() );
 
Provides global constants and enumerations for use throughout the application.
 
MeshEditingErrorType
Type of error that can occur during mesh frame editing.
 
@ TooManyVerticesInFace
A face has more vertices than the maximum number supported per face.
 
@ InvalidFace
An error occurs due to an invalid face (for example, vertex indexes are unordered)
 
@ UniqueSharedVertex
A least two faces share only one vertices.
 
@ ManifoldFace
ManifoldFace.
 
@ InvalidVertex
An error occurs due to an invalid vertex (for example, vertex index is out of range the available ver...
 
@ FlatFace
A flat face is present.
 
static double sqrDistToLine(double ptX, double ptY, double x1, double y1, double x2, double y2, double &minDistX, double &minDistY, double epsilon)
Returns the squared distance between a point and a line.
 
A geometry is the spatial representation of a feature.
 
static QgsGeometry fromPolylineXY(const QgsPolylineXY &polyline)
Creates a new LineString geometry from a list of QgsPointXY points.
 
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
 
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
 
static QgsGeometry fromPolygonXY(const QgsPolygonXY &polygon)
Creates a new geometry from a QgsPolygonXY.
 
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
 
bool intersects(const QgsRectangle &rectangle) const
Returns true if this geometry exactly intersects with a rectangle.
 
Line string geometry type, with support for z-dimension and m-values.
 
Abstract class that can be derived to implement advanced editing on mesh.
 
virtual QgsTopologicalMesh::Changes apply(QgsMeshEditor *meshEditor)=0
Apply a change to mesh Editor.
 
virtual bool isFinished() const
Returns whether the advanced edit is finished, if not, this edit has to be applied again with QgsMesh...
 
virtual QString text() const
Returns a short text string describing what this advanced edit does. Default implementation return a ...
 
virtual int maximumVerticesCountPerFace() const
Returns the maximum number of vertices per face supported by the current mesh, if returns 0,...
 
Abstract class that represents a dataset group.
 
void setStatisticObsolete() const
Sets statistic obsolete, that means statistic will be recalculated when requested.
 
Represents an error which occurred during mesh editing.
 
Qgis::MeshEditingErrorType errorType
 
QgsMeshEditingError()
Constructor of the default error, that is NoError.
 
Handles edit operations on a mesh layer.
 
friend class QgsMeshLayerUndoCommandSplitFaces
 
QgsMeshEditingError initialize()
Initializes the mesh editor and returns first error if the internal native mesh has topological error...
 
friend class QgsMeshLayerUndoCommandMerge
 
void changeXYValues(const QList< int > &verticesIndexes, const QList< QgsPointXY > &newValues)
Changes the (X,Y) coordinates values of the vertices with indexes in verticesIndexes with the values ...
 
int validFacesCount() const
Returns the count of valid faces, that is non void faces in the mesh.
 
friend class QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles
 
QgsMeshEditingError removeFaces(const QList< int > &facesToRemove)
Removes faces faces to the mesh, returns topological errors if this operation fails (operation is not...
 
QgsMeshEditingError addFaces(const QVector< QgsMeshFace > &faces)
Adds faces faces to the mesh, returns topological errors if this operation fails (operation is not re...
 
bool checkConsistency(QgsMeshEditingError &error) const
Return true if the edited mesh is consistent.
 
QList< int > removeVerticesFillHoles(const QList< int > &verticesToRemoveIndexes)
Removes vertices with indexes in the list verticesToRemoveIndexes in the mesh the surrounding faces A...
 
void flipEdge(int vertexIndex1, int vertexIndex2)
Flips edge (vertexIndex1, vertexIndex2)
 
QgsRectangle extent() const
Returns the extent of the edited mesh.
 
friend class QgsMeshLayerUndoCommandAddVertices
 
bool faceCanBeSplit(int faceIndex) const
Returns true if face with index faceIndex can be split.
 
QgsMeshEditingError initializeWithErrorsFix()
Initializes the mesh editor.
 
int maximumVerticesPerFace() const
Returns the maximum count of vertices per face that the mesh can support.
 
QgsMeshEditingError addFace(const QVector< int > &vertexIndexes)
Adds a face face to the mesh with vertex indexes vertexIndexes, returns topological errors if this op...
 
QgsMeshEditor(QgsMeshLayer *meshLayer)
Constructor with a specified layer meshLayer.
 
void merge(int vertexIndex1, int vertexIndex2)
Merges faces separated by vertices with indexes vertexIndex1 and vertexIndex2.
 
bool edgeIsClose(QgsPointXY point, double tolerance, int &faceIndex, int &edgePosition)
Returns true if an edge of face is closest than the tolerance from the point in triangular mesh coord...
 
QgsMeshEditingError removeVerticesWithoutFillHoles(const QList< int > &verticesToRemoveIndexes)
Removes vertices with indexes in the list verticesToRemoveIndexes in the mesh removing the surroundin...
 
bool isFaceGeometricallyCompatible(const QgsMeshFace &face) const
Returns true if the face does not intersect or contains any other elements (faces or vertices) The to...
 
QList< int > freeVerticesIndexes() const
Returns all the free vertices indexes.
 
friend class QgsMeshLayerUndoCommandChangeXYValue
 
void addVertexWithDelaunayRefinement(const QgsMeshVertex &vertex, const double tolerance)
Add a vertex in a face with Delaunay refinement of neighboring faces All neighboring faces sharing a ...
 
bool isVertexOnBoundary(int vertexIndex) const
Returns whether the vertex with index vertexIndex is on a boundary.
 
friend class QgsMeshLayerUndoCommandFlipEdge
 
bool faceCanBeAdded(const QgsMeshFace &face) const
Returns true if a face can be added to the mesh.
 
void changeCoordinates(const QList< int > &verticesIndexes, const QList< QgsPoint > &newCoordinates)
Changes the (X,Y,Z) coordinates values of the vertices with indexes in vertices indexes with the valu...
 
void stopEditing()
Stops editing.
 
friend class QgsMeshLayerUndoCommandAdvancedEditing
 
bool canBeMerged(int vertexIndex1, int vertexIndex2) const
Returns true if faces separated by vertices with indexes vertexIndex1 and vertexIndex2 can be merged.
 
friend class QgsMeshLayerUndoCommandAddFaces
 
QgsMeshEditingError addFaceWithNewVertices(const QList< int > &vertexIndexes, const QList< QgsMeshVertex > &newVertices)
Adds a face formed by some vertices vertexIndexes to the mesh, returns topological errors if this ope...
 
friend class QgsMeshLayerUndoCommandChangeCoordinates
 
bool edgeCanBeFlipped(int vertexIndex1, int vertexIndex2) const
Returns true if the edge can be flipped (only available for edge shared by two faces with 3 vertices)
 
int splitFaces(const QList< int > &faceIndexes)
Splits faces with index faceIndexes.
 
QgsMeshVertexCirculator vertexCirculator(int vertexIndex) const
Returns a vertex circulator linked to this mesh around the vertex with index vertexIndex.
 
bool faceCanBeAddedWithNewVertices(const QList< int > &verticesIndex, const QList< QgsMeshVertex > &newVertices) const
Returns true if a face formed by some vertices can be added to the mesh.
 
void meshEdited()
Emitted when the mesh is edited.
 
friend class QgsMeshLayerUndoCommandAddVertexInFaceWithDelaunayRefinement
 
void changeZValues(const QList< int > &verticesIndexes, const QList< double > &newValues)
Changes the Z values of the vertices with indexes in vertices indexes with the values in newValues.
 
void resetTriangularMesh(QgsTriangularMesh *triangularMesh)
Resets the triangular mesh.
 
bool isModified() const
Returns whether the mesh has been modified.
 
void advancedEdit(QgsMeshAdvancedEditing *editing)
Applies an advance editing on the edited mesh, see QgsMeshAdvancedEditing.
 
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...
 
int addVertices(const QVector< QgsMeshVertex > &vertices, double tolerance)
Adds vertices in triangular mesh coordinate in the mesh.
 
int validVerticesCount() const
Returns the count of valid vertices, that is non void vertices in the mesh.
 
friend class QgsMeshLayerUndoCommandRemoveVerticesFillHoles
 
bool isVertexFree(int vertexIndex) const
Returns whether the vertex with index vertexIndex is a free vertex.
 
bool reindex(bool renumbering)
Reindexes the mesh, that is remove unusued index of face and vertices, this operation void the undo/r...
 
friend class QgsMeshLayerUndoCommandChangeZValue
 
QgsTriangularMesh * triangularMesh()
Returns a pointer to the triangular mesh.
 
bool fixError(const QgsMeshEditingError &error)
Tries to fix the topological error in the mesh.
 
QgsMeshDatasetGroup * createZValueDatasetGroup()
Creates and returns a scalar dataset group with value on vertex that is can be used to access the Z v...
 
friend class QgsMeshLayerUndoCommandRemoveFaces
 
QgsTopologicalMesh & topologicalMesh()
Returns a reference to the topological mesh.
 
int addPointsAsVertices(const QVector< QgsPoint > &point, double tolerance)
Adds points as vertices in triangular mesh coordinate in the mesh.
 
QgsMeshLayerUndoCommandAddFaces(QgsMeshEditor *meshEditor, QgsTopologicalMesh::TopologicalFaces &faces)
Constructor with the associated meshEditor and faces that will be added.
 
QgsMeshLayerUndoCommandAddVertexInFaceWithDelaunayRefinement(QgsMeshEditor *meshEditor, const QgsMeshVertex &vertex, double tolerance)
Constructor with the associated meshEditor and indexes vertex and tolerance.
 
QgsMeshLayerUndoCommandAddVertices(QgsMeshEditor *meshEditor, const QVector< QgsMeshVertex > &vertices, double tolerance)
Constructor with the associated meshEditor and vertices that will be added.
 
QgsMeshLayerUndoCommandAdvancedEditing(QgsMeshEditor *meshEditor, QgsMeshAdvancedEditing *advancdEdit)
Constructor with the associated meshEditor.
 
QgsMeshLayerUndoCommandChangeCoordinates(QgsMeshEditor *meshEditor, const QList< int > &verticesIndexes, const QList< QgsPoint > &newCoordinates)
Constructor with the associated meshEditor and indexes verticesIndexes of the vertices that will have...
 
QgsMeshLayerUndoCommandChangeXYValue(QgsMeshEditor *meshEditor, const QList< int > &verticesIndexes, const QList< QgsPointXY > &newValues)
Constructor with the associated meshEditor and indexes verticesIndexes of the vertices that will have...
 
QgsMeshLayerUndoCommandChangeZValue(QgsMeshEditor *meshEditor, const QList< int > &verticesIndexes, const QList< double > &newValues)
Constructor with the associated meshEditor and indexes verticesIndexes of the vertices that will have...
 
QgsMeshLayerUndoCommandFlipEdge(QgsMeshEditor *meshEditor, int vertexIndex1, int vertexIndex2)
Constructor with the associated meshEditor and the vertex indexes of the edge (vertexIndex1,...
 
QgsMeshLayerUndoCommandMerge(QgsMeshEditor *meshEditor, int vertexIndex1, int vertexIndex2)
Constructor with the associated meshEditor and the vertex indexes of the edge (vertexIndex1,...
 
Base class for undo/redo command for mesh editing.
 
QList< QgsMeshEditor::Edit > mEdits
 
QgsMeshLayerUndoCommandMeshEdit(QgsMeshEditor *meshEditor)
Constructor for the base class.
 
QPointer< QgsMeshEditor > mMeshEditor
 
QgsMeshLayerUndoCommandRemoveFaces(QgsMeshEditor *meshEditor, const QList< int > &facesToRemoveIndexes)
Constructor with the associated meshEditor and indexes facesToRemoveIndexes of the faces that will be...
 
QgsMeshLayerUndoCommandRemoveVerticesFillHoles(QgsMeshEditor *meshEditor, const QList< int > &verticesToRemoveIndexes, QList< int > *remainingVerticesPointer=nullptr)
Constructor with the associated meshEditor and vertices that will be removed.
 
QgsMeshLayerUndoCommandRemoveVerticesWithoutFillHoles(QgsMeshEditor *meshEditor, const QList< int > &verticesToRemoveIndexes)
Constructor with the associated meshEditor and vertices that will be removed.
 
QgsMeshLayerUndoCommandSplitFaces(QgsMeshEditor *meshEditor, const QList< int > &faceIndexes)
Constructor with the associated meshEditor and indexes faceIndexes of the faces to split.
 
Represents a mesh layer supporting display of data on structured or unstructured meshes.
 
QgsMeshDataProvider * dataProvider() override
Returns the layer's data provider, it may be nullptr.
 
static QgsGeometry toGeometry(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry.
 
Convenience class that turns around a vertex and provides information about faces and vertices.
 
bool goBoundaryCounterClockwise() const
Sets the circulator on the boundary face turning counter clockwise, return false is there isn't bound...
 
int oppositeVertexCounterClockwise() const
Returns the opposite vertex of the current face and on the edge on the side turning counter clockwise...
 
bool goBoundaryClockwise() const
Sets the circulator on the boundary face turning clockwise, return false is there isn't boundary face...
 
int oppositeVertexClockwise() const
Returns the opposite vertex of the current face and on the edge on the side turning clockwise.
 
double distance(double x, double y) const
Returns the distance between this point and a specified x, y coordinate.
 
Point geometry type, with support for z-dimension and m-values.
 
bool isEmpty() const override
Returns true if the geometry is empty.
 
A rectangle specified with double values.
 
Contains topological differences between two states of a topological mesh, only accessible from the Q...
 
QVector< QgsMeshFace > removedFaces() const
Returns the faces that are removed with this changes.
 
QVector< QgsMeshVertex > addedVertices() const
Returns the added vertices with this changes.
 
bool isEmpty() const
Returns whether changes are empty, that there is nothing to change.
 
QVector< QgsMeshFace > addedFaces() const
Returns the face that are added with this changes.
 
QList< int > verticesToRemoveIndexes() const
Returns the indexes of vertices to remove.
 
Contains independent faces and topological information about these faces.
 
void clear()
Clears all data contained in the instance.
 
QVector< QgsMeshFace > meshFaces() const
Returns faces.
 
Wraps a QgsMesh to ensure the consistency of the mesh during editing and helps to access elements fro...
 
static QgsMeshEditingError checkTopologyOfVerticesAsFace(const QVector< QgsMeshVertex > &vertices, bool &clockwise)
Checks the topology of the vertices as they are contained in a face and returns indication on directi...
 
Changes changeZValue(const QList< int > &verticesIndexes, const QList< double > &newValues)
Changes the Z values of the vertices with indexes in vertices indexes with the values in newValues.
 
static QgsTopologicalMesh createTopologicalMesh(QgsMesh *mesh, int maxVerticesPerFace, QgsMeshEditingError &error)
Creates a topologicaly consistent mesh with mesh, this static method modifies mesh to be topological ...
 
bool isVertexFree(int vertexIndex) const
Returns whether the vertex is a free vertex.
 
static QgsMeshEditingError counterClockwiseFaces(QgsMeshFace &face, QgsMesh *mesh)
Checks the topology of the face and sets it counter clockwise if necessary.
 
Changes removeVertexFillHole(int vertexIndex)
Removes the vertex with index vertexIndex.
 
void applyChanges(const Changes &changes)
Applies the changes.
 
QgsMeshEditingError checkConsistency() const
Checks the consistency of the topological mesh and return false if there is a consistency issue.
 
Changes removeVertices(const QList< int > &vertices)
Removes all the vertices with index in the list vertices If vertices in linked with faces,...
 
Changes changeXYValue(const QList< int > &verticesIndexes, const QList< QgsPointXY > &newValues)
Changes the (X,Y) values of the vertices with indexes in vertices indexes with the values in newValue...
 
void reindex()
Reindexes faces and vertices, after this operation, the topological mesh can't be edited anymore and ...
 
QgsMeshEditingError facesCanBeAdded(const TopologicalFaces &topologicalFaces) const
Returns whether the faces can be added to the mesh.
 
bool renumber()
Renumbers the indexes of vertices and faces using the Reverse CutHill McKee Algorithm.
 
Changes flipEdge(int vertexIndex1, int vertexIndex2)
Flips edge (vertexIndex1, vertexIndex2) The method returns a instance of the class QgsTopologicalMesh...
 
QgsMeshEditingError facesCanBeRemoved(const QList< int > &facesIndexes)
Returns whether faces with index in faceIndexes can be removed/ The method an error object with type ...
 
void reverseChanges(const Changes &changes)
Reverses the changes.
 
Changes addFaces(const TopologicalFaces &topologicFaces)
Adds faces topologicFaces to the topologic mesh.
 
Changes merge(int vertexIndex1, int vertexIndex2)
Merges faces separated by vertices with indexes vertexIndex1 and vertexIndex2 The method returns a in...
 
Changes removeFaces(const QList< int > &facesIndexes)
Removes faces with index in faceIndexes.
 
QList< int > freeVerticesIndexes() const
Returns a list of vertices are not linked to any faces.
 
bool edgeCanBeFlipped(int vertexIndex1, int vertexIndex2) const
Returns true if the edge can be flipped (only available for edge shared by two faces with 3 vertices)
 
Changes addVertexInFace(int faceIndex, const QgsMeshVertex &vertex)
Adds a vertex in the face with index faceIndex.
 
bool canBeMerged(int vertexIndex1, int vertexIndex2) const
Returns true if faces separated by vertices with indexes vertexIndex1 and vertexIndex2 can be merged.
 
QList< int > facesAroundVertex(int vertexIndex) const
Returns the indexes of faces that are around the vertex with index vertexIndex.
 
bool canBeSplit(int faceIndex) const
Returns true if face with index faceIndex can be split.
 
Changes addFreeVertex(const QgsMeshVertex &vertex)
Adds a free vertex in the face, that is a vertex that is not included or linked with any faces.
 
Changes insertVertexInFacesEdge(int faceIndex, int position, const QgsMeshVertex &vertex)
Inserts a vertex in the edge of face with index faceIndex at position .
 
bool isVertexOnBoundary(int vertexIndex) const
Returns whether the vertex is on a boundary.
 
Changes splitFace(int faceIndex)
Splits face with index faceIndex The method returns a instance of the class QgsTopologicalMesh::Chang...
 
static TopologicalFaces createNewTopologicalFaces(const QVector< QgsMeshFace > &faces, bool uniqueSharedVertexAllowed, QgsMeshEditingError &error)
Creates new topological faces that are not yet included in the mesh.
 
QgsMeshVertexCirculator vertexCirculator(int vertexIndex) const
Returns a vertex circulator linked to this mesh around the vertex with index vertexIndex.
 
Makes changes to a triangular mesh and keeps track of these changes.
 
A triangular/derived mesh with vertices in map coordinates.
 
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
 
QgsRectangle nativeExtent()
Returns the extent of the mesh in the native mesh coordinates system, returns empty extent if the tra...
 
int nativeFaceIndexForPoint(const QgsPointXY &point) const
Finds index of native face at given point It uses spatial indexing.
 
void reverseChanges(const Changes &changes, const QgsMesh &nativeMesh)
Reverses the changes on the triangular mesh (see Changes)
 
void applyChanges(const Changes &changes)
Applies the changes on the triangular mesh (see Changes)
 
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
 
QgsMeshVertex triangularToNativeCoordinates(const QgsMeshVertex &vertex) const
Transforms the vertex from triangular mesh coordinates system to native coordinates system.
 
QgsMeshVertex nativeToTriangularCoordinates(const QgsMeshVertex &vertex) const
Transforms the vertex from native coordinates system to triangular mesh coordinates system.
 
bool update(QgsMesh *nativeMesh, const QgsCoordinateTransform &transform)
Constructs triangular mesh from layer's native mesh and transform to destination CRS.
 
const QVector< QgsMeshVertex > & faceCentroids() const
Returns centroids of the native faces in map CRS.
 
QList< int > nativeFaceIndexForRectangle(const QgsRectangle &rectangle) const
Finds indexes of native faces which bounding boxes intersect given bounding box It uses spatial index...
 
int faceIndexForPoint_v2(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing and don't use geos to be faster.
 
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.
 
QVector< QgsMeshFace > faces
 
int faceCount() const
Returns number of faces.