39  double ux1 = v1.
x() - vc.
x();
 
   40  double uy1 = v1.
y() - vc.
y();
 
   41  double vx1 = v2.
x() - vc.
x();
 
   42  double vy1 = v2.
y() - vc.
y();
 
   44  return ux1 * vy1 - uy1 * vx1;
 
   47static double crossProduct( 
int centralVertex, 
int vertex1, 
int vertex2, 
const QgsMesh &mesh )
 
   53  return crossProduct( vc, v1, v2 );
 
   58  : mFaces( topologicalMesh.mMesh->faces )
 
   59  , mFacesNeighborhood( topologicalMesh.mFacesNeighborhood )
 
   60  ,  mVertexIndex( vertexIndex )
 
   62  if ( vertexIndex >= 0 && vertexIndex < topologicalMesh.mMesh->vertexCount() )
 
   64    mCurrentFace = topologicalMesh.mVertexToFace[vertexIndex];
 
   73    mLastValidFace = mCurrentFace;
 
 
   77  : mFaces( topologicalFaces.mFaces )
 
   78  , mFacesNeighborhood( topologicalFaces.mFacesNeighborhood )
 
   79  , mVertexIndex( vertexIndex )
 
   81  const QgsMeshFace &face = topologicalFaces.mFaces.at( faceIndex );
 
   84  mCurrentFace = faceIndex;
 
   85  mLastValidFace = mCurrentFace;
 
 
   89  : mFaces( topologicalFaces.mFaces )
 
   90  , mFacesNeighborhood( topologicalFaces.mFacesNeighborhood )
 
   91  , mVertexIndex( vertexIndex )
 
   93  if ( topologicalFaces.mVerticesToFace.contains( vertexIndex ) )
 
   94    mCurrentFace = topologicalFaces.mVerticesToFace.values( vertexIndex ).first();
 
   95  mLastValidFace = mCurrentFace;
 
   96  mIsValid = mCurrentFace != -1;
 
 
  101  if ( mCurrentFace == -1 )
 
  102    mCurrentFace = mLastValidFace;
 
  105    int currentPos = positionInCurrentFace();
 
  106    Q_ASSERT( currentPos != -1 );
 
  110    mLastValidFace = mCurrentFace;
 
  111    mCurrentFace = mFacesNeighborhood.at( mCurrentFace ).at( ( currentPos + faceSize - 1 ) % 
currentFace.count() );
 
 
  119  if ( mCurrentFace == -1 )
 
  120    mCurrentFace = mLastValidFace;
 
  123    int currentPos = positionInCurrentFace();
 
  124    Q_ASSERT( currentPos != -1 );
 
  128    mLastValidFace = mCurrentFace;
 
  129    mCurrentFace = mFacesNeighborhood.at( mCurrentFace ).at( ( currentPos ) % faceSize );
 
 
  142  if ( mCurrentFace != -1 )
 
  143    return mFaces.at( mCurrentFace );
 
 
  153  if ( mCurrentFace == -1 )
 
  154    mCurrentFace = mLastValidFace;
 
  156  int firstFace = mCurrentFace;
 
  159  if ( mCurrentFace == firstFace )
 
 
  170  if ( mCurrentFace == -1 )
 
  171    mCurrentFace = mLastValidFace;
 
  173  int firstFace = mCurrentFace;
 
  176  if ( mCurrentFace == firstFace )
 
 
  184  if ( mCurrentFace == -1 )
 
  189  if ( face.isEmpty() )
 
  194  if ( vertexPosition == -1 )
 
  197  return face.at( ( vertexPosition + 1 ) % face.count() );
 
 
  202  if ( mCurrentFace == -1 )
 
  207  if ( face.isEmpty() )
 
  212  if ( vertexPosition == -1 )
 
  215  return face.at( ( vertexPosition - 1 + face.count() ) % face.count() );
 
 
  229  if ( mCurrentFace != -1 )
 
  230    ret.append( mCurrentFace );
 
 
  275int QgsMeshVertexCirculator::positionInCurrentFace()
 const 
  277  if ( mCurrentFace < 0 || mCurrentFace >= mFaces.count() )
 
  290  for ( 
int i = 0; i < changes.
mFacesToAdd.count(); ++i )
 
  293  for ( 
int boundary : topologicalFaces.mBoundaries )
 
  296    if ( mVertexToFace.at( boundary ) == -1 )
 
  299    const QList<int> &linkedFaces = topologicalFaces.mVerticesToFace.values( boundary );
 
  300    for ( 
int linkedFace : linkedFaces )
 
  306      if ( mVertexToFace.at( oppositeVertexForNewFace ) == -1 )
 
  316      if ( oppositeVertexForMeshFace != oppositeVertexForNewFace )
 
  328          boundaryPositionInMeshFace,
 
  338  for ( 
int f = 0; f < changes.
mFacesToAdd.count(); ++f )
 
  339    for ( 
int n = 0; n < changes.
mFacesToAdd.at( f ).count(); ++n )
 
  341        changes.
mFacesNeighborhoodToAdd[f][n] = changes.addedFaceIndexInMesh( topologicalFaces.mFacesNeighborhood.at( f ).at( n ) );
 
  343  const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
 
  344  for ( 
const int vtc : verticesToFaceToChange )
 
  345    if ( mVertexToFace.at( vtc ) == -1 )
 
  347                                              mVertexToFace.at( vtc ),
 
  348                                              changes.addedFaceIndexInMesh( topologicalFaces.mVerticesToFace.values( vtc ).first() )
 
  351  applyChanges( changes );
 
 
  358  int initialVerticesCount = mMesh->
vertices.count();
 
  363    mVertexToFace.resize( newSize );
 
  369    mMesh->
faces.resize( newSize );
 
  370    mFacesNeighborhood.resize( newSize );
 
  376    mFacesNeighborhood[changes.removedFaceIndexInMesh( i )] = 
FaceNeighbors();
 
  382    if ( mVertexToFace.at( vertexIndex ) == -1 )
 
  383      dereferenceAsFreeVertex( vertexIndex );
 
  385    mVertexToFace[vertexIndex] = -1;
 
  393      referenceAsFreeVertex( initialVerticesCount + i );
 
  396  for ( 
int i = 0; i < changes.
mFacesToAdd.count(); ++i )
 
  398    mMesh->
faces[changes.addedFaceIndexInMesh( i )] = changes.
mFacesToAdd.at( i );
 
  404    const int faceIndex = neighborChange.at( 0 );
 
  405    const int positionInFace = neighborChange.at( 1 );
 
  406    const int valueToApply = neighborChange.at( 3 );
 
  407    mFacesNeighborhood[faceIndex][positionInFace] = valueToApply;
 
  412    int vertexIndex = vertexToFaceChange.at( 0 );
 
  413    mVertexToFace[vertexToFaceChange.at( 0 )] = vertexToFaceChange.at( 2 );
 
  415    if ( vertexToFaceChange.at( 2 ) == -1 &&
 
  416         vertexToFaceChange.at( 1 ) != -1 &&
 
  417         !mMesh->
vertices.at( vertexIndex ).isEmpty() )
 
  418      referenceAsFreeVertex( vertexIndex );
 
  420    if ( vertexToFaceChange.at( 1 ) == -1 && vertexToFaceChange.at( 2 ) != -1 )
 
  421      dereferenceAsFreeVertex( vertexIndex );
 
  432      mMesh->
vertices[vertexIndex].setX( pt.
x() );
 
  433      mMesh->
vertices[vertexIndex].setY( pt.
y() );
 
 
  442    const int faceIndex = neighborChange.at( 0 );
 
  443    const int positionInFace = neighborChange.at( 1 );
 
  444    const int valueToApply = neighborChange.at( 2 );
 
  445    mFacesNeighborhood[faceIndex][positionInFace] = valueToApply;
 
  459    if ( mVertexToFace.at( vertexIndex ) == -1 )
 
  460      referenceAsFreeVertex( vertexIndex );
 
  464  for ( 
int i = 0; i < verticesToFaceChangesCount; ++i )
 
  466    const std::array<int, 3> vertexToFaceChange = changes.
mVerticesToFaceChanges.at( verticesToFaceChangesCount - i - 1 );
 
  467    int vertexIndex = vertexToFaceChange.at( 0 );
 
  468    mVertexToFace[vertexIndex] = vertexToFaceChange.at( 1 );
 
  470    if ( vertexToFaceChange.at( 2 ) == -1 && vertexToFaceChange.at( 1 ) != -1 )
 
  471      dereferenceAsFreeVertex( vertexIndex );
 
  473    if ( vertexToFaceChange.at( 1 ) == -1 &&
 
  474         vertexToFaceChange.at( 2 ) != -1 &&
 
  476      referenceAsFreeVertex( vertexIndex );
 
  482    mMesh->
faces.resize( newSize );
 
  483    mFacesNeighborhood.resize( newSize );
 
  490    for ( 
int i = newSize; i < mMesh->
vertexCount(); ++i )
 
  491      if ( mVertexToFace.at( i ) == -1 )
 
  492        dereferenceAsFreeVertex( i );
 
  495    mVertexToFace.resize( newSize );
 
  506      mMesh->
vertices[vertexIndex].setX( pt.
x() );
 
  507      mMesh->
vertices[vertexIndex].setY( pt.
y() );
 
 
  517QSet<int> QgsTopologicalMesh::concernedFacesBy( 
const QList<int> &faceIndexes )
 const 
  520  for ( 
const int faceIndex : faceIndexes )
 
  523    for ( 
int i = 0; i < face.count(); ++i )
 
  526      faces.unite( QSet< int >( around.begin(), around.end() ) );
 
  532void QgsTopologicalMesh::dereferenceAsFreeVertex( 
int vertexIndex )
 
  534  mFreeVertices.remove( vertexIndex );
 
  537void QgsTopologicalMesh::referenceAsFreeVertex( 
int vertexIndex )
 
  541  mFreeVertices.insert( vertexIndex );
 
  546  for ( 
int faceIndex = 0 ; faceIndex < mMesh->
faces.count( ); ++faceIndex )
 
  549    const FaceNeighbors &neighborhood = mFacesNeighborhood.at( faceIndex );
 
  550    if ( face.count() != neighborhood.count() )
 
  552    for ( 
int i = 0; i < face.count(); ++i )
 
  554      int vertexIndex = face.at( i );
 
  556      if ( mVertexToFace.at( vertexIndex ) == -1 )
 
  559      int neighborIndex = neighborhood.at( i );
 
  560      if ( neighborIndex != -1 )
 
  563        if ( neighborFace.isEmpty() )
 
  565        int neighborSize = neighborFace.size();
 
  566        const FaceNeighbors &neighborhoodOfNeighbor = mFacesNeighborhood.at( neighborIndex );
 
  568        if ( neighborhoodOfNeighbor.isEmpty() || neighborhoodOfNeighbor.at( ( posInNeighbor + neighborSize - 1 ) % neighborSize ) != faceIndex )
 
  574  for ( 
int vertexIndex = 0; vertexIndex < mMesh->
vertexCount(); ++vertexIndex )
 
  576    if ( mVertexToFace.at( vertexIndex ) != -1 )
 
  578      if ( !mMesh->
face( mVertexToFace.at( vertexIndex ) ).contains( vertexIndex ) )
 
 
  604  if ( vertexIndex < 0 || vertexIndex >= mMesh->
vertexCount() )
 
  606  return mVertexToFace.at( vertexIndex );
 
 
  621  if ( vertexIndex < 0 || vertexIndex >= mMesh->
vertexCount() )
 
  624  if ( mMesh->
vertices.at( vertexIndex ).isEmpty() )
 
  627  return mVertexToFace.at( vertexIndex ) == -1;
 
 
  632  return QList<int>( mFreeVertices.begin(), mFreeVertices.end() );
 
 
  637  int size = vertices.size();
 
  639  for ( 
int i = 0; i < size; ++i )
 
  642    int iv1 = ( i + 1 ) % size;
 
  643    int iv2 = ( i + 2 ) % size;
 
  658    double crossProd = crossProduct( v1, v0, v2 ); 
 
  659    if ( direction != 0 && crossProd * direction < 0 )   
 
  661      clockwise = direction > 0;
 
  664    else if ( crossProd == 0 )
 
  666      clockwise = direction > 0;
 
  669    else if ( direction == 0 )
 
  670      direction = crossProd / std::fabs( crossProd );
 
  673  clockwise = direction > 0;
 
 
  682  int faceSize = face.count();
 
  686  QVector<QgsMeshVertex> vertices( face.size() );
 
  688  for ( 
int i = 0; i < faceSize; ++i )
 
  697  bool clockwise = 
false;
 
  704    for ( 
int i = 0; i < faceSize / 2; ++i )
 
  707      face[i] = face.at( faceSize - i - 1 );
 
  708      face[faceSize - i - 1] = temp;
 
 
  717  QVector<int> oldToNewIndex( mMesh->
vertices.count(), -1 );
 
  721  while ( oldIndex < verticesTotalCount )
 
  729      oldToNewIndex[oldIndex] = newIndex;
 
  730      if ( oldIndex != newIndex )
 
  732      oldToNewIndex[oldIndex] = newIndex;
 
  742  int facesTotalCount = mMesh->
faceCount();
 
  743  while ( oldIndex < facesTotalCount )
 
  745    if ( mMesh->
face( oldIndex ).isEmpty() )
 
  749      if ( oldIndex != newIndex )
 
  750        mMesh->
faces[newIndex] = mMesh->
faces[oldIndex];
 
  752      for ( 
int i = 0; i < face.count(); ++i )
 
  753        face[i] = oldToNewIndex[face.at( i )];
 
  759  mMesh->
faces.resize( newIndex );
 
  761  mVertexToFace.clear();
 
  762  mFacesNeighborhood.clear();
 
 
  767  QVector<int> oldToNewVerticesIndexes;
 
  768  if ( !renumberVertices( oldToNewVerticesIndexes ) )
 
  772  QVector<int> oldToNewFacesIndexes;
 
  774  if ( !renumberFaces( oldToNewFacesIndexes ) )
 
  779  QVector<QgsMeshVertex> tempVertices( mMesh->
vertices.count() );
 
  780  for ( 
int i = 0; i < oldToNewVerticesIndexes.count(); ++i )
 
  782    tempVertices[oldToNewVerticesIndexes.at( i )] = mMesh->
vertex( i );
 
  786  QVector<QgsMeshFace> tempFaces( mMesh->
faces.count() );
 
  787  for ( 
int i = 0; i < oldToNewFacesIndexes.count(); ++i )
 
  789    tempFaces[oldToNewFacesIndexes.at( i )] = mMesh->
face( i );
 
  791    QgsMeshFace &face = tempFaces[oldToNewFacesIndexes.at( i )];
 
  793    for ( 
int fi = 0; fi < face.count(); ++fi )
 
  795      face[fi] = oldToNewVerticesIndexes.at( face.at( fi ) );
 
  799  mMesh->
faces = tempFaces;
 
 
  805bool QgsTopologicalMesh::renumberVertices( QVector<int> &oldToNewIndex )
 const 
  807  std::vector<QgsMeshVertexCirculator> circulators;
 
  808  circulators.reserve( mMesh->
vertices.count() );
 
  809  int minDegree = std::numeric_limits<int>::max();
 
  810  int minDegreeVertex = -1;
 
  813  QSet<int> nonThreadedVertex;
 
  814  oldToNewIndex = QVector<int> ( mMesh->
vertexCount(), -1 );
 
  817    circulators.emplace_back( *
this, i );
 
  819    if ( circulators.back().degree() < minDegree )
 
  821      minDegreeVertex = circulators.size() - 1;
 
  822      minDegree = circulator.
degree();
 
  824    nonThreadedVertex.insert( i );
 
  827  auto sortedNeighbor = [circulators]( QList<int> &neighbors, 
int index )
 
  841      int degree = circulators.at( neighborIndex ).degree();
 
  842      QList<int>::Iterator it = neighbors.begin();
 
  843      while ( it != neighbors.end() )
 
  845        if ( degree <= circulators.at( *it ).degree() )
 
  847          neighbors.insert( it, neighborIndex );
 
  852      if ( it == neighbors.end() )
 
  853        neighbors.append( neighborIndex );
 
  859  int currentVertex = minDegreeVertex;
 
  860  nonThreadedVertex.remove( minDegreeVertex );
 
  862  while ( newIndex < mMesh->vertexCount() )
 
  864    if ( oldToNewIndex[currentVertex] == -1 )
 
  865      oldToNewIndex[currentVertex] = newIndex++;
 
  867    if ( circulators.at( currentVertex ).isValid() )
 
  869      QList<int> neighbors;
 
  870      sortedNeighbor( neighbors, currentVertex );
 
  872      for ( 
const int i : std::as_const( neighbors ) )
 
  873        if ( oldToNewIndex.at( i ) == -1 && nonThreadedVertex.contains( i ) )
 
  876          nonThreadedVertex.remove( i );
 
  880    if ( queue.isEmpty() )
 
  882      if ( nonThreadedVertex.isEmpty() && newIndex < mMesh->vertexCount() )
 
  885      const QList<int> remainingVertex( nonThreadedVertex.constBegin(), nonThreadedVertex.constEnd() );
 
  886      int minRemainingDegree = std::numeric_limits<int>::max();
 
  887      int minRemainingVertex = -1;
 
  888      for ( 
const int i : remainingVertex )
 
  890        int degree = circulators.at( i ).degree();
 
  891        if ( degree < minRemainingDegree )
 
  893          minRemainingDegree = degree;
 
  894          minRemainingVertex = i;
 
  897      currentVertex = minRemainingVertex;
 
  898      nonThreadedVertex.remove( currentVertex );
 
  902      currentVertex = queue.dequeue();
 
  909bool QgsTopologicalMesh::renumberFaces( QVector<int> &oldToNewIndex )
 const 
  912  QSet<int> nonThreadedFaces;
 
  914  oldToNewIndex = QVector<int>( mMesh->
faceCount(), -1 );
 
  916  QVector<int> faceDegrees( mMesh->
faceCount(), 0 );
 
  918  int minDegree = std::numeric_limits<int>::max();
 
  919  int minDegreeFace = -1;
 
  920  for ( 
int faceIndex = 0; faceIndex < mMesh->
faceCount(); ++faceIndex )
 
  922    const FaceNeighbors &neighbors = mFacesNeighborhood.at( faceIndex );
 
  925    for ( 
int n = 0; n < neighbors.size(); ++n )
 
  927      if ( neighbors.at( n ) != -1 )
 
  931    if ( degree < minDegree )
 
  934      minDegreeFace = faceIndex;
 
  937    faceDegrees[faceIndex] = degree;
 
  938    nonThreadedFaces.insert( faceIndex );
 
  942  int currentFace = minDegreeFace;
 
  943  nonThreadedFaces.remove( minDegreeFace );
 
  945  auto sortedNeighbor = [
this, faceDegrees]( QList<int> &neighbors, 
int index )
 
  947    const FaceNeighbors &neighborhood = mFacesNeighborhood.at( index );
 
  949    for ( 
int i = 0; i < neighborhood.count(); ++i )
 
  951      int neighborIndex = neighborhood.at( i );
 
  952      if ( neighborIndex == -1 )
 
  955      int degree = faceDegrees.at( neighborIndex );
 
  956      if ( neighbors.isEmpty() )
 
  957        neighbors.append( neighborIndex );
 
  960        QList<int>::Iterator it = neighbors.begin();
 
  961        while ( it != neighbors.end() )
 
  963          if ( degree <= faceDegrees.at( *it ) )
 
  965            neighbors.insert( it, neighborIndex );
 
  970        if ( it == neighbors.end() )
 
  971          neighbors.append( neighborIndex );
 
  976  while ( newIndex < mMesh->faceCount() )
 
  978    if ( oldToNewIndex[currentFace] == -1 )
 
  979      oldToNewIndex[currentFace] = newIndex++;
 
  981    QList<int> neighbors;
 
  982    sortedNeighbor( neighbors, currentFace );
 
  984    for ( 
const int i : std::as_const( neighbors ) )
 
  985      if ( oldToNewIndex.at( i ) == -1 && nonThreadedFaces.contains( i ) )
 
  988        nonThreadedFaces.remove( i );
 
  991    if ( queue.isEmpty() )
 
  993      if ( nonThreadedFaces.isEmpty() && newIndex < mMesh->faceCount() )
 
  996      const QList<int> remainingFace( nonThreadedFaces.constBegin(), nonThreadedFaces.constEnd() );
 
  997      int minRemainingDegree = std::numeric_limits<int>::max();
 
  998      int minRemainingFace = -1;
 
  999      for ( 
const int i : remainingFace )
 
 1001        int degree = faceDegrees.at( i );
 
 1002        if ( degree < minRemainingDegree )
 
 1004          minRemainingDegree = degree;
 
 1005          minRemainingFace = i;
 
 1008      currentFace = minRemainingFace;
 
 1009      nonThreadedFaces.remove( currentFace );
 
 1013      currentFace = queue.dequeue();
 
 1028  return mFacesToRemove;
 
 
 1033  return mFaceIndexesToRemove;
 
 
 1038  return mVerticesToAdd;
 
 
 1043  return mChangeCoordinateVerticesIndexes;
 
 
 1053  return mNewXYValues;
 
 
 1058  return mOldXYValues;
 
 
 1063  return mNativeFacesIndexesGeometryChanged;
 
 
 1068  return ( mFaceIndexesToRemove.isEmpty() &&
 
 1069           mFacesToAdd.isEmpty() &&
 
 1070           mFacesNeighborhoodToAdd.isEmpty() &&
 
 1071           mFacesToRemove.isEmpty() &&
 
 1072           mFacesNeighborhoodToRemove.isEmpty() &&
 
 1073           mNeighborhoodChanges.isEmpty() &&
 
 1074           mVerticesToAdd.isEmpty() &&
 
 1075           mVertexToFaceToAdd.isEmpty() &&
 
 1076           mVerticesToRemoveIndexes.isEmpty() &&
 
 1077           mRemovedVertices.isEmpty() &&
 
 1078           mVerticesToFaceRemoved.isEmpty() &&
 
 1079           mVerticesToFaceChanges.isEmpty() &&
 
 1080           mChangeCoordinateVerticesIndexes.isEmpty() &&
 
 1081           mNewZValues.isEmpty() &&
 
 1082           mOldZValues.isEmpty() &&
 
 1083           mNewXYValues.isEmpty() &&
 
 1084           mOldXYValues.isEmpty() &&
 
 1085           mNativeFacesIndexesGeometryChanged.isEmpty() );
 
 
 1090  return mVerticesToRemoveIndexes;
 
 
 1093int QgsTopologicalMesh::Changes::addedFaceIndexInMesh( 
int internalIndex )
 const 
 1095  if ( internalIndex == -1 )
 
 1098  return internalIndex + mAddedFacesFirstIndex;
 
 1101int QgsTopologicalMesh::Changes::removedFaceIndexInMesh( 
int internalIndex )
 const 
 1103  if ( internalIndex == -1 )
 
 1106  return mFaceIndexesToRemove.at( internalIndex );
 
 1111  mAddedFacesFirstIndex = 0;
 
 1112  mFaceIndexesToRemove.clear();
 
 1113  mFacesToAdd.clear();
 
 1114  mFacesNeighborhoodToAdd.clear();
 
 1115  mFacesToRemove.clear();
 
 1116  mFacesNeighborhoodToRemove.clear();
 
 1117  mNeighborhoodChanges.clear();
 
 1119  mVerticesToAdd.clear();
 
 1120  mVertexToFaceToAdd.clear();
 
 1121  mVerticesToRemoveIndexes.clear();
 
 1122  mRemovedVertices.clear();
 
 1123  mVerticesToFaceRemoved.clear();
 
 1124  mVerticesToFaceChanges.clear();
 
 1126  mChangeCoordinateVerticesIndexes.clear();
 
 1127  mNewZValues.clear();
 
 1128  mOldZValues.clear();
 
 1129  mNewXYValues.clear();
 
 1130  mOldXYValues.clear();
 
 1131  mNativeFacesIndexesGeometryChanged.clear();
 
 
 1141  mVertexToFace.append( -1 );
 
 1142  referenceAsFreeVertex( mMesh->
vertices.count() - 1 );
 
 
 1148static double vertexPolygonOrientation( 
const QgsMesh &
mesh, 
const QList<int> &vertexIndexes )
 
 1150  if ( vertexIndexes.count() < 3 )
 
 1153  int hullDomainVertexPos = -1;
 
 1154  double xMin = std::numeric_limits<double>::max();
 
 1155  double yMin = std::numeric_limits<double>::max();
 
 1156  for ( 
int i = 0; i < vertexIndexes.count(); ++i )
 
 1159    if ( xMin >= vertex.
x() && yMin > vertex.
y() )
 
 1161      hullDomainVertexPos = i;
 
 1167  if ( hullDomainVertexPos >= 0 )
 
 1169    int iv1 = vertexIndexes.at( ( hullDomainVertexPos - 1 + vertexIndexes.count() ) % vertexIndexes.count() );
 
 1170    int iv2 = vertexIndexes.at( ( hullDomainVertexPos + 1 ) % vertexIndexes.count() );
 
 1171    int ivc = vertexIndexes.at( ( hullDomainVertexPos ) );
 
 1172    double cp = crossProduct( ivc, iv1, iv2, 
mesh );
 
 1181  if ( vertexIndex >= mVertexToFace.count() )
 
 1184  if ( mVertexToFace.at( vertexIndex ) == -1 ) 
 
 1190    dereferenceAsFreeVertex( vertexIndex );
 
 1198  QList<int> boundariesVertexIndex;
 
 1199  QList<int> associateFaceToBoundaries;
 
 1200  QList<int> removedFacesIndexes;
 
 1201  QSet<int> boundaryInGlobalMesh;
 
 1207    Q_ASSERT( !mMesh->
vertices.at( boundariesVertexIndex.last() ).isEmpty() );
 
 1209    associateFaceToBoundaries.append( mFacesNeighborhood.at( circulator.
currentFaceIndex() ).at(
 
 1212    if ( currentFace.count() > 3 ) 
 
 1215      for ( 
int i = 2; i < currentFace.count() - 1; ++i )
 
 1217        boundariesVertexIndex.append( currentFace.at( ( posInface + i ) % currentFace.count() ) );
 
 1218        Q_ASSERT( !mMesh->
vertices.at( boundariesVertexIndex.last() ).isEmpty() );
 
 1219        associateFaceToBoundaries.append( mFacesNeighborhood.at( circulator.
currentFaceIndex() ).at(
 
 1226  bool boundaryFill = 
false;
 
 1229    boundaryFill = 
true;
 
 1233    boundariesVertexIndex.append( lastVertexIndex );
 
 1242      boundaryFill = 
false; 
 
 1245      associateFaceToBoundaries.append( -1 );
 
 1247    for ( 
const int index : std::as_const( boundariesVertexIndex ) )
 
 1250        boundaryInGlobalMesh.insert( index );
 
 1254  int currentVertexToFace = mVertexToFace.at( vertexIndex );
 
 1258  QList<QList<int>> holes;
 
 1259  QList<QList<int>> associateMeshFacesToHoles;
 
 1261  bool cancelOperation = 
false;
 
 1269    int finalPos = boundariesVertexIndex.count() - 1;
 
 1270    QList<int> uncoveredVertex;
 
 1272    QList<int> partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
 
 1273    QList<int> associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
 
 1274    while ( startPos < finalPos && !partToCheck.isEmpty() )
 
 1277      int secondPos = partToCheck.count() - 1;
 
 1278      const QgsPoint &closingSegmentExtremety1 = mMesh->
vertex( partToCheck.at( 0 ) );
 
 1279      const QgsPoint &closingSegmentExtremety2 = mMesh->
vertex( partToCheck.last() );
 
 1280      bool isEdgeIntersect = 
false;
 
 1281      for ( 
int i = 1; i < secondPos - 1; ++i )
 
 1285        bool isLineIntersection;
 
 1288        if ( isEdgeIntersect )
 
 1292      int index = partToCheck.at( 0 );
 
 1293      if ( boundaryInGlobalMesh.contains( index ) && index != boundariesVertexIndex.at( 0 ) )
 
 1295        cancelOperation = 
true;
 
 1301      if ( isEdgeIntersect || vertexPolygonOrientation( *mMesh, partToCheck ) >= 0 )
 
 1303        partToCheck.removeLast();
 
 1304        associateFacePart.removeAt( associateFacePart.count() - 2 );
 
 1305        if ( partToCheck.count() == 1 )
 
 1307          uncoveredVertex.append( index );
 
 1308          startPos = startPos + 1;
 
 1309          partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
 
 1310          associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
 
 1316        holes.append( partToCheck );
 
 1317        associateMeshFacesToHoles.append( associateFacePart );
 
 1319        startPos = startPos + partToCheck.count() - 1;
 
 1320        uncoveredVertex.append( partToCheck.at( 0 ) );
 
 1321        partToCheck = boundariesVertexIndex.mid( startPos, finalPos - startPos + 1 );
 
 1322        associateFacePart = associateFaceToBoundaries.mid( startPos, finalPos - startPos + 1 );
 
 1328    holes.append( boundariesVertexIndex );
 
 1329    associateMeshFacesToHoles.append( associateFaceToBoundaries );
 
 1332  if ( cancelOperation )
 
 1338  Q_ASSERT( holes.count() == associateMeshFacesToHoles.count() );
 
 1344  dereferenceAsFreeVertex( vertexIndex );
 
 1346  mVertexToFace[vertexIndex] = -1;
 
 1349  for ( 
int h = 0; h < holes.count(); ++h )
 
 1351    const QList<int> &holeVertices = holes.at( h );
 
 1352    const QList<int> &associateMeshFacesToHole = associateMeshFacesToHoles.at( h );
 
 1353    QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
 
 1354    std::vector<p2t::Point *> holeToFill( holeVertices.count() );
 
 1357      for ( 
int i = 0; i < holeVertices.count(); ++i )
 
 1360        holeToFill[i] = 
new p2t::Point( vertex.
x(), vertex.
y() );
 
 1361        mapPoly2TriPointToVertex.insert( holeToFill[i], holeVertices.at( i ) );
 
 1364      auto cdt = std::make_unique<p2t::CDT>( holeToFill );
 
 1367      std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
 
 1368      QVector<QgsMeshFace> newFaces( triangles.size() );
 
 1369      for ( 
size_t i = 0; i < triangles.size(); ++i )
 
 1373        for ( 
int j = 0; j < 3; j++ )
 
 1375          int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
 
 1376          if ( vertInd == -1 )
 
 1377            throw std::exception();
 
 1378          Q_ASSERT( !mMesh->
vertices.at( vertInd ).isEmpty() );
 
 1386        throw std::exception();
 
 1387      int newFaceIndexStartIndex = mMesh->
faceCount();
 
 1394      const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
 
 1395      for ( 
const int vtc : verticesToFaceToChange )
 
 1396        if ( mVertexToFace.at( vtc ) == -1 )
 
 1398              mVertexToFace.at( vtc ),
 
 1399              addChanges.addedFaceIndexInMesh( topologicalFaces.mVerticesToFace.values( vtc ).first() )
 
 1404      for ( 
int i = 0; i < topologicalFaces.mFaces.count(); ++i )
 
 1406        FaceNeighbors &faceNeighbors = addChanges.mFacesNeighborhoodToAdd[i];
 
 1407        faceNeighbors = topologicalFaces.mFacesNeighborhood.at( i );
 
 1408        for ( 
int n = 0; n < faceNeighbors.count(); ++n )
 
 1410          if ( faceNeighbors.at( n ) != -1 )
 
 1411            faceNeighbors[n] += newFaceIndexStartIndex; 
 
 1416      for ( 
int i = 0 ; i < holeVertices.count(); ++i )
 
 1418        int vertexHoleIndex = holeVertices.at( i );
 
 1419        int meshFaceBoundaryIndex = associateMeshFacesToHole.at( i );
 
 1424        int newFaceBoundaryIndexInMesh = circulator.
currentFaceIndex() + newFaceIndexStartIndex;
 
 1428        if ( meshFaceBoundaryIndex != -1 )
 
 1431          int positionInMeshFaceBoundary = 
vertexPositionInFace( *mMesh, vertexHoleIndex, meshFaceBoundaryIndex );
 
 1432          positionInMeshFaceBoundary = ( positionInMeshFaceBoundary - 1 + meshFace.count() ) % meshFace.count(); 
 
 1434          addChanges.mNeighborhoodChanges.append( {meshFaceBoundaryIndex, positionInMeshFaceBoundary, -1, newFaceBoundaryIndexInMesh} );
 
 1437        addChanges.mFacesNeighborhoodToAdd[newFaceBoundaryLocalIndex][positionInNewFaces] = meshFaceBoundaryIndex;
 
 1442      changes.
mFacesToAdd.append( addChanges.mFacesToAdd );
 
 1445      for ( 
const std::array<int, 4> &neighborChangeToAdd : std::as_const( addChanges.mNeighborhoodChanges ) )
 
 1447        bool merged = 
false;
 
 1450          if ( existingNeighborChange.at( 0 ) == neighborChangeToAdd.at( 0 ) &&
 
 1451               existingNeighborChange.at( 1 ) == neighborChangeToAdd.at( 1 ) )
 
 1454            Q_ASSERT( existingNeighborChange.at( 3 ) == neighborChangeToAdd.at( 2 ) );
 
 1455            existingNeighborChange[3] = neighborChangeToAdd.at( 3 );
 
 1462      for ( 
const std::array<int, 3> &verticesToFaceToAdd : std::as_const( addChanges.mVerticesToFaceChanges ) )
 
 1464        bool merged = 
false;
 
 1467          if ( existingVerticesToFace.at( 0 ) == verticesToFaceToAdd.at( 0 ) )
 
 1470            Q_ASSERT( existingVerticesToFace.at( 2 ) == verticesToFaceToAdd.at( 1 ) );
 
 1471            existingVerticesToFace[2] = verticesToFaceToAdd.at( 2 );
 
 1478      qDeleteAll( holeToFill );
 
 1482      qDeleteAll( holeToFill );
 
 1486  changes.mAddedFacesFirstIndex = oldFacesCount;
 
 1490  changes.mAddedFacesFirstIndex = oldFacesCount;
 
 
 1497  QSet<int> facesIndex;
 
 1499  for ( 
int vertexIndex : vertices )
 
 1502    facesIndex.unite( QSet< int >( faces.begin(), faces.end() ) );
 
 1509  for ( 
int vertexIndex : vertices )
 
 1511    int currentVertexToFace = mVertexToFace.at( vertexIndex );
 
 1517    dereferenceAsFreeVertex( vertexIndex );
 
 1519    mVertexToFace[vertexIndex] = -1;
 
 
 1527  QList<int> boundariesToCheckClockwiseInNewFaces = topologicFaces.mBoundaries;
 
 1528  QList<std::array<int, 2>> boundariesToCheckCounterClockwiseInNewFaces; 
 
 1529  QList<int> uniqueSharedVertexBoundary;
 
 1537  while ( !boundariesToCheckClockwiseInNewFaces.isEmpty() )
 
 1539    int boundary = boundariesToCheckClockwiseInNewFaces.takeLast();
 
 1541    const QList<int> &linkedFaces = topologicFaces.mVerticesToFace.values( boundary );
 
 1543    for ( 
int const linkedFace : linkedFaces )
 
 1547      if ( mVertexToFace.at( boundary ) == -1 )
 
 1553      if ( !newFacescirculator.
isValid() )
 
 1567      if ( oppositeVertexCCWInMesh == oppositeVertexInNewFaces ) 
 
 1573        int faceSize = newFaceOnBoundary.size();
 
 1575        int previousVertexIndex = ( posInNewFace + faceSize - 1 ) % faceSize;
 
 1576        if ( newFaceOnBoundary.at( previousVertexIndex ) == oppositeVertexCCWInMesh )
 
 1584      if ( oppositeVertexCWInMesh == oppositeVertexInNewFaces )
 
 1588      boundariesToCheckCounterClockwiseInNewFaces.append( {boundary, linkedFace} );
 
 1593  while ( !boundariesToCheckCounterClockwiseInNewFaces.isEmpty() )
 
 1595    std::array<int, 2> boundaryLinkedface = boundariesToCheckCounterClockwiseInNewFaces.takeLast();
 
 1596    int boundary = boundaryLinkedface.at( 0 );
 
 1597    int linkedFace = boundaryLinkedface.at( 1 );
 
 1612    if ( oppositeVertexCWInMesh == oppositeVertexInNewFaces ) 
 
 1619    if ( oppositeVertexCCWInMesh == oppositeVertexInNewFaces )
 
 1622    uniqueSharedVertexBoundary.append( boundary );
 
 1625  if ( !uniqueSharedVertexBoundary.isEmpty() )
 
 1629  QSet<int> boundaryVertices( topologicFaces.mBoundaries.constBegin(), topologicFaces.mBoundaries.constEnd() );
 
 1630  for ( 
const QgsMeshFace &newFace : std::as_const( topologicFaces.mFaces ) )
 
 1632    for ( 
const int vertexIndex : newFace )
 
 1634      if ( boundaryVertices.contains( vertexIndex ) )
 
 1636      if ( mVertexToFace.at( vertexIndex ) != -1 )
 
 
 1647  mFacesNeighborhood.clear();
 
 1648  mVerticesToFace.clear();
 
 1649  mBoundaries.clear();
 
 
 1654  return mFacesNeighborhood;
 
 
 1659  if ( mVerticesToFace.contains( vertexIndex ) )
 
 1660    return mVerticesToFace.values( vertexIndex ).at( 0 );
 
 
 1668  topologicMesh.mMesh = 
mesh;
 
 1669  topologicMesh.mVertexToFace = QVector<int>( 
mesh->
vertexCount(), -1 );
 
 1670  topologicMesh.mMaximumVerticesPerFace = maxVerticesPerFace;
 
 1677    if ( maxVerticesPerFace != 0 && 
mesh->
face( i ).count() > maxVerticesPerFace )
 
 1695    topologicMesh.mFacesNeighborhood = subMesh.mFacesNeighborhood;
 
 1697    for ( 
int i = 0; i < topologicMesh.mMesh->
vertexCount(); ++i )
 
 1699      if ( topologicMesh.mVertexToFace.at( i ) == -1 )
 
 1700        topologicMesh.mFreeVertices.insert( i );
 
 1704  return topologicMesh;
 
 
 1709  return createTopologicalFaces( faces, 
nullptr, error, uniqueSharedVertexAllowed );
 
 
 1714  const QVector<QgsMeshFace> &faces,
 
 1715  QVector<int> *globalVertexToFace,
 
 1717  bool allowUniqueSharedVertex )
 
 1719  int facesCount = faces.count();
 
 1720  QVector<FaceNeighbors> faceTopologies;
 
 1721  QMultiHash<int, int> verticesToFace;
 
 1724  TopologicalFaces ret;
 
 1728  QMap<int, QMap<int, int>> verticesToNeighbor;
 
 1730  for ( 
int faceIndex = 0; faceIndex < facesCount; ++faceIndex )
 
 1733    int faceSize = face.count();
 
 1735    for ( 
int i = 0; i < faceSize; ++i )
 
 1737      int v1 = face[i % faceSize];
 
 1738      int v2 = face[( i + 1 ) % faceSize];
 
 1739      if ( verticesToNeighbor[v2].contains( v1 ) )
 
 1745        verticesToNeighbor[v2].insert( v1, faceIndex );
 
 1749  faceTopologies = QVector<FaceNeighbors>( faces.count() );
 
 1751  QSet<int> boundaryVertices;
 
 1753  for ( 
int faceIndex = 0; faceIndex < facesCount; ++faceIndex )
 
 1756    int faceSize = face.size();
 
 1758    faceTopology.resize( faceSize );
 
 1760    for ( 
int i = 0; i < faceSize; ++i )
 
 1762      int v1 = face.at( i );
 
 1763      int v2 = face.at( ( i + 1 ) % faceSize );
 
 1765      if ( globalVertexToFace )
 
 1767        if ( ( *globalVertexToFace )[v1] == -1 )
 
 1768          ( *globalVertexToFace )[v1] = faceIndex ;
 
 1772        if ( allowUniqueSharedVertex || !verticesToFace.contains( v1 ) )
 
 1773          verticesToFace.insert( v1, faceIndex ) ;
 
 1776      QMap<int, int> &edges = verticesToNeighbor[v1];
 
 1777      if ( edges.contains( v2 ) )
 
 1778        faceTopology[i] = edges.value( v2 );
 
 1781        faceTopology[i] = -1;
 
 1783        if ( !allowUniqueSharedVertex )
 
 1785          if ( boundaryVertices.contains( v1 ) )
 
 1791        boundaryVertices.insert( v1 );
 
 1797  ret.mFacesNeighborhood = faceTopologies;
 
 1798  ret.mBoundaries = boundaryVertices.values();
 
 1799  ret.mVerticesToFace = verticesToFace;
 
 1805  return mFacesNeighborhood.at( faceIndex );
 
 
 1817  QSet<int> removedFaces( facesIndexes.begin(), facesIndexes.end() );
 
 1818  QSet<int> concernedFaces = concernedFacesBy( facesIndexes );
 
 1820  for ( 
const int f : std::as_const( removedFaces ) )
 
 1821    concernedFaces.remove( f );
 
 1823  QVector<QgsMeshFace> remainingFaces;
 
 1824  remainingFaces.reserve( concernedFaces.count() );
 
 1825  for ( 
const int f : std::as_const( concernedFaces ) )
 
 1826    remainingFaces.append( mMesh->
face( f ) );
 
 1829  createTopologicalFaces( remainingFaces, 
nullptr, error, 
false );
 
 
 1841  QSet<int> indexSet( facesIndexesToRemove.begin(), facesIndexesToRemove.end() );
 
 1842  QSet<int> threatedVertex;
 
 1844  for ( 
int i = 0; i < facesIndexesToRemove.count(); ++i )
 
 1846    const int faceIndex = facesIndexesToRemove.at( i );
 
 1849    const FaceNeighbors &neighborhood = mFacesNeighborhood.at( faceIndex );
 
 1851    for ( 
int j = 0; j < face.count(); ++j )
 
 1854      int neighborIndex = neighborhood.at( j );
 
 1855      if ( neighborIndex != -1 && !indexSet.contains( neighborIndex ) )
 
 1857        int positionInNeighbor = mFacesNeighborhood.at( neighborIndex ).indexOf( faceIndex );
 
 1862      int vertexIndex = face.at( j );
 
 1863      if ( !threatedVertex.contains( vertexIndex ) && indexSet.contains( mVertexToFace.at( vertexIndex ) ) )
 
 1865        int oldValue = mVertexToFace.at( vertexIndex );
 
 1868        if ( neighborIndex != -1 && !indexSet.contains( neighborIndex ) ) 
 
 1869          refValue = neighborIndex;
 
 1873          aroundFaces.removeOne( faceIndex );
 
 1874          if ( !aroundFaces.isEmpty() )
 
 1876            while ( !aroundFaces.isEmpty() && refValue == -1 )
 
 1878              if ( !indexSet.contains( aroundFaces.first() ) )
 
 1879                refValue = aroundFaces.first();
 
 1881                aroundFaces.removeFirst();
 
 1886        threatedVertex.insert( vertexIndex );
 
 
 1896bool QgsTopologicalMesh::eitherSideFacesAndVertices( 
int vertexIndex1,
 
 1900    int &neighborVertex1InFace1,
 
 1901    int &neighborVertex1InFace2,
 
 1902    int &neighborVertex2inFace1,
 
 1903    int &neighborVertex2inFace2 )
 const 
 1945  int oppositeVertexFace1;
 
 1946  int oppositeVertexFace2;
 
 1947  int supposedOppositeVertexFace1;
 
 1948  int supposedoppositeVertexFace2;
 
 1950  bool result = eitherSideFacesAndVertices(
 
 1955                  oppositeVertexFace1,
 
 1956                  supposedoppositeVertexFace2,
 
 1957                  supposedOppositeVertexFace1,
 
 1958                  oppositeVertexFace2 );
 
 1963       oppositeVertexFace1 < 0 ||
 
 1964       oppositeVertexFace2 < 0 ||
 
 1965       supposedOppositeVertexFace1 != oppositeVertexFace1 ||
 
 1966       supposedoppositeVertexFace2 != oppositeVertexFace2 )
 
 1973  if ( face1.count() != 3 || face2.count() != 3 )
 
 1976  double crossProduct1 = crossProduct( vertexIndex1, oppositeVertexFace1, oppositeVertexFace2, *mMesh );
 
 1977  double crossProduct2 = crossProduct( vertexIndex2, oppositeVertexFace1, oppositeVertexFace2, *mMesh );
 
 1979  return crossProduct1 * crossProduct2 < 0;
 
 
 1986  int oppositeVertexFace1;
 
 1987  int oppositeVertexFace2;
 
 1988  int supposedOppositeVertexFace1;
 
 1989  int supposedoppositeVertexFace2;
 
 1991  bool result = eitherSideFacesAndVertices(
 
 1996                  oppositeVertexFace1,
 
 1997                  supposedoppositeVertexFace2,
 
 1998                  supposedOppositeVertexFace1,
 
 1999                  oppositeVertexFace2 );
 
 2004       oppositeVertexFace1 < 0 ||
 
 2005       oppositeVertexFace2 < 0 ||
 
 2006       supposedOppositeVertexFace1 != oppositeVertexFace1 ||
 
 2007       supposedoppositeVertexFace2 != oppositeVertexFace2 )
 
 2016  Q_ASSERT( face1.count() == 3 );
 
 2017  Q_ASSERT( face2.count() == 3 );
 
 2022  int neighborFace1 = mFacesNeighborhood.at( faceIndex1 ).at( pos1 );
 
 2024  int neighborFace2 = mFacesNeighborhood.at( faceIndex1 ).at( ( pos1 + 1 ) % 3 );
 
 2026  int neighborFace3 = mFacesNeighborhood.at( faceIndex2 ).at( pos2 );
 
 2028  int neighborFace4 = mFacesNeighborhood.at( faceIndex2 ).at( ( pos2 + 1 ) % 3 );
 
 2039  changes.
mFacesToAdd.append( {oppositeVertexFace1, oppositeVertexFace2, vertexIndex1} );
 
 2040  changes.
mFacesToAdd.append( {oppositeVertexFace2, oppositeVertexFace1, vertexIndex2} );
 
 2042                                          mFacesNeighborhood.at( faceIndex2 ).at( ( pos2 + 1 ) % 3 ),
 
 2043                                          mFacesNeighborhood.at( faceIndex1 ).at( pos1 )
 
 2046                                          mFacesNeighborhood.at( faceIndex1 ).at( ( pos1 + 1 ) % 3 ),
 
 2047                                          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();
 
 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 )
 
 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 )
 
 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 );
 
 2272                                          mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 1 ) % faceSize ),
 
 2276                                          mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 2 ) % faceSize ),
 
 2277                                          mFacesNeighborhood.at( faceIndex ).at( ( splitVertexPos + 3 ) % faceSize )
 
 2280  for ( 
int i = 0; i < faceSize; ++i )
 
 2282    if ( neighborIndex[i] >= 0 )
 
 2283      changes.
mNeighborhoodChanges.append( {neighborIndex[i], posInNeighbor[i], faceIndex, startIndex + int( i / 2 )} );
 
 2285    int vertexIndex = face.at( ( splitVertexPos + i ) % faceSize );
 
 2286    if ( mVertexToFace.at( vertexIndex ) == faceIndex )
 
 
 2303  mVertexToFace.append( -1 );
 
 2307  const FaceNeighbors includingFaceNeighborhood = mFacesNeighborhood.at( includingFaceIndex );
 
 2308  int includingFaceSize = includingFace.count();
 
 2310  for ( 
int i = 0; i < includingFaceSize; ++i )
 
 2315    face[1] = includingFace.at( i );
 
 2316    face[2] = includingFace.at( ( i + 1 ) % includingFaceSize );
 
 2317    mMesh->
faces.append( face );
 
 2320    int currentVertexIndex = includingFace.at( i );
 
 2321    if ( mVertexToFace.at( currentVertexIndex ) == includingFaceIndex )
 
 2323      int newFaceIndex = mMesh->
faceCount() - 1;
 
 2324      mVertexToFace[currentVertexIndex] = newFaceIndex;
 
 2328    int includingFaceNeighbor = includingFaceNeighborhood.at( i );
 
 2332      includingFaceNeighbor,
 
 2335    mFacesNeighborhood.append( neighbors );
 
 2338    if ( includingFaceNeighbor != -1 )
 
 2341      int oldValue = mFacesNeighborhood[includingFaceNeighbor][indexInNeighbor];
 
 2353  mVertexToFace[mVertexToFace.count() - 1] = mMesh->
faceCount() - 1;
 
 
 2368  int newVertexPositionInFace1 = position + 1;
 
 2370  auto triangulate = [
this, &changes]( 
int removedFaceIndex, 
const QgsMeshVertex & newVertex, 
int newVertexPosition, QVector<int> &edgeFacesIndexes )->
bool 
 2376    const int addedVertexIndex = mMesh->
vertexCount();
 
 2379    int localStartIndex = changes.
mFacesToAdd.count();
 
 2381    QVector<int> newBoundary = initialFace;
 
 2382    newBoundary.insert( newVertexPosition, addedVertexIndex );
 
 2386      QHash<p2t::Point *, int> mapPoly2TriPointToVertex;
 
 2387      std::vector<p2t::Point *> faceToFill( newBoundary.count() );
 
 2388      for ( 
int i = 0; i < newBoundary.count(); ++i )
 
 2392        if ( newBoundary.at( i ) == addedVertexIndex )
 
 2395          vert = mMesh->
vertex( newBoundary.at( i ) );
 
 2397        faceToFill[i] = 
new p2t::Point( vert.
x(), vert.
y() );
 
 2398        mapPoly2TriPointToVertex.insert( faceToFill[i], newBoundary.at( i ) );
 
 2401      auto cdt = std::make_unique<p2t::CDT>( faceToFill );
 
 2403      std::vector<p2t::Triangle *> triangles = cdt->GetTriangles();
 
 2404      QVector<QgsMeshFace> newFaces( triangles.size() );
 
 2405      for ( 
size_t i = 0; i < triangles.size(); ++i )
 
 2409        for ( 
int j = 0; j < 3; j++ )
 
 2411          int vertInd = mapPoly2TriPointToVertex.value( triangles.at( i )->GetPoint( j ), -1 );
 
 2412          if ( vertInd == -1 )
 
 2413            throw std::exception();
 
 2421        throw std::exception();
 
 2427      const QList<int> &verticesToFaceToChange = topologicalFaces.mVerticesToFace.keys();
 
 2428      for ( 
const int vtc : verticesToFaceToChange )
 
 2429        if ( vtc != addedVertexIndex && mVertexToFace.at( vtc ) == removedFaceIndex )
 
 2434          topologicalFaces.
vertexToFace( vtc ) + faceStartGlobalIndex
 
 2438      for ( 
int i = 0; i < topologicalFaces.mFaces.count(); ++i )
 
 2441        for ( 
int n = 0; n < faceNeighbors.count(); ++n )
 
 2443          if ( faceNeighbors.at( n ) != -1 )
 
 2444            faceNeighbors[n] += faceStartGlobalIndex; 
 
 2448      edgeFacesIndexes.resize( 2 );
 
 2450      for ( 
int i = 0 ; i < newBoundary.count(); ++i )
 
 2452        int vertexIndex = newBoundary.at( i );
 
 2455        int newFaceBoundaryLocalIndex = localStartIndex + circulator.
currentFaceIndex();
 
 2457        int newFaceBoundaryIndexInMesh = faceStartGlobalIndex;
 
 2459        int meshFaceBoundaryIndex;
 
 2460        if ( i == newVertexPosition )
 
 2462          meshFaceBoundaryIndex = -1; 
 
 2463          edgeFacesIndexes[0] =  newFaceBoundaryLocalIndex;
 
 2465        else if ( i == ( newVertexPosition + newBoundary.count() - 1 ) % newBoundary.count() )
 
 2467          meshFaceBoundaryIndex = -1; 
 
 2468          edgeFacesIndexes[1] =  newFaceBoundaryLocalIndex;
 
 2476        if ( meshFaceBoundaryIndex != -1 )
 
 2480          positionInMeshFaceBoundary = ( positionInMeshFaceBoundary - 1 + meshFace.count() ) % meshFace.count(); 
 
 2483                                                positionInMeshFaceBoundary,
 
 2485                                                newFaceBoundaryIndexInMesh +
 
 2493      qDeleteAll( faceToFill );
 
 2503  QVector<int> edgeFacesIndexes;
 
 2504  if ( !triangulate( faceIndex, vertexToInsert, newVertexPositionInFace1, edgeFacesIndexes ) )
 
 2507  changes.mVertexToFaceToAdd.append( edgeFacesIndexes.at( 0 ) + changes.mAddedFacesFirstIndex );
 
 2512  int face2Index = mFacesNeighborhood.at( faceIndex ).at( position );
 
 2513  if ( face2Index != -1 )
 
 2517    QVector<int> edgeFacesIndexesFace2;
 
 2518    if ( !triangulate( face2Index, vertexToInsert, vertexPositionInFace2, edgeFacesIndexesFace2 ) )
 
 2522    const QgsMeshFace &firstFaceSide1 = changes.mFacesToAdd.at( edgeFacesIndexes.at( 0 ) );
 
 2525    const QgsMeshFace &secondFaceSide1 = changes.mFacesToAdd.at( edgeFacesIndexes.at( 1 ) );
 
 2527    pos2InFaceSide1 = ( pos2InFaceSide1 + secondFaceSide1.size() - 1 ) % secondFaceSide1.size();
 
 2529    const QgsMeshFace &firstFaceSide2 = changes.mFacesToAdd.at( edgeFacesIndexesFace2.at( 0 ) );
 
 2532    const QgsMeshFace &secondFaceSide2 = changes.mFacesToAdd.at( edgeFacesIndexesFace2.at( 1 ) );
 
 2534    pos2InFaceSide2 = ( pos2InFaceSide2 + secondFaceSide1.size() - 1 ) % secondFaceSide1.size();
 
 2536    changes.mFacesNeighborhoodToAdd[edgeFacesIndexes.at( 0 )][pos1InFaceSide1] = edgeFacesIndexesFace2.at( 1 ) + changes.mAddedFacesFirstIndex;
 
 2537    changes.mFacesNeighborhoodToAdd[edgeFacesIndexes.at( 1 )][pos2InFaceSide1] = edgeFacesIndexesFace2.at( 0 ) + changes.mAddedFacesFirstIndex;
 
 2538    changes.mFacesNeighborhoodToAdd[edgeFacesIndexesFace2.at( 0 )][pos1InFaceSide2] = edgeFacesIndexes.at( 1 ) + changes.mAddedFacesFirstIndex;
 
 2539    changes.mFacesNeighborhoodToAdd[edgeFacesIndexesFace2.at( 1 )][pos2InFaceSide2] = edgeFacesIndexes.at( 0 ) + changes.mAddedFacesFirstIndex;
 
 
 2548  Q_ASSERT( verticesIndexes.count() == newValues.count() );
 
 2551  changes.
mNewZValues.reserve( verticesIndexes.count() );
 
 2552  changes.
mOldZValues.reserve( verticesIndexes.count() );
 
 2553  for ( 
int i = 0; i < verticesIndexes.count(); ++i )
 
 
 2567  Q_ASSERT( verticesIndexes.count() == newValues.count() );
 
 2570  changes.
mNewXYValues.reserve( verticesIndexes.count() );
 
 2571  changes.
mOldXYValues.reserve( verticesIndexes.count() );
 
 2572  QSet<int> concernedFace;
 
 2573  for ( 
int i = 0; i < verticesIndexes.count(); ++i )
 
 2579    concernedFace.unite( QSet< int>( faces.begin(), faces.end() ) );
 
 
 2593  int oppositeVertexFace1;
 
 2594  int oppositeVertexFace2;
 
 2595  int supposedOppositeVertexFace1;
 
 2596  int supposedoppositeVertexFace2;
 
 2598  bool result =  eitherSideFacesAndVertices(
 
 2603                   oppositeVertexFace1,
 
 2604                   supposedoppositeVertexFace2,
 
 2605                   supposedOppositeVertexFace1,
 
 2606                   oppositeVertexFace2 );
 
 2615                     mMesh->
vertex( face1.at( 1 ) ),
 
 2616                     mMesh->
vertex( face1.at( 2 ) ) );
 
 2617  bool circle1ContainsPoint = circle.
contains( mMesh->
vertex( supposedoppositeVertexFace2 ) );
 
 2620                                   mMesh->
vertex( face2.at( 1 ) ),
 
 2621                                   mMesh->
vertex( face2.at( 2 ) ) );
 
 2622  bool circle2ContainsPoint = circle.
contains( mMesh->
vertex( supposedOppositeVertexFace1 ) );
 
 2624  return !( circle1ContainsPoint || circle2ContainsPoint );
 
 
@ 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.
bool contains(const QgsPoint &point, double epsilon=1E-8) const
Returns true if the circle contains the point.
static QgsCircle from3Points(const QgsPoint &pt1, const QgsPoint &pt2, const QgsPoint &pt3, double epsilon=1E-8)
Constructs a circle by 3 points on the circle.
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.
Represents an error which occurred during mesh editing.
Qgis::MeshEditingErrorType errorType
Convenience class that turns around a vertex and provides 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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
Adds a message to the log instance (and creates it if necessary).
Point geometry type, with support for z-dimension and m-values.
bool isEmpty() const override
Returns true if the geometry is empty.
Contains topological differences between two states of a topological mesh, only accessible from the Q...
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.
Contains independent faces and topological information about these 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.
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.
static int vertexPositionInFace(int vertexIndex, const QgsMeshFace &face)
Returns vertex position in face.
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 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 .
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.
bool delaunayConditionForEdge(int vertexIndex1, int vertexIndex2)
Check if Delaunay condition holds for given edge returns true if delaunay condition holds false other...
Represent a 2-dimensional 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.