27static int vertexPositionInFace( 
int vertexIndex, 
const QgsMeshFace &face )
 
   29  return face.indexOf( vertexIndex );
 
   32static int vertexPositionInFace( 
const QgsMesh &mesh, 
int vertexIndex, 
int faceIndex )
 
   34  if ( faceIndex < 0 || faceIndex >= mesh.
faceCount() )
 
   37  return vertexPositionInFace( vertexIndex, mesh.
face( faceIndex ) );
 
   43  double ux1 = v1.
x() - vc.
x();
 
   44  double uy1 = v1.
y() - vc.
y();
 
   45  double vx1 = v2.
x() - vc.
x();
 
   46  double vy1 = v2.
y() - vc.
y();
 
   48  return ux1 * vy1 - uy1 * vx1;
 
   51static double crossProduct( 
int centralVertex, 
int vertex1, 
int vertex2, 
const QgsMesh &mesh )
 
   57  return crossProduct( vc, v1, v2 );
 
   62  : mFaces( topologicalMesh.mMesh->faces )
 
   63  , mFacesNeighborhood( topologicalMesh.mFacesNeighborhood )
 
   64  ,  mVertexIndex( vertexIndex )
 
   66  if ( vertexIndex >= 0 && vertexIndex < topologicalMesh.mMesh->vertexCount() )
 
   68    mCurrentFace = topologicalMesh.mVertexToFace[vertexIndex];
 
   69    mIsValid = vertexPositionInFace( *topologicalMesh.
mesh(), vertexIndex, mCurrentFace ) != -1;
 
   77    mLastValidFace = mCurrentFace;
 
 
   81  : mFaces( topologicalFaces.mFaces )
 
   82  , mFacesNeighborhood( topologicalFaces.mFacesNeighborhood )
 
   83  , mVertexIndex( vertexIndex )
 
   85  const QgsMeshFace &face = topologicalFaces.mFaces.at( faceIndex );
 
   86  mIsValid = vertexPositionInFace( vertexIndex, face ) != -1;
 
   88  mCurrentFace = faceIndex;
 
   89  mLastValidFace = mCurrentFace;
 
 
   93  : mFaces( topologicalFaces.mFaces )
 
   94  , mFacesNeighborhood( topologicalFaces.mFacesNeighborhood )
 
   95  , mVertexIndex( vertexIndex )
 
   97  if ( topologicalFaces.mVerticesToFace.contains( vertexIndex ) )
 
   98    mCurrentFace = topologicalFaces.mVerticesToFace.values( vertexIndex ).first();
 
   99  mLastValidFace = mCurrentFace;
 
  100  mIsValid = mCurrentFace != -1;
 
 
  105  if ( mCurrentFace == -1 )
 
  106    mCurrentFace = mLastValidFace;
 
  109    int currentPos = positionInCurrentFace();
 
  110    Q_ASSERT( currentPos != -1 );
 
  114    mLastValidFace = mCurrentFace;
 
  115    mCurrentFace = mFacesNeighborhood.at( mCurrentFace ).at( ( currentPos + faceSize - 1 ) % 
currentFace.count() );
 
 
  123  if ( mCurrentFace == -1 )
 
  124    mCurrentFace = mLastValidFace;
 
  127    int currentPos = positionInCurrentFace();
 
  128    Q_ASSERT( currentPos != -1 );
 
  132    mLastValidFace = mCurrentFace;
 
  133    mCurrentFace = mFacesNeighborhood.at( mCurrentFace ).at( ( currentPos ) % faceSize );
 
 
  146  if ( mCurrentFace != -1 )
 
  147    return mFaces.at( mCurrentFace );
 
 
  157  if ( mCurrentFace == -1 )
 
  158    mCurrentFace = mLastValidFace;
 
  160  int firstFace = mCurrentFace;
 
  163  if ( mCurrentFace == firstFace )
 
 
  174  if ( mCurrentFace == -1 )
 
  175    mCurrentFace = mLastValidFace;
 
  177  int firstFace = mCurrentFace;
 
  180  if ( mCurrentFace == firstFace )
 
 
  188  if ( mCurrentFace == -1 )
 
  193  if ( face.isEmpty() )
 
  196  int vertexPosition = vertexPositionInFace( mVertexIndex, 
currentFace() );
 
  198  if ( vertexPosition == -1 )
 
  201  return face.at( ( vertexPosition + 1 ) % face.count() );
 
 
  206  if ( mCurrentFace == -1 )
 
  211  if ( face.isEmpty() )
 
  214  int vertexPosition = vertexPositionInFace( mVertexIndex, 
currentFace() );
 
  216  if ( vertexPosition == -1 )
 
  219  return face.at( ( vertexPosition - 1 + face.count() ) % face.count() );
 
 
  233  if ( mCurrentFace != -1 )
 
  234    ret.append( mCurrentFace );
 
 
  279int QgsMeshVertexCirculator::positionInCurrentFace()
 const 
  281  if ( mCurrentFace < 0 || mCurrentFace >= mFaces.count() )
 
  284  return vertexPositionInFace( mVertexIndex, mFaces.at( mCurrentFace ) );
 
  294  for ( 
int i = 0; i < changes.
mFacesToAdd.count(); ++i )
 
  297  for ( 
int boundary : topologicalFaces.mBoundaries )
 
  300    if ( mVertexToFace.at( boundary ) == -1 )
 
  303    const QList<int> &linkedFaces = topologicalFaces.mVerticesToFace.values( boundary );
 
  304    for ( 
int linkedFace : linkedFaces )
 
  310      if ( mVertexToFace.at( oppositeVertexForNewFace ) == -1 )
 
  318      int boundaryPositionInNewFace = vertexPositionInFace( boundary, newFaceBoundary );
 
  320      if ( oppositeVertexForMeshFace != oppositeVertexForNewFace )
 
  332          boundaryPositionInMeshFace,
 
  342  for ( 
int f = 0; f < changes.
mFacesToAdd.count(); ++f )
 
  343    for ( 
int n = 0; n < changes.
mFacesToAdd.at( f ).count(); ++n )
 
  345        changes.
mFacesNeighborhoodToAdd[f][n] = changes.addedFaceIndexInMesh( topologicalFaces.mFacesNeighborhood.at( f ).at( n ) );
 
  347  const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
 
  348  for ( 
const int vtc : verticesToFaceToChange )
 
  349    if ( mVertexToFace.at( vtc ) == -1 )
 
  351                                              mVertexToFace.at( vtc ),
 
  352                                              changes.addedFaceIndexInMesh( topologicalFaces.mVerticesToFace.values( vtc ).first() ) } );
 
  354  applyChanges( changes );
 
 
  361  int initialVerticesCount = mMesh->
vertices.count();
 
  366    mVertexToFace.resize( newSize );
 
  372    mMesh->
faces.resize( newSize );
 
  373    mFacesNeighborhood.resize( newSize );
 
  379    mFacesNeighborhood[changes.removedFaceIndexInMesh( i )] = 
FaceNeighbors();
 
  385    if ( mVertexToFace.at( vertexIndex ) == -1 )
 
  386      dereferenceAsFreeVertex( vertexIndex );
 
  388    mVertexToFace[vertexIndex] = -1;
 
  396      referenceAsFreeVertex( initialVerticesCount + i );
 
  399  for ( 
int i = 0; i < changes.
mFacesToAdd.count(); ++i )
 
  401    mMesh->
faces[changes.addedFaceIndexInMesh( i )] = changes.
mFacesToAdd.at( i );
 
  407    const int faceIndex = neigborChange.at( 0 );
 
  408    const int positionInFace = neigborChange.at( 1 );
 
  409    const int valueToApply = neigborChange.at( 3 );
 
  410    mFacesNeighborhood[faceIndex][positionInFace] = valueToApply;
 
  415    int vertexIndex = vertexToFaceChange.at( 0 );
 
  416    mVertexToFace[vertexToFaceChange.at( 0 )] = vertexToFaceChange.at( 2 );
 
  418    if ( vertexToFaceChange.at( 2 ) == -1 &&
 
  419         vertexToFaceChange.at( 1 ) != -1 &&
 
  420         !mMesh->
vertices.at( vertexIndex ).isEmpty() )
 
  421      referenceAsFreeVertex( vertexIndex );
 
  423    if ( vertexToFaceChange.at( 1 ) == -1 && vertexToFaceChange.at( 2 ) != -1 )
 
  424      dereferenceAsFreeVertex( vertexIndex );
 
  435      mMesh->
vertices[vertexIndex].setX( pt.
x() );
 
  436      mMesh->
vertices[vertexIndex].setY( pt.
y() );
 
 
  445    const int faceIndex = neigborChange.at( 0 );
 
  446    const int positionInFace = neigborChange.at( 1 );
 
  447    const int valueToApply = neigborChange.at( 2 );
 
  448    mFacesNeighborhood[faceIndex][positionInFace] = valueToApply;
 
  462    if ( mVertexToFace.at( vertexIndex ) == -1 )
 
  463      referenceAsFreeVertex( vertexIndex );
 
  467  for ( 
int i = 0; i < verticesToFaceChangesCount; ++i )
 
  469    const std::array<int, 3> vertexToFaceChange = changes.
mVerticesToFaceChanges.at( verticesToFaceChangesCount - i - 1 );
 
  470    int vertexIndex = vertexToFaceChange.at( 0 );
 
  471    mVertexToFace[vertexIndex] = vertexToFaceChange.at( 1 );
 
  473    if ( vertexToFaceChange.at( 2 ) == -1 && vertexToFaceChange.at( 1 ) != -1 )
 
  474      dereferenceAsFreeVertex( vertexIndex );
 
  476    if ( vertexToFaceChange.at( 1 ) == -1 &&
 
  477         vertexToFaceChange.at( 2 ) != -1 &&
 
  479      referenceAsFreeVertex( vertexIndex );
 
  485    mMesh->
faces.resize( newSize );
 
  486    mFacesNeighborhood.resize( newSize );
 
  493    for ( 
int i = newSize; i < mMesh->
vertexCount(); ++i )
 
  494      if ( mVertexToFace.at( i ) == -1 )
 
  495        dereferenceAsFreeVertex( i );
 
  498    mVertexToFace.resize( newSize );
 
  509      mMesh->
vertices[vertexIndex].setX( pt.
x() );
 
  510      mMesh->
vertices[vertexIndex].setY( pt.
y() );
 
 
  520QSet<int> QgsTopologicalMesh::concernedFacesBy( 
const QList<int> &faceIndexes )
 const 
  523  for ( 
const int faceIndex : faceIndexes )
 
  526    for ( 
int i = 0; i < face.count(); ++i )
 
  529      faces.unite( QSet< int >( around.begin(), around.end() ) );
 
  535void QgsTopologicalMesh::dereferenceAsFreeVertex( 
int vertexIndex )
 
  537  mFreeVertices.remove( vertexIndex );
 
  540void QgsTopologicalMesh::referenceAsFreeVertex( 
int vertexIndex )
 
  544  mFreeVertices.insert( vertexIndex );
 
  549  for ( 
int faceIndex = 0 ; faceIndex < mMesh->
faces.count( ); ++faceIndex )
 
  552    const FaceNeighbors &neighborhood = mFacesNeighborhood.at( faceIndex );
 
  553    if ( face.count() != neighborhood.count() )
 
  555    for ( 
int i = 0; i < face.count(); ++i )
 
  557      int vertexIndex = face.at( i );
 
  559      if ( mVertexToFace.at( vertexIndex ) == -1 )
 
  562      int neighborIndex = neighborhood.at( i );
 
  563      if ( neighborIndex != -1 )
 
  566        if ( neighborFace.isEmpty() )
 
  568        int neighborSize = neighborFace.size();
 
  569        const FaceNeighbors &neighborhoodOfNeighbor = mFacesNeighborhood.at( neighborIndex );
 
  570        int posInNeighbor = vertexPositionInFace( *mMesh, vertexIndex, neighborIndex );
 
  571        if ( neighborhoodOfNeighbor.isEmpty() || neighborhoodOfNeighbor.at( ( posInNeighbor + neighborSize - 1 ) % neighborSize ) != faceIndex )
 
  577  for ( 
int vertexIndex = 0; vertexIndex < mMesh->
vertexCount(); ++vertexIndex )
 
  579    if ( mVertexToFace.at( vertexIndex ) != -1 )
 
  581      if ( !mMesh->
face( mVertexToFace.at( vertexIndex ) ).contains( vertexIndex ) )
 
 
  607  if ( vertexIndex < 0 || vertexIndex >= mMesh->
vertexCount() )
 
  609  return mVertexToFace.at( vertexIndex );
 
 
  624  if ( vertexIndex < 0 || vertexIndex >= mMesh->
vertexCount() )
 
  627  if ( mMesh->
vertices.at( vertexIndex ).isEmpty() )
 
  630  return mVertexToFace.at( vertexIndex ) == -1;
 
 
  635  return QList<int>( mFreeVertices.begin(), mFreeVertices.end() );
 
 
  640  int size = vertices.size();
 
  642  for ( 
int i = 0; i < size; ++i )
 
  645    int iv1 = ( i + 1 ) % size;
 
  646    int iv2 = ( i + 2 ) % size;
 
  661    double crossProd = crossProduct( v1, v0, v2 ); 
 
  662    if ( direction != 0 && crossProd * direction < 0 )   
 
  664      clockwise = direction > 0;
 
  667    else if ( crossProd == 0 )
 
  669      clockwise = direction > 0;
 
  672    else if ( direction == 0 )
 
  673      direction = crossProd / std::fabs( crossProd );
 
  676  clockwise = direction > 0;
 
 
  685  int faceSize = face.count();
 
  689  QVector<QgsMeshVertex> vertices( face.size() );
 
  691  for ( 
int i = 0; i < faceSize; ++i )
 
  700  bool clockwise = 
false;
 
  707    for ( 
int i = 0; i < faceSize / 2; ++i )
 
  710      face[i] = face.at( faceSize - i - 1 );
 
  711      face[faceSize - i - 1] = temp;
 
 
  720  QVector<int> oldToNewIndex( mMesh->
vertices.count(), -1 );
 
  724  while ( oldIndex < verticesTotalCount )
 
  732      oldToNewIndex[oldIndex] = newIndex;
 
  733      if ( oldIndex != newIndex )
 
  735      oldToNewIndex[oldIndex] = newIndex;
 
  745  int facesTotalCount = mMesh->
faceCount();
 
  746  while ( oldIndex < facesTotalCount )
 
  748    if ( mMesh->
face( oldIndex ).isEmpty() )
 
  752      if ( oldIndex != newIndex )
 
  753        mMesh->
faces[newIndex] = mMesh->
faces[oldIndex];
 
  755      for ( 
int i = 0; i < face.count(); ++i )
 
  756        face[i] = oldToNewIndex[face.at( i )];
 
  762  mMesh->
faces.resize( newIndex );
 
  764  mVertexToFace.clear();
 
  765  mFacesNeighborhood.clear();
 
 
  770  QVector<int> oldToNewVerticesIndexes;
 
  771  if ( !renumberVertices( oldToNewVerticesIndexes ) )
 
  775  QVector<int> oldToNewFacesIndexes;
 
  777  if ( !renumberFaces( oldToNewFacesIndexes ) )
 
  782  QVector<QgsMeshVertex> tempVertices( mMesh->
vertices.count() );
 
  783  for ( 
int i = 0; i < oldToNewVerticesIndexes.count(); ++i )
 
  785    tempVertices[oldToNewVerticesIndexes.at( i )] = mMesh->
vertex( i );
 
  789  QVector<QgsMeshFace> tempFaces( mMesh->
faces.count() );
 
  790  for ( 
int i = 0; i < oldToNewFacesIndexes.count(); ++i )
 
  792    tempFaces[oldToNewFacesIndexes.at( i )] = mMesh->
face( i );
 
  794    QgsMeshFace &face = tempFaces[oldToNewFacesIndexes.at( i )];
 
  796    for ( 
int fi = 0; fi < face.count(); ++fi )
 
  798      face[fi] = oldToNewVerticesIndexes.at( face.at( fi ) );
 
  802  mMesh->
faces = tempFaces;
 
 
  808bool QgsTopologicalMesh::renumberVertices( QVector<int> &oldToNewIndex )
 const 
  810  std::vector<QgsMeshVertexCirculator> circulators;
 
  811  circulators.reserve( mMesh->
vertices.count() );
 
  812  int minDegree = std::numeric_limits<int>::max();
 
  813  int minDegreeVertex = -1;
 
  816  QSet<int> nonThreadedVertex;
 
  817  oldToNewIndex = QVector<int> ( mMesh->
vertexCount(), -1 );
 
  820    circulators.emplace_back( *
this, i );
 
  822    if ( circulators.back().degree() < minDegree )
 
  824      minDegreeVertex = circulators.size() - 1;
 
  825      minDegree = circulator.
degree();
 
  827    nonThreadedVertex.insert( i );
 
  830  auto sortedNeighbor = [ = ]( QList<int> &neighbors, 
int index )
 
  844      int degree = circulators.at( neighborIndex ).degree();
 
  845      QList<int>::Iterator it = neighbors.begin();
 
  846      while ( it != neighbors.end() )
 
  848        if ( degree <= circulators.at( *it ).degree() )
 
  850          neighbors.insert( it, neighborIndex );
 
  855      if ( it == neighbors.end() )
 
  856        neighbors.append( neighborIndex );
 
  862  int currentVertex = minDegreeVertex;
 
  863  nonThreadedVertex.remove( minDegreeVertex );
 
  865  while ( newIndex < mMesh->vertexCount() )
 
  867    if ( oldToNewIndex[currentVertex] == -1 )
 
  868      oldToNewIndex[currentVertex] = newIndex++;
 
  870    if ( circulators.at( currentVertex ).isValid() )
 
  872      QList<int> neighbors;
 
  873      sortedNeighbor( neighbors, currentVertex );
 
  875      for ( 
const int i : std::as_const( neighbors ) )
 
  876        if ( oldToNewIndex.at( i ) == -1 && nonThreadedVertex.contains( i ) )
 
  879          nonThreadedVertex.remove( i );
 
  883    if ( queue.isEmpty() )
 
  885      if ( nonThreadedVertex.isEmpty() && newIndex < mMesh->vertexCount() )
 
  888      const QList<int> remainingVertex( nonThreadedVertex.constBegin(), nonThreadedVertex.constEnd() );
 
  889      int minRemainingDegree = std::numeric_limits<int>::max();
 
  890      int minRemainingVertex = -1;
 
  891      for ( 
const int i : remainingVertex )
 
  893        int degree = circulators.at( i ).degree();
 
  894        if ( degree < minRemainingDegree )
 
  896          minRemainingDegree = degree;
 
  897          minRemainingVertex = i;
 
  900      currentVertex = minRemainingVertex;
 
  901      nonThreadedVertex.remove( currentVertex );
 
  905      currentVertex = queue.dequeue();
 
  912bool QgsTopologicalMesh::renumberFaces( QVector<int> &oldToNewIndex )
 const 
  915  QSet<int> nonThreadedFaces;
 
  917  oldToNewIndex = QVector<int>( mMesh->
faceCount(), -1 );
 
  919  QVector<int> faceDegrees( mMesh->
faceCount(), 0 );
 
  921  int minDegree = std::numeric_limits<int>::max();
 
  922  int minDegreeFace = -1;
 
  923  for ( 
int faceIndex = 0; faceIndex < mMesh->
faceCount(); ++faceIndex )
 
  925    const FaceNeighbors &neighbors = mFacesNeighborhood.at( faceIndex );
 
  928    for ( 
int n = 0; n < neighbors.size(); ++n )
 
  930      if ( neighbors.at( n ) != -1 )
 
  934    if ( degree < minDegree )
 
  937      minDegreeFace = faceIndex;
 
  940    faceDegrees[faceIndex] = degree;
 
  941    nonThreadedFaces.insert( faceIndex );
 
  945  int currentFace = minDegreeFace;
 
  946  nonThreadedFaces.remove( minDegreeFace );
 
  948  auto sortedNeighbor = [ = ]( QList<int> &neighbors, 
int index )
 
  950    const FaceNeighbors &neighborhood = mFacesNeighborhood.at( index );
 
  952    for ( 
int i = 0; i < neighborhood.count(); ++i )
 
  954      int neighborIndex = neighborhood.at( i );
 
  955      if ( neighborIndex == -1 )
 
  958      int degree = faceDegrees.at( neighborIndex );
 
  959      if ( neighbors.isEmpty() )
 
  960        neighbors.append( neighborIndex );
 
  963        QList<int>::Iterator it = neighbors.begin();
 
  964        while ( it != neighbors.end() )
 
  966          if ( degree <= faceDegrees.at( *it ) )
 
  968            neighbors.insert( it, neighborIndex );
 
  973        if ( it == neighbors.end() )
 
  974          neighbors.append( neighborIndex );
 
  979  while ( newIndex < mMesh->faceCount() )
 
  981    if ( oldToNewIndex[currentFace] == -1 )
 
  982      oldToNewIndex[currentFace] = newIndex++;
 
  984    QList<int> neighbors;
 
  985    sortedNeighbor( neighbors, currentFace );
 
  987    for ( 
const int i : std::as_const( neighbors ) )
 
  988      if ( oldToNewIndex.at( i ) == -1 && nonThreadedFaces.contains( i ) )
 
  991        nonThreadedFaces.remove( i );
 
  994    if ( queue.isEmpty() )
 
  996      if ( nonThreadedFaces.isEmpty() && newIndex < mMesh->faceCount() )
 
  999      const QList<int> remainingFace( nonThreadedFaces.constBegin(), nonThreadedFaces.constEnd() );
 
 1000      int minRemainingDegree = std::numeric_limits<int>::max();
 
 1001      int minRemainingFace = -1;
 
 1002      for ( 
const int i : remainingFace )
 
 1004        int degree = faceDegrees.at( i );
 
 1005        if ( degree < minRemainingDegree )
 
 1007          minRemainingDegree = degree;
 
 1008          minRemainingFace = i;
 
 1011      currentFace = minRemainingFace;
 
 1012      nonThreadedFaces.remove( currentFace );
 
 1016      currentFace = queue.dequeue();
 
 1031  return mFacesToRemove;
 
 
 1036  return mFaceIndexesToRemove;
 
 
 1041  return mVerticesToAdd;
 
 
 1046  return mChangeCoordinateVerticesIndexes;
 
 
 1056  return mNewXYValues;
 
 
 1061  return mOldXYValues;
 
 
 1066  return mNativeFacesIndexesGeometryChanged;
 
 
 1071  return ( mFaceIndexesToRemove.isEmpty() &&
 
 1072           mFacesToAdd.isEmpty() &&
 
 1073           mFacesNeighborhoodToAdd.isEmpty() &&
 
 1074           mFacesToRemove.isEmpty() &&
 
 1075           mFacesNeighborhoodToRemove.isEmpty() &&
 
 1076           mNeighborhoodChanges.isEmpty() &&
 
 1077           mVerticesToAdd.isEmpty() &&
 
 1078           mVertexToFaceToAdd.isEmpty() &&
 
 1079           mVerticesToRemoveIndexes.isEmpty() &&
 
 1080           mRemovedVertices.isEmpty() &&
 
 1081           mVerticesToFaceRemoved.isEmpty() &&
 
 1082           mVerticesToFaceChanges.isEmpty() &&
 
 1083           mChangeCoordinateVerticesIndexes.isEmpty() &&
 
 1084           mNewZValues.isEmpty() &&
 
 1085           mOldZValues.isEmpty() &&
 
 1086           mNewXYValues.isEmpty() &&
 
 1087           mOldXYValues.isEmpty() &&
 
 1088           mNativeFacesIndexesGeometryChanged.isEmpty() );
 
 
 1093  return mVerticesToRemoveIndexes;
 
 
 1096int QgsTopologicalMesh::Changes::addedFaceIndexInMesh( 
int internalIndex )
 const 
 1098  if ( internalIndex == -1 )
 
 1101  return internalIndex + mAddedFacesFirstIndex;
 
 1104int QgsTopologicalMesh::Changes::removedFaceIndexInMesh( 
int internalIndex )
 const 
 1106  if ( internalIndex == -1 )
 
 1109  return mFaceIndexesToRemove.at( internalIndex );
 
 1114  mAddedFacesFirstIndex = 0;
 
 1115  mFaceIndexesToRemove.clear();
 
 1116  mFacesToAdd.clear();
 
 1117  mFacesNeighborhoodToAdd.clear();
 
 1118  mFacesToRemove.clear();
 
 1119  mFacesNeighborhoodToRemove.clear();
 
 1120  mNeighborhoodChanges.clear();
 
 1122  mVerticesToAdd.clear();
 
 1123  mVertexToFaceToAdd.clear();
 
 1124  mVerticesToRemoveIndexes.clear();
 
 1125  mRemovedVertices.clear();
 
 1126  mVerticesToFaceRemoved.clear();
 
 1127  mVerticesToFaceChanges.clear();
 
 1129  mChangeCoordinateVerticesIndexes.clear();
 
 1130  mNewZValues.clear();
 
 1131  mOldZValues.clear();
 
 1132  mNewXYValues.clear();
 
 1133  mOldXYValues.clear();
 
 1134  mNativeFacesIndexesGeometryChanged.clear();
 
 
 1144  mVertexToFace.append( -1 );
 
 1145  referenceAsFreeVertex( mMesh->
vertices.count() - 1 );
 
 
 1151static double vertexPolygonOrientation( 
const QgsMesh &
mesh, 
const QList<int> &vertexIndexes )
 
 1153  if ( vertexIndexes.count() < 3 )
 
 1156  int hullDomainVertexPos = -1;
 
 1157  double xMin = std::numeric_limits<double>::max();
 
 1158  double yMin = std::numeric_limits<double>::max();
 
 1159  for ( 
int i = 0; i < vertexIndexes.count(); ++i )
 
 1162    if ( xMin >= vertex.
x() && yMin > vertex.
y() )
 
 1164      hullDomainVertexPos = i;
 
 1170  if ( hullDomainVertexPos >= 0 )
 
 1172    int iv1 = vertexIndexes.at( ( hullDomainVertexPos - 1 + vertexIndexes.count() ) % vertexIndexes.count() );
 
 1173    int iv2 = vertexIndexes.at( ( hullDomainVertexPos + 1 ) % vertexIndexes.count() );
 
 1174    int ivc = vertexIndexes.at( ( hullDomainVertexPos ) );
 
 1175    double cp = crossProduct( ivc, iv1, iv2, 
mesh );
 
 1184  if ( vertexIndex >= mVertexToFace.count() )
 
 1187  if ( mVertexToFace.at( vertexIndex ) == -1 ) 
 
 1193    dereferenceAsFreeVertex( vertexIndex );
 
 1201  QList<int> boundariesVertexIndex;
 
 1202  QList<int> associateFaceToBoundaries;
 
 1203  QList<int> removedFacesIndexes;
 
 1204  QSet<int> boundaryInGlobalMesh;
 
 1210    Q_ASSERT( !mMesh->
vertices.at( boundariesVertexIndex.last() ).isEmpty() );
 
 1212    associateFaceToBoundaries.append( mFacesNeighborhood.at( circulator.
currentFaceIndex() ).at(
 
 1213                                        vertexPositionInFace( boundariesVertexIndex.last(), currentFace ) ) );
 
 1215    if ( currentFace.count() > 3 ) 
 
 1217      int posInface = vertexPositionInFace( vertexIndex, currentFace );
 
 1218      for ( 
int i = 2; i < currentFace.count() - 1; ++i )
 
 1220        boundariesVertexIndex.append( currentFace.at( ( posInface + i ) % currentFace.count() ) );
 
 1221        Q_ASSERT( !mMesh->
vertices.at( boundariesVertexIndex.last() ).isEmpty() );
 
 1222        associateFaceToBoundaries.append( mFacesNeighborhood.at( circulator.
currentFaceIndex() ).at(
 
 1223                                            vertexPositionInFace( boundariesVertexIndex.last(), currentFace ) ) );
 
 1229  bool boundaryFill = 
false;
 
 1232    boundaryFill = 
true;
 
 1236    boundariesVertexIndex.append( lastVertexIndex );
 
 1245      boundaryFill = 
false; 
 
 1248      associateFaceToBoundaries.append( -1 );
 
 1250    for ( 
const int index : std::as_const( boundariesVertexIndex ) )
 
 1253        boundaryInGlobalMesh.insert( index );
 
 1257  int currentVertexToFace = mVertexToFace.at( vertexIndex );
 
 1261  QList<QList<int>> holes;
 
 1262  QList<QList<int>> associateMeshFacesToHoles;
 
 1264  bool cancelOperation = 
false;
 
 1272    int finalPos = boundariesVertexIndex.count() - 1;
 
 1273    QList<int> uncoveredVertex;
 
 1275    QList<int> partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
 
 1276    QList<int> associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
 
 1277    while ( startPos < finalPos && !partToCheck.isEmpty() )
 
 1280      int secondPos = partToCheck.count() - 1;
 
 1281      const QgsPoint &closingSegmentExtremety1 = mMesh->
vertex( partToCheck.at( 0 ) );
 
 1282      const QgsPoint &closingSegmentExtremety2 = mMesh->
vertex( partToCheck.last() );
 
 1283      bool isEdgeIntersect = 
false;
 
 1284      for ( 
int i = 1; i < secondPos - 1; ++i )
 
 1288        bool isLineIntersection;
 
 1291        if ( isEdgeIntersect )
 
 1295      int index = partToCheck.at( 0 );
 
 1296      if ( boundaryInGlobalMesh.contains( index ) && index != boundariesVertexIndex.at( 0 ) )
 
 1298        cancelOperation = 
true;
 
 1304      if ( isEdgeIntersect || vertexPolygonOrientation( *mMesh, partToCheck ) >= 0 )
 
 1306        partToCheck.removeLast();
 
 1307        associateFacePart.removeAt( associateFacePart.count() - 2 );
 
 1308        if ( partToCheck.count() == 1 )
 
 1310          uncoveredVertex.append( index );
 
 1311          startPos = startPos + 1;
 
 1312          partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
 
 1313          associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
 
 1319        holes.append( partToCheck );
 
 1320        associateMeshFacesToHoles.append( associateFacePart );
 
 1322        startPos = startPos + partToCheck.count() - 1;
 
 1323        uncoveredVertex.append( partToCheck.at( 0 ) );
 
 1324        partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
 
 1325        associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
 
 1331    holes.append( boundariesVertexIndex );
 
 1332    associateMeshFacesToHoles.append( associateFaceToBoundaries );
 
 1335  if ( cancelOperation )
 
 1341  Q_ASSERT( holes.count() == associateMeshFacesToHoles.count() );
 
 1347  dereferenceAsFreeVertex( vertexIndex );
 
 1349  mVertexToFace[vertexIndex] = -1;
 
 1352  for ( 
int h = 0; h < holes.count(); ++h )
 
 1354    const QList<int> &holeVertices = holes.at( h );
 
 1355    const QList<int> &associateMeshFacesToHole = associateMeshFacesToHoles.at( h );
 
 1356    QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
 
 1357    std::vector<p2t::Point *> holeToFill( holeVertices.count() );
 
 1360      for ( 
int i = 0; i < holeVertices.count(); ++i )
 
 1363        holeToFill[i] = 
new p2t::Point( vertex.
x(), vertex.
y() );
 
 1364        mapPoly2TriPointToVertex.insert( holeToFill[i], holeVertices.at( i ) );
 
 1367      std::unique_ptr<p2t::CDT> cdt( 
new p2t::CDT( holeToFill ) );
 
 1370      std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
 
 1371      QVector<QgsMeshFace> newFaces( triangles.size() );
 
 1372      for ( 
size_t i = 0; i < triangles.size(); ++i )
 
 1376        for ( 
int j = 0; j < 3; j++ )
 
 1378          int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
 
 1379          if ( vertInd == -1 )
 
 1380            throw std::exception();
 
 1381          Q_ASSERT( !mMesh->
vertices.at( vertInd ).isEmpty() );
 
 1389        throw std::exception();
 
 1390      int newFaceIndexStartIndex = mMesh->
faceCount();
 
 1397      const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
 
 1398      for ( 
const int vtc : verticesToFaceToChange )
 
 1399        if ( mVertexToFace.at( vtc ) == -1 )
 
 1401              mVertexToFace.at( vtc ),
 
 1402              addChanges.addedFaceIndexInMesh( topologicalFaces.mVerticesToFace.values( vtc ).first() ) } );
 
 1406      for ( 
int i = 0; i < topologicalFaces.mFaces.count(); ++i )
 
 1408        FaceNeighbors &faceNeighbors = addChanges.mFacesNeighborhoodToAdd[i];
 
 1409        faceNeighbors = topologicalFaces.mFacesNeighborhood.at( i );
 
 1410        for ( 
int n = 0; n < faceNeighbors.count(); ++n )
 
 1412          if ( faceNeighbors.at( n ) != -1 )
 
 1413            faceNeighbors[n] += newFaceIndexStartIndex; 
 
 1418      for ( 
int i = 0 ; i < holeVertices.count(); ++i )
 
 1420        int vertexHoleIndex = holeVertices.at( i );
 
 1421        int meshFaceBoundaryIndex = associateMeshFacesToHole.at( i );
 
 1426        int newFaceBoundaryIndexInMesh = circulator.
currentFaceIndex() + newFaceIndexStartIndex;
 
 1428        int positionInNewFaces = vertexPositionInFace( vertexHoleIndex, newFace );
 
 1430        if ( meshFaceBoundaryIndex != -1 )
 
 1433          int positionInMeshFaceBoundary = vertexPositionInFace( *mMesh, vertexHoleIndex, meshFaceBoundaryIndex );
 
 1434          positionInMeshFaceBoundary = ( positionInMeshFaceBoundary - 1 + meshFace.count() ) % meshFace.count(); 
 
 1436          addChanges.mNeighborhoodChanges.append( {meshFaceBoundaryIndex, positionInMeshFaceBoundary, -1, newFaceBoundaryIndexInMesh} );
 
 1439        addChanges.mFacesNeighborhoodToAdd[newFaceBoundaryLocalIndex][positionInNewFaces] = meshFaceBoundaryIndex;
 
 1444      changes.
mFacesToAdd.append( addChanges.mFacesToAdd );
 
 1447      for ( 
const std::array<int, 4> &neighborChangeToAdd : std::as_const( addChanges.mNeighborhoodChanges ) )
 
 1449        bool merged = 
false;
 
 1452          if ( existingNeighborChange.at( 0 ) == neighborChangeToAdd.at( 0 ) &&
 
 1453               existingNeighborChange.at( 1 ) == neighborChangeToAdd.at( 1 ) )
 
 1456            Q_ASSERT( existingNeighborChange.at( 3 ) == neighborChangeToAdd.at( 2 ) );
 
 1457            existingNeighborChange[3] = neighborChangeToAdd.at( 3 );
 
 1464      for ( 
const std::array<int, 3> &verticesToFaceToAdd : std::as_const( addChanges.mVerticesToFaceChanges ) )
 
 1466        bool merged = 
false;
 
 1469          if ( existingVerticesToFace.at( 0 ) == verticesToFaceToAdd.at( 0 ) )
 
 1472            Q_ASSERT( existingVerticesToFace.at( 2 ) == verticesToFaceToAdd.at( 1 ) );
 
 1473            existingVerticesToFace[2] = verticesToFaceToAdd.at( 2 );
 
 1480      qDeleteAll( holeToFill );
 
 1484      qDeleteAll( holeToFill );
 
 1488  changes.mAddedFacesFirstIndex = oldFacesCount;
 
 1492  changes.mAddedFacesFirstIndex = oldFacesCount;
 
 
 1499  QSet<int> facesIndex;
 
 1501  for ( 
int vertexIndex : vertices )
 
 1504    facesIndex.unite( QSet< int >( faces.begin(), faces.end() ) );
 
 1511  for ( 
int vertexIndex : vertices )
 
 1513    int currentVertexToFace = mVertexToFace.at( vertexIndex );
 
 1519    dereferenceAsFreeVertex( vertexIndex );
 
 1521    mVertexToFace[vertexIndex] = -1;
 
 
 1529  QList<int> boundariesToCheckClockwiseInNewFaces = topologicFaces.mBoundaries;
 
 1530  QList<std::array<int, 2>> boundariesToCheckCounterClockwiseInNewFaces; 
 
 1531  QList<int> uniqueSharedVertexBoundary;
 
 1539  while ( !boundariesToCheckClockwiseInNewFaces.isEmpty() )
 
 1541    int boundary = boundariesToCheckClockwiseInNewFaces.takeLast();
 
 1543    const QList<int> &linkedFaces = topologicFaces.mVerticesToFace.values( boundary );
 
 1545    for ( 
int const linkedFace : linkedFaces )
 
 1549      if ( mVertexToFace.at( boundary ) == -1 )
 
 1555      if ( !newFacescirculator.
isValid() )
 
 1569      if ( oppositeVertexCCWInMesh == oppositeVertexInNewFaces ) 
 
 1575        int faceSize = newFaceOnBoundary.size();
 
 1576        int posInNewFace = vertexPositionInFace( boundary, newFaceOnBoundary );
 
 1577        int previousVertexIndex = ( posInNewFace + faceSize - 1 ) % faceSize;
 
 1578        if ( newFaceOnBoundary.at( previousVertexIndex ) == oppositeVertexCCWInMesh )
 
 1586      if ( oppositeVertexCWInMesh == oppositeVertexInNewFaces )
 
 1590      boundariesToCheckCounterClockwiseInNewFaces.append( {boundary, linkedFace} );
 
 1595  while ( !boundariesToCheckCounterClockwiseInNewFaces.isEmpty() )
 
 1597    std::array<int, 2> boundaryLinkedface = boundariesToCheckCounterClockwiseInNewFaces.takeLast();
 
 1598    int boundary = boundaryLinkedface.at( 0 );
 
 1599    int linkedFace = boundaryLinkedface.at( 1 );
 
 1614    if ( oppositeVertexCWInMesh == oppositeVertexInNewFaces ) 
 
 1621    if ( oppositeVertexCCWInMesh == oppositeVertexInNewFaces )
 
 1624    uniqueSharedVertexBoundary.append( boundary );
 
 1627  if ( !uniqueSharedVertexBoundary.isEmpty() )
 
 1631  QSet<int> boundaryVertices( topologicFaces.mBoundaries.constBegin(), topologicFaces.mBoundaries.constEnd() );
 
 1632  for ( 
const QgsMeshFace &newFace : std::as_const( topologicFaces.mFaces ) )
 
 1634    for ( 
const int vertexIndex : newFace )
 
 1636      if ( boundaryVertices.contains( vertexIndex ) )
 
 1638      if ( mVertexToFace.at( vertexIndex ) != -1 )
 
 
 1649  mFacesNeighborhood.clear();
 
 1650  mVerticesToFace.clear();
 
 1651  mBoundaries.clear();
 
 
 1656  return mFacesNeighborhood;
 
 
 1661  if ( mVerticesToFace.contains( vertexIndex ) )
 
 1662    return mVerticesToFace.values( vertexIndex ).at( 0 );
 
 
 1670  topologicMesh.mMesh = 
mesh;
 
 1671  topologicMesh.mVertexToFace = QVector<int>( 
mesh->
vertexCount(), -1 );
 
 1672  topologicMesh.mMaximumVerticesPerFace = maxVerticesPerFace;
 
 1679    if ( maxVerticesPerFace != 0 && 
mesh->
face( i ).count() > maxVerticesPerFace )
 
 1697    topologicMesh.mFacesNeighborhood = subMesh.mFacesNeighborhood;
 
 1699    for ( 
int i = 0; i < topologicMesh.mMesh->
vertexCount(); ++i )
 
 1701      if ( topologicMesh.mVertexToFace.at( i ) == -1 )
 
 1702        topologicMesh.mFreeVertices.insert( i );
 
 1706  return topologicMesh;
 
 
 1711  return createTopologicalFaces( faces, 
nullptr, error, uniqueSharedVertexAllowed );
 
 
 1716  const QVector<QgsMeshFace> &faces,
 
 1717  QVector<int> *globalVertexToFace,
 
 1719  bool allowUniqueSharedVertex )
 
 1721  int facesCount = faces.count();
 
 1722  QVector<FaceNeighbors> faceTopologies;
 
 1723  QMultiHash<int, int> verticesToFace;
 
 1726  TopologicalFaces ret;
 
 1730  QMap<int, QMap<int, int>> verticesToNeighbor;
 
 1732  for ( 
int faceIndex = 0; faceIndex < facesCount; ++faceIndex )
 
 1735    int faceSize = face.count();
 
 1737    for ( 
int i = 0; i < faceSize; ++i )
 
 1739      int v1 = face[i % faceSize];
 
 1740      int v2 = face[( i + 1 ) % faceSize];
 
 1741      if ( verticesToNeighbor[v2].contains( v1 ) )
 
 1747        verticesToNeighbor[v2].insert( v1, faceIndex );
 
 1751  faceTopologies = QVector<FaceNeighbors>( faces.count() );
 
 1753  QSet<int> boundaryVertices;
 
 1755  for ( 
int faceIndex = 0; faceIndex < facesCount; ++faceIndex )
 
 1758    int faceSize = face.size();
 
 1760    faceTopology.resize( faceSize );
 
 1762    for ( 
int i = 0; i < faceSize; ++i )
 
 1764      int v1 = face.at( i );
 
 1765      int v2 = face.at( ( i + 1 ) % faceSize );
 
 1767      if ( globalVertexToFace )
 
 1769        if ( ( *globalVertexToFace )[v1] == -1 )
 
 1770          ( *globalVertexToFace )[v1] = faceIndex ;
 
 1774        if ( allowUniqueSharedVertex || !verticesToFace.contains( v1 ) )
 
 1775          verticesToFace.insert( v1, faceIndex ) ;
 
 1778      QMap<int, int> &edges = verticesToNeighbor[v1];
 
 1779      if ( edges.contains( v2 ) )
 
 1780        faceTopology[i] = edges.value( v2 );
 
 1783        faceTopology[i] = -1;
 
 1785        if ( !allowUniqueSharedVertex )
 
 1787          if ( boundaryVertices.contains( v1 ) )
 
 1793        boundaryVertices.insert( v1 );
 
 1799  ret.mFacesNeighborhood = faceTopologies;
 
 1800  ret.mBoundaries = boundaryVertices.values();
 
 1801  ret.mVerticesToFace = verticesToFace;
 
 1807  return mFacesNeighborhood.at( faceIndex );
 
 
 1819  QSet<int> removedFaces( facesIndexes.begin(), facesIndexes.end() );
 
 1820  QSet<int> concernedFaces = concernedFacesBy( facesIndexes );
 
 1822  for ( 
const int f : std::as_const( removedFaces ) )
 
 1823    concernedFaces.remove( f );
 
 1825  QVector<QgsMeshFace> remainingFaces;
 
 1826  remainingFaces.reserve( concernedFaces.count() );
 
 1827  for ( 
const int f : std::as_const( concernedFaces ) )
 
 1828    remainingFaces.append( mMesh->
face( f ) );
 
 1831  createTopologicalFaces( remainingFaces, 
nullptr, error, 
false );
 
 
 1843  QSet<int> indexSet( facesIndexesToRemove.begin(), facesIndexesToRemove.end() );
 
 1844  QSet<int> threatedVertex;
 
 1846  for ( 
int i = 0; i < facesIndexesToRemove.count(); ++i )
 
 1848    const int faceIndex = facesIndexesToRemove.at( i );
 
 1851    const FaceNeighbors &neighborhood = mFacesNeighborhood.at( faceIndex );
 
 1853    for ( 
int j = 0; j < face.count(); ++j )
 
 1856      int neighborIndex = neighborhood.at( j );
 
 1857      if ( neighborIndex != -1 && !indexSet.contains( neighborIndex ) )
 
 1859        int positionInNeighbor = mFacesNeighborhood.at( neighborIndex ).indexOf( faceIndex );
 
 1864      int vertexIndex = face.at( j );
 
 1865      if ( !threatedVertex.contains( vertexIndex ) && indexSet.contains( mVertexToFace.at( vertexIndex ) ) )
 
 1867        int oldValue = mVertexToFace.at( vertexIndex );
 
 1870        if ( neighborIndex != -1 && !indexSet.contains( neighborIndex ) ) 
 
 1871          refValue = neighborIndex;
 
 1875          aroundFaces.removeOne( faceIndex );
 
 1876          if ( !aroundFaces.isEmpty() )
 
 1878            while ( !aroundFaces.isEmpty() && refValue == -1 )
 
 1880              if ( !indexSet.contains( aroundFaces.first() ) )
 
 1881                refValue = aroundFaces.first();
 
 1883                aroundFaces.removeFirst();
 
 1888        threatedVertex.insert( vertexIndex );
 
 
 1898bool QgsTopologicalMesh::eitherSideFacesAndVertices( 
int vertexIndex1,
 
 1902    int &neighborVertex1InFace1,
 
 1903    int &neighborVertex1InFace2,
 
 1904    int &neighborVertex2inFace1,
 
 1905    int &neighborVertex2inFace2 )
 const 
 1947  int oppositeVertexFace1;
 
 1948  int oppositeVertexFace2;
 
 1949  int supposedOppositeVertexFace1;
 
 1950  int supposedoppositeVertexFace2;
 
 1952  bool result = eitherSideFacesAndVertices(
 
 1957                  oppositeVertexFace1,
 
 1958                  supposedoppositeVertexFace2,
 
 1959                  supposedOppositeVertexFace1,
 
 1960                  oppositeVertexFace2 );
 
 1965       oppositeVertexFace1 < 0 ||
 
 1966       oppositeVertexFace2 < 0 ||
 
 1967       supposedOppositeVertexFace1 != oppositeVertexFace1 ||
 
 1968       supposedoppositeVertexFace2 != oppositeVertexFace2 )
 
 1975  if ( face1.count() != 3 || face2.count() != 3 )
 
 1978  double crossProduct1 = crossProduct( vertexIndex1, oppositeVertexFace1, oppositeVertexFace2, *mMesh );
 
 1979  double crossProduct2 = crossProduct( vertexIndex2, oppositeVertexFace1, oppositeVertexFace2, *mMesh );
 
 1981  return crossProduct1 * crossProduct2 < 0;
 
 
 1988  int oppositeVertexFace1;
 
 1989  int oppositeVertexFace2;
 
 1990  int supposedOppositeVertexFace1;
 
 1991  int supposedoppositeVertexFace2;
 
 1993  bool result = eitherSideFacesAndVertices(
 
 1998                  oppositeVertexFace1,
 
 1999                  supposedoppositeVertexFace2,
 
 2000                  supposedOppositeVertexFace1,
 
 2001                  oppositeVertexFace2 );
 
 2006       oppositeVertexFace1 < 0 ||
 
 2007       oppositeVertexFace2 < 0 ||
 
 2008       supposedOppositeVertexFace1 != oppositeVertexFace1 ||
 
 2009       supposedoppositeVertexFace2 != oppositeVertexFace2 )
 
 2018  Q_ASSERT( face1.count() == 3 );
 
 2019  Q_ASSERT( face2.count() == 3 );
 
 2021  int pos1 = vertexPositionInFace( vertexIndex1, face1 );
 
 2022  int pos2 = vertexPositionInFace( vertexIndex2, face2 );
 
 2024  int neighborFace1 = mFacesNeighborhood.at( faceIndex1 ).at( pos1 );
 
 2025  int posInNeighbor1 = vertexPositionInFace( *mMesh, oppositeVertexFace1, neighborFace1 );
 
 2026  int neighborFace2 = mFacesNeighborhood.at( faceIndex1 ).at( ( pos1 + 1 ) % 3 );
 
 2027  int posInNeighbor2 = vertexPositionInFace( *mMesh, vertexIndex2, neighborFace2 );
 
 2028  int neighborFace3 = mFacesNeighborhood.at( faceIndex2 ).at( pos2 );
 
 2029  int posInNeighbor3 = vertexPositionInFace( *mMesh, oppositeVertexFace2, neighborFace3 );
 
 2030  int neighborFace4 = mFacesNeighborhood.at( faceIndex2 ).at( ( pos2 + 1 ) % 3 );
 
 2031  int posInNeighbor4 = vertexPositionInFace( *mMesh, vertexIndex1, neighborFace4 );
 
 2041  changes.
mFacesToAdd.append( {oppositeVertexFace1, oppositeVertexFace2, vertexIndex1} );
 
 2042  changes.
mFacesToAdd.append( {oppositeVertexFace2, oppositeVertexFace1, vertexIndex2} );
 
 2044                                          mFacesNeighborhood.at( faceIndex2 ).at( ( pos2 + 1 ) % 3 ),
 
 2045                                          mFacesNeighborhood.at( faceIndex1 ).at( pos1 )} );
 
 2047                                          mFacesNeighborhood.at( faceIndex1 ).at( ( pos1 + 1 ) % 3 ),
 
 2048                                          mFacesNeighborhood.at( faceIndex2 ).at( pos2 )} );
 
 2050  if ( neighborFace1 >= 0 )
 
 2051    changes.
mNeighborhoodChanges.append( {neighborFace1, posInNeighbor1, faceIndex1, startIndex} );
 
 2052  if ( neighborFace2 >= 0 )
 
 2053    changes.
mNeighborhoodChanges.append( {neighborFace2, posInNeighbor2, faceIndex1, startIndex + 1} );
 
 2054  if ( neighborFace3 >= 0 )
 
 2055    changes.
mNeighborhoodChanges.append( {neighborFace3, posInNeighbor3, faceIndex2, startIndex + 1} );
 
 2056  if ( neighborFace4 >= 0 )
 
 2057    changes.
mNeighborhoodChanges.append( {neighborFace4, posInNeighbor4, faceIndex2, startIndex} );
 
 2060  if ( mVertexToFace.at( vertexIndex1 ) == faceIndex1 || mVertexToFace.at( vertexIndex1 ) == faceIndex2 )
 
 2062  if ( mVertexToFace.at( vertexIndex2 ) == faceIndex1 || mVertexToFace.at( vertexIndex2 ) == faceIndex2 )
 
 2063    changes.
mVerticesToFaceChanges.append( {vertexIndex2,  mVertexToFace.at( vertexIndex2 ), startIndex + 1} );
 
 2065  if ( mVertexToFace.at( oppositeVertexFace1 ) == faceIndex1 )
 
 2068  if ( mVertexToFace.at( oppositeVertexFace2 ) == faceIndex2 )
 
 
 2080  int neighborVertex1InFace1;
 
 2081  int neighborVertex1InFace2;
 
 2082  int neighborVertex2inFace1;
 
 2083  int neighborVertex2inFace2;
 
 2085  bool result = eitherSideFacesAndVertices(
 
 2090                  neighborVertex1InFace1,
 
 2091                  neighborVertex1InFace2,
 
 2092                  neighborVertex2inFace1,
 
 2093                  neighborVertex2inFace2 );
 
 2103  if ( face1.count() + face2.count() - 2 > mMaximumVerticesPerFace )
 
 2113  double crossProduct1 = crossProduct( vertexIndex1, neighborVertex1InFace1, neighborVertex1InFace2, *mMesh );
 
 2114  double crossProduct2 = crossProduct( vertexIndex2, neighborVertex2inFace1, neighborVertex2inFace2, *mMesh );
 
 2116  return crossProduct1 * crossProduct2 < 0;
 
 
 2123  int neighborVertex1InFace1;
 
 2124  int neighborVertex1InFace2;
 
 2125  int neighborVertex2inFace1;
 
 2126  int neighborVertex2inFace2;
 
 2128  bool result = eitherSideFacesAndVertices(
 
 2133                  neighborVertex1InFace1,
 
 2134                  neighborVertex1InFace2,
 
 2135                  neighborVertex2inFace1,
 
 2136                  neighborVertex2inFace2 );
 
 2147  int faceSize1 = face1.count();
 
 2148  int faceSize2 = face2.count();
 
 2150  int pos1 = vertexPositionInFace( vertexIndex1, face1 );
 
 2151  int pos2 = vertexPositionInFace( vertexIndex2, face2 );
 
 2164  for ( 
int i = 0; i < faceSize1 - 1; ++i )
 
 2166    int currentPos = ( pos1 + i ) % faceSize1;
 
 2167    newface.append( face1.at( currentPos ) ); 
 
 2169    int currentNeighbor = mFacesNeighborhood.at( faceIndex1 ).at( currentPos );
 
 2170    newNeighborhood.append( currentNeighbor );
 
 2172    if ( currentNeighbor != -1 )
 
 2174      int currentPosInNeighbor = vertexPositionInFace( *mMesh, face1.at( ( currentPos + 1 ) % faceSize1 ), currentNeighbor );
 
 2175      changes.
mNeighborhoodChanges.append( {currentNeighbor, currentPosInNeighbor, faceIndex1, startIndex} );
 
 2178  for ( 
int i = 0; i < faceSize2 - 1; ++i )
 
 2180    int currentPos = ( pos2 + i ) % faceSize2;
 
 2181    newface.append( face2.at( currentPos ) ); 
 
 2183    int currentNeighbor = mFacesNeighborhood.at( faceIndex2 ).at( currentPos );
 
 2184    newNeighborhood.append( currentNeighbor );
 
 2186    if ( currentNeighbor != -1 )
 
 2188      int currentPosInNeighbor = vertexPositionInFace( *mMesh, face2.at( ( currentPos + 1 ) % faceSize2 ), currentNeighbor );
 
 2189      changes.
mNeighborhoodChanges.append( {currentNeighbor, currentPosInNeighbor, faceIndex2, startIndex} );
 
 2193  for ( 
int i = 0; i < faceSize1; ++i )
 
 2194    if ( mVertexToFace.at( face1.at( i ) ) == faceIndex1 )
 
 2197  for ( 
int i = 0; i < faceSize2; ++i )
 
 2198    if ( mVertexToFace.at( face2.at( i ) ) == faceIndex2 )
 
 
 2213  return face.count() == 4;
 
 
 2220  int faceSize = face.count();
 
 2222  Q_ASSERT( faceSize == 4 );
 
 2224  double maxAngle = 0;
 
 2225  int splitVertexPos = -1;
 
 2226  for ( 
int i = 0; i < faceSize; ++i )
 
 2228    QgsVector vect1( mMesh->
vertex( face.at( i ) ) - mMesh->
vertex( face.at( ( i + 1 ) % faceSize ) ) );
 
 2229    QgsVector vect2( mMesh->
vertex( face.at( ( i + 2 ) % faceSize ) ) - mMesh->
vertex( face.at( ( i + 1 ) % faceSize ) ) );
 
 2231    double angle = std::abs( vect1.
angle( vect2 ) );
 
 2232    angle = std::min( angle, 2.0 * M_PI - angle );
 
 2233    if ( angle > maxAngle )
 
 2236      splitVertexPos = ( i + 1 ) % faceSize;
 
 2241  if ( splitVertexPos == -1 )
 
 2244  const QgsMeshFace newFace1 = {face.at( splitVertexPos ),
 
 2245                                face.at( ( splitVertexPos + 1 ) % faceSize ),
 
 2246                                face.at( ( splitVertexPos + 2 ) % faceSize )
 
 2249  const QgsMeshFace newFace2 = {face.at( splitVertexPos ),
 
 2250                                face.at( ( splitVertexPos + 2 ) % faceSize ),
 
 2251                                face.at( ( splitVertexPos + 3 ) % faceSize )
 
 2254  QVector<int> neighborIndex( faceSize );
 
 2255  QVector<int> posInNeighbor( faceSize );
 
 2257  for ( 
int i = 0; i < faceSize; ++i )
 
 2259    neighborIndex[i] = mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + i ) % faceSize );
 
 2260    posInNeighbor[i] = vertexPositionInFace( *mMesh,  face.at( ( splitVertexPos + i + 1 ) % faceSize ), neighborIndex[i] );
 
 2272                                          mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 1 ) % faceSize ),
 
 2275                                          mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 2 ) % faceSize ),
 
 2276                                          mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 3 ) % faceSize )} );
 
 2278  for ( 
int i = 0; i < faceSize; ++i )
 
 2280    if ( neighborIndex[i] >= 0 )
 
 2281      changes.
mNeighborhoodChanges.append( {neighborIndex[i], posInNeighbor[i], faceIndex, startIndex + int( i / 2 )} );
 
 2283    int vertexIndex = face.at( ( splitVertexPos + i ) % faceSize );
 
 2284    if ( mVertexToFace.at( vertexIndex ) == faceIndex )
 
 
 2301  mVertexToFace.append( -1 );
 
 2305  const FaceNeighbors includingFaceNeighborhood = mFacesNeighborhood.at( includingFaceIndex );
 
 2306  int includingFaceSize = includingFace.count();
 
 2308  for ( 
int i = 0; i < includingFaceSize; ++i )
 
 2313    face[1] = includingFace.at( i );
 
 2314    face[2] = includingFace.at( ( i + 1 ) % includingFaceSize );
 
 2315    mMesh->
faces.append( face );
 
 2318    int currentVertexIndex = includingFace.at( i );
 
 2319    if ( mVertexToFace.at( currentVertexIndex ) == includingFaceIndex )
 
 2321      int newFaceIndex = mMesh->
faceCount() - 1;
 
 2322      mVertexToFace[currentVertexIndex] = newFaceIndex;
 
 2326    int includingFaceNeighbor = includingFaceNeighborhood.at( i );
 
 2330      includingFaceNeighbor,
 
 2333    mFacesNeighborhood.append( neighbors );
 
 2336    if ( includingFaceNeighbor != -1 )
 
 2338      int indexInNeighbor = vertexPositionInFace( *mMesh, includingFace.at( ( i + 1 ) % includingFaceSize ), includingFaceNeighbor );
 
 2339      int oldValue = mFacesNeighborhood[includingFaceNeighbor][indexInNeighbor];
 
 2351  mVertexToFace[mVertexToFace.count() - 1] = mMesh->
faceCount() - 1;
 
 
 2366  int newVertexPositionInFace1 = position + 1;
 
 2368  auto triangulate = [
this, &changes]( 
int removedFaceIndex, 
const QgsMeshVertex & newVertex, 
int newVertexPosition, QVector<int> &edgeFacesIndexes )->
bool 
 2374    const int addedVertexIndex = mMesh->
vertexCount();
 
 2377    int localStartIndex = changes.
mFacesToAdd.count();
 
 2379    QVector<int> newBoundary = initialFace;
 
 2380    newBoundary.insert( newVertexPosition, addedVertexIndex );
 
 2384      QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
 
 2385      std::vector<p2t::Point *> faceToFill( newBoundary.count() );
 
 2386      for ( 
int i = 0; i < newBoundary.count(); ++i )
 
 2390        if ( newBoundary.at( i ) == addedVertexIndex )
 
 2393          vert = mMesh->
vertex( newBoundary.at( i ) );
 
 2395        faceToFill[i] = 
new p2t::Point( vert.
x(), vert.
y() );
 
 2396        mapPoly2TriPointToVertex.insert( faceToFill[i], newBoundary.at( i ) );
 
 2399      std::unique_ptr<p2t::CDT> cdt( 
new p2t::CDT( faceToFill ) );
 
 2401      std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
 
 2402      QVector<QgsMeshFace> newFaces( triangles.size() );
 
 2403      for ( 
size_t i = 0; i < triangles.size(); ++i )
 
 2407        for ( 
int j = 0; j < 3; j++ )
 
 2409          int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
 
 2410          if ( vertInd == -1 )
 
 2411            throw std::exception();
 
 2419        throw std::exception();
 
 2425      const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
 
 2426      for ( 
const int vtc : verticesToFaceToChange )
 
 2427        if ( vtc != addedVertexIndex && mVertexToFace.at( vtc ) == removedFaceIndex )
 
 2432          topologicalFaces.
vertexToFace( vtc ) + faceStartGlobalIndex
 
 2436      for ( 
int i = 0; i < topologicalFaces.mFaces.count(); ++i )
 
 2439        for ( 
int n = 0; n < faceNeighbors.count(); ++n )
 
 2441          if ( faceNeighbors.at( n ) != -1 )
 
 2442            faceNeighbors[n] += faceStartGlobalIndex; 
 
 2446      edgeFacesIndexes.resize( 2 );
 
 2448      for ( 
int i = 0 ; i < newBoundary.count(); ++i )
 
 2450        int vertexIndex = newBoundary.at( i );
 
 2453        int newFaceBoundaryLocalIndex = localStartIndex + circulator.
currentFaceIndex();
 
 2455        int newFaceBoundaryIndexInMesh = faceStartGlobalIndex;
 
 2457        int meshFaceBoundaryIndex;
 
 2458        if ( i == newVertexPosition )
 
 2460          meshFaceBoundaryIndex = -1; 
 
 2461          edgeFacesIndexes[0] =  newFaceBoundaryLocalIndex;
 
 2463        else if ( i == ( newVertexPosition + newBoundary.count() - 1 ) % newBoundary.count() )
 
 2465          meshFaceBoundaryIndex = -1; 
 
 2466          edgeFacesIndexes[1] =  newFaceBoundaryLocalIndex;
 
 2469          meshFaceBoundaryIndex = mFacesNeighborhood.at( removedFaceIndex ).at( vertexPositionInFace( vertexIndex, initialFace ) );
 
 2472        int positionInNewFaces = vertexPositionInFace( vertexIndex, newFace );
 
 2474        if ( meshFaceBoundaryIndex != -1 )
 
 2477          int positionInMeshFaceBoundary = vertexPositionInFace( *mMesh, vertexIndex, meshFaceBoundaryIndex );
 
 2478          positionInMeshFaceBoundary = ( positionInMeshFaceBoundary - 1 + meshFace.count() ) % meshFace.count(); 
 
 2481                                                positionInMeshFaceBoundary,
 
 2483                                                newFaceBoundaryIndexInMesh +
 
 2490      qDeleteAll( faceToFill );
 
 2500  QVector<int> edgeFacesIndexes;
 
 2501  if ( !triangulate( faceIndex, vertexToInsert, newVertexPositionInFace1, edgeFacesIndexes ) )
 
 2504  changes.mVertexToFaceToAdd.append( edgeFacesIndexes.at( 0 ) + changes.mAddedFacesFirstIndex );
 
 2509  int face2Index = mFacesNeighborhood.at( faceIndex ).at( position );
 
 2510  if ( face2Index != -1 )
 
 2513    int vertexPositionInFace2 = vertexPositionInFace( face1.at( position ), face2 );
 
 2514    QVector<int> edgeFacesIndexesFace2;
 
 2515    if ( !triangulate( face2Index, vertexToInsert, vertexPositionInFace2, edgeFacesIndexesFace2 ) )
 
 2519    const QgsMeshFace &firstFaceSide1 = changes.mFacesToAdd.at( edgeFacesIndexes.at( 0 ) );
 
 2520    int pos1InFaceSide1 = vertexPositionInFace( addedVertexIndex, firstFaceSide1 );
 
 2522    const QgsMeshFace &secondFaceSide1 = changes.mFacesToAdd.at( edgeFacesIndexes.at( 1 ) );
 
 2523    int pos2InFaceSide1 = vertexPositionInFace( addedVertexIndex, secondFaceSide1 );
 
 2524    pos2InFaceSide1 = ( pos2InFaceSide1 + secondFaceSide1.size() - 1 ) % secondFaceSide1.size();
 
 2526    const QgsMeshFace &firstFaceSide2 = changes.mFacesToAdd.at( edgeFacesIndexesFace2.at( 0 ) );
 
 2527    int pos1InFaceSide2 = vertexPositionInFace( addedVertexIndex, firstFaceSide2 );
 
 2529    const QgsMeshFace &secondFaceSide2 = changes.mFacesToAdd.at( edgeFacesIndexesFace2.at( 1 ) );
 
 2530    int pos2InFaceSide2 = vertexPositionInFace( addedVertexIndex, secondFaceSide2 );
 
 2531    pos2InFaceSide2 = ( pos2InFaceSide2 + secondFaceSide1.size() - 1 ) % secondFaceSide1.size();
 
 2533    changes.mFacesNeighborhoodToAdd[edgeFacesIndexes.at( 0 )][pos1InFaceSide1] = edgeFacesIndexesFace2.at( 1 ) + changes.mAddedFacesFirstIndex;
 
 2534    changes.mFacesNeighborhoodToAdd[edgeFacesIndexes.at( 1 )][pos2InFaceSide1] = edgeFacesIndexesFace2.at( 0 ) + changes.mAddedFacesFirstIndex;
 
 2535    changes.mFacesNeighborhoodToAdd[edgeFacesIndexesFace2.at( 0 )][pos1InFaceSide2] = edgeFacesIndexes.at( 1 ) + changes.mAddedFacesFirstIndex;
 
 2536    changes.mFacesNeighborhoodToAdd[edgeFacesIndexesFace2.at( 1 )][pos2InFaceSide2] = edgeFacesIndexes.at( 0 ) + changes.mAddedFacesFirstIndex;
 
 
 2545  Q_ASSERT( verticesIndexes.count() == newValues.count() );
 
 2548  changes.
mNewZValues.reserve( verticesIndexes.count() );
 
 2549  changes.
mOldZValues.reserve( verticesIndexes.count() );
 
 2550  for ( 
int i = 0; i < verticesIndexes.count(); ++i )
 
 
 2564  Q_ASSERT( verticesIndexes.count() == newValues.count() );
 
 2567  changes.
mNewXYValues.reserve( verticesIndexes.count() );
 
 2568  changes.
mOldXYValues.reserve( verticesIndexes.count() );
 
 2569  QSet<int> concernedFace;
 
 2570  for ( 
int i = 0; i < verticesIndexes.count(); ++i )
 
 2576    concernedFace.unite( QSet< int>( faces.begin(), faces.end() ) );
 
 
@ 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 bool segmentIntersection(const QgsPoint &p1, const QgsPoint &p2, const QgsPoint &q1, const QgsPoint &q2, QgsPoint &intersectionPoint, bool &isIntersection, double tolerance=1e-8, bool acceptImproperIntersection=false)
Compute the intersection between two segments.
 
Class that represents an error during mesh editing.
 
Qgis::MeshEditingErrorType errorType
 
Convenient class that turn around a vertex and provide information about faces and vertices.
 
bool isValid() const
Returns whether the vertex circulator is valid.
 
int turnClockwise() const
Turns counter clockwise around the vertex and returns the new current face, -1 if the circulator pass...
 
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...
 
int turnCounterClockwise() const
Turns counter clockwise around the vertex and returns the new current face, -1 if the circulator pass...
 
int currentFaceIndex() const
Returns the current face index, -1 if the circulator has passed a boundary or circulator is invalid.
 
bool goBoundaryClockwise() const
Sets the circulator on the boundary face turning clockwise, return false is there isn't boundary face...
 
QgsMeshFace currentFace() const
Returns the current face, empty face if the circulator pass a boundary or circulator is invalid.
 
QgsMeshVertexCirculator(const QgsTopologicalMesh &topologicalMesh, int vertexIndex)
Constructor with topologicalMesh and vertexIndex.
 
int oppositeVertexClockwise() const
Returns the opposite vertex of the current face and on the edge on the side turning clockwise.
 
int degree() const
Returns the degree of the vertex, that is the count of other vertices linked.
 
QList< int > facesAround() const
Returns all the faces indexes around the vertex.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
 
A class to represent a 2D point.
 
Point geometry type, with support for z-dimension and m-values.
 
bool isEmpty() const override
Returns true if the geometry is empty.
 
Class that contains topological differences between two states of a topological mesh,...
 
QList< int > mChangeCoordinateVerticesIndexes
 
QList< int > mVerticesToFaceRemoved
 
void clearChanges()
Clears all changes.
 
QVector< FaceNeighbors > mFacesNeighborhoodToRemove
 
QVector< QgsMeshFace > removedFaces() const
Returns the faces that are removed with this changes.
 
QList< QgsPointXY > mNewXYValues
 
QList< QgsMeshVertex > mRemovedVertices
 
QVector< QgsMeshVertex > addedVertices() const
Returns the added vertices with this changes.
 
QList< std::array< int, 4 > > mNeighborhoodChanges
 
bool isEmpty() const
Returns whether changes are empty, that there is nothing to change.
 
QList< int > mVerticesToRemoveIndexes
 
QList< int > changedCoordinatesVerticesIndexes() const
Returns the indexes of vertices that have changed coordinates.
 
QList< int > mNativeFacesIndexesGeometryChanged
 
QVector< QgsMeshFace > mFacesToAdd
 
QList< int > removedFaceIndexes() const
Returns the indexes of the faces that are removed with this changes.
 
QVector< FaceNeighbors > mFacesNeighborhoodToAdd
 
QList< std::array< int, 3 > > mVerticesToFaceChanges
 
QList< QgsPointXY > mOldXYValues
 
QList< double > newVerticesZValues() const
Returns the new Z values of vertices that have changed their coordinates.
 
QList< double > mNewZValues
 
QVector< QgsMeshVertex > mVerticesToAdd
 
QVector< QgsMeshFace > addedFaces() const
Returns the face that are added with this changes.
 
QList< QgsPointXY > oldVerticesXYValues() const
Returns the old (X,Y) values of vertices that have changed their coordinates.
 
int mAddedFacesFirstIndex
 
QVector< int > mVertexToFaceToAdd
 
QList< int > mFaceIndexesToRemove
 
QList< QgsPointXY > newVerticesXYValues() const
Returns the new (X,Y) values of vertices that have changed their coordinates.
 
QVector< QgsMeshFace > mFacesToRemove
 
QList< double > mOldZValues
 
QList< int > nativeFacesIndexesGeometryChanged() const
Returns a list of the native face indexes that have a geometry changed.
 
QList< int > verticesToRemoveIndexes() const
Returns the indexes of vertices to remove.
 
Class that contains independent faces an topological information about this faces.
 
int vertexToFace(int vertexIndex) const
Returns a face linked to the vertices with index vertexIndex.
 
QVector< FaceNeighbors > facesNeighborhood() const
Returns the face neighborhood of the faces, indexing is local.
 
void clear()
Clears all data contained in the instance.
 
QVector< QgsMeshFace > meshFaces() const
Returns faces.
 
Class that wraps a QgsMesh to ensure the consistency of the mesh during editing and help to access to...
 
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.
 
static QgsMeshEditingError checkTopology(const QgsMesh &mesh, int maxVerticesPerFace)
Checks the topology of the mesh mesh, if error occurs, this mesh can't be edited.
 
friend class QgsMeshVertexCirculator
 
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.
 
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 ...
 
QVector< int > neighborsOfFace(int faceIndex) const
Returns the indexes of neighbor faces of the face with index faceIndex.
 
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 ...
 
QVector< int > FaceNeighbors
 
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 tha tis 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 .
 
QgsMesh * mesh() const
Returns a pointer to the wrapped mesh.
 
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.
 
A class to represent a vector.
 
double angle() const
Returns the angle of the vector in radians.
 
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.
 
QgsMeshVertex vertex(int index) const
Returns a vertex at the index.