30#include "meshOptimizer/meshoptimizer.h" 
   32static void ENP_centroid_step( 
const QPolygonF &pX, 
double &cx, 
double &cy, 
double &signedArea, 
int i, 
int i1 )
 
   44  a = x0 * y1 - x1 * y0;
 
   46  cx += ( x0 + x1 ) * a;
 
   47  cy += ( y0 + y1 ) * a;
 
   50static void ENP_centroid( 
const QPolygonF &pX, 
double &cx, 
double &cy )
 
   59  double signedArea = 0.0;
 
   61  const QPointF &pt0 = pX.first();
 
   62  QPolygonF localPolygon( pX.count() );
 
   63  for ( 
int i = 0; i < pX.count(); ++i )
 
   64    localPolygon[i] = pX.at( i ) - pt0;
 
   68  for ( ; i < localPolygon.size() - 1; ++i )
 
   70    ENP_centroid_step( localPolygon, cx, cy, signedArea, i, i + 1 );
 
   74  ENP_centroid_step( localPolygon, cx, cy, signedArea, i, 0 );
 
   77  cx /= ( 6.0 * signedArea );
 
   78  cy /= ( 6.0 * signedArea );
 
   84static void triangulateFaces( 
const QgsMeshFace &face,
 
   86                              QVector<QgsMeshFace> &destinationFaces,
 
   87                              QVector<int> &triangularToNative,
 
   88                              const QgsMesh &verticesMeshSource )
 
   90  int vertexCount = face.size();
 
   91  if ( vertexCount < 3 )
 
   94  while ( vertexCount > 3 )
 
   97    const QgsMeshFace ear = { face[vertexCount - 2], face[vertexCount - 1], face[0] };
 
   98    if ( !( std::isnan( verticesMeshSource.
vertex( ear[0] ).
x() )  ||
 
   99            std::isnan( verticesMeshSource.
vertex( ear[1] ).
x() )  ||
 
  100            std::isnan( verticesMeshSource.
vertex( ear[2] ).
x() ) ) )
 
  102      destinationFaces.push_back( ear );
 
  103      triangularToNative.push_back( nativeIndex );
 
  108  const QgsMeshFace triangle = { face[1], face[2], face[0] };
 
  109  if ( !( std::isnan( verticesMeshSource.
vertex( triangle[0] ).
x() )  ||
 
  110          std::isnan( verticesMeshSource.
vertex( triangle[1] ).
x() )  ||
 
  111          std::isnan( verticesMeshSource.
vertex( triangle[2] ).
x() ) ) )
 
  113    destinationFaces.push_back( triangle );
 
  114    triangularToNative.push_back( nativeIndex );
 
  118void QgsTriangularMesh::triangulate( 
const QgsMeshFace &face, 
int nativeIndex )
 
  120  triangulateFaces( face, nativeIndex, mTriangularMesh.
faces, mTrianglesToNativeFaces, mTriangularMesh );
 
  127  if ( mCoordinateTransform.
isValid() )
 
  131      transformedVertex.
transform( mCoordinateTransform, direction );
 
  141  return transformedVertex;
 
  146  return QgsMeshUtils::centroid( nativeFace, mTriangularMesh.
vertices );
 
  151  return mAverageTriangleSize;
 
 
  159  Q_ASSERT( nativeMesh );
 
  161  bool needUpdateVerticesCoordinates = mTriangularMesh.
vertices.size() != nativeMesh->
vertices.size() ||
 
  167  bool needUpdateFrame =  mTriangularMesh.
vertices.size() != nativeMesh->
vertices.size() ||
 
  168                          mNativeMeshFaceCentroids.size() != nativeMesh->
faces.size() ||
 
  169                          mTriangularMesh.
faces.size() < nativeMesh->
faces.size() ||
 
  170                          mTriangularMesh.
edges.size() != nativeMesh->
edges.size();
 
  174  if ( ! needUpdateVerticesCoordinates  && !needUpdateFrame )
 
  179  if ( needUpdateFrame )
 
  181    mTriangularMesh.
faces.clear();
 
  182    mTriangularMesh.
edges.clear();
 
  183    mEdgesToNativeEdges.clear();
 
  184    mTrianglesToNativeFaces.clear();
 
  188  mCoordinateTransform = transform;
 
  191  for ( 
int i = 0; i < nativeMesh->
vertices.size(); ++i )
 
  197  if ( needUpdateFrame )
 
  200    for ( 
int i = 0; i < nativeMesh->
faces.size(); ++i )
 
  203      triangulate( face, i );
 
  208  mNativeMeshFaceCentroids.resize( nativeMesh->
faces.size() );
 
  209  for ( 
int i = 0; i < nativeMesh->
faces.size(); ++i )
 
  212    mNativeMeshFaceCentroids[i] = calculateCentroid( face );
 
  218  if ( needUpdateFrame )
 
  226  if ( needUpdateFrame )
 
  228    const QVector<QgsMeshEdge> 
edges = nativeMesh->
edges;
 
  229    for ( 
int nativeIndex = 0; nativeIndex < 
edges.size(); ++nativeIndex )
 
  232      if ( !( std::isnan( mTriangularMesh.
vertex( edge.first ).
x() )  ||
 
  233              std::isnan( mTriangularMesh.
vertex( edge.second ).
x() ) ) )
 
  235        mTriangularMesh.
edges.push_back( edge );
 
  236        mEdgesToNativeEdges.push_back( nativeIndex );
 
  242  mNativeMeshEdgeCentroids.resize( nativeMesh->
edgeCount() );
 
  243  for ( 
int i = 0; i < nativeMesh->
edgeCount(); ++i )
 
  248    mNativeMeshEdgeCentroids[i] = 
QgsMeshVertex( ( a.
x() + b.
x() ) / 2.0, ( a.
y() + b.
y() ) / 2.0, ( a.
z() + b.
z() ) / 2.0 );
 
 
  259  return update( nativeMesh, mCoordinateTransform );
 
 
  262void QgsTriangularMesh::finalizeTriangles()
 
  264  mAverageTriangleSize = 0;
 
  265  for ( 
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
 
  273    QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( v0, v1, v2 );
 
  275    mAverageTriangleSize += std::fmax( bbox.
width(), bbox.
height() );
 
  277    QgsMeshUtils::setCounterClockwise( face, v0, v1, v2 );
 
  279  mAverageTriangleSize /= mTriangularMesh.
faceCount();
 
  317  if ( !mIsExtentValid )
 
  320    for ( 
int i = 0; i < mTriangularMesh.
vertices.size(); ++i )
 
  321      if ( !mTriangularMesh.
vertices.at( i ).isEmpty() )
 
  324    mIsExtentValid = 
true;
 
 
  349void QgsTriangularMesh::addVertex( 
const QgsMeshVertex &vertex )
 
  352  mTriangularMesh.
vertices.append( vertexInTriangularCoordinates );
 
  353  if ( !vertexInTriangularCoordinates.
isEmpty() )
 
  354    mExtent.
include( vertexInTriangularCoordinates );
 
  364  return mTriangularMesh.
faces;
 
 
  369  return mTriangularMesh.
edges;
 
 
  379  return mNativeMeshFaceCentroids;
 
 
  384  return mNativeMeshEdgeCentroids;
 
 
  389  return mTrianglesToNativeFaces;
 
 
  394  return mEdgesToNativeEdges;
 
 
  400  if ( mCoordinateTransform.
isValid() )
 
  404      mapPoint = mCoordinateTransform.
transform( point );
 
 
  422  for ( 
const int faceIndex : faceIndexes )
 
 
  435  if ( triangleIndex == -1 )
 
  438  if ( triangleIndex < mTrianglesToNativeFaces.count() )
 
  439    return mTrianglesToNativeFaces.at( triangleIndex );
 
 
  446  QSet<int> concernedFaceIndex = QgsMeshUtils::nativeFacesFromTriangles(
 
  449  return concernedFaceIndex.values();
 
 
  456  for ( 
const int faceIndex : faceIndexes )
 
  459    if ( QgsMeshUtils::isInTriangleFace( point, face, mTriangularMesh.
vertices ) )
 
 
  467  return mSpatialFaceIndex.
intersects( rectangle );
 
 
  472  return mSpatialEdgeIndex.
intersects( rectangle );
 
 
  477  QVector<QVector3D> normals( 
vertices().count(), QVector3D( 0, 0, 0 ) );
 
  481    if ( face.isEmpty() )
 
  484    for ( 
int i = 0; i < 3; i++ )
 
  486      int index1( face.at( i ) );
 
  487      int index2( face.at( ( i + 1 ) % 3 ) );
 
  488      int index3( face.at( ( i + 2 ) % 3 ) );
 
  494      QVector3D v1( 
float( otherVert1.
x() - vert.
x() ), 
float( otherVert1.
y() - vert.
y() ), vertScale * 
float( otherVert1.
z() - vert.
z() ) );
 
  495      QVector3D v2( 
float( otherVert2.
x() - vert.
x() ), 
float( otherVert2.
y() - vert.
y() ), vertScale * 
float( otherVert2.
z() - vert.
z() ) );
 
  497      normals[index1] += QVector3D::crossProduct( v1, v2 );
 
 
  505  QVector<QgsTriangularMesh *> simplifiedMeshes;
 
  508    return simplifiedMeshes;
 
  510  if ( !( reductionFactor > 1 ) )
 
  511    return simplifiedMeshes;
 
  513  size_t verticesCount = size_t( mTriangularMesh.
vertices.count() );
 
  515  unsigned int baseIndexCount = mTriangularMesh.
faceCount() * 3;
 
  517  QVector<unsigned int> indexes( mTriangularMesh.
faces.count() * 3 );
 
  518  for ( 
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
 
  521    for ( 
int j = 0; j < 3; ++j )
 
  522      indexes[i * 3 + j] = f.at( j );
 
  526  for ( 
int i = 0; i < mTriangularMesh.
vertices.count(); ++i )
 
  538    size_t maxNumberOfIndexes = baseIndexCount / pow( reductionFactor, path + 1 );
 
  540    if ( indexes.size() <= 
int( maxNumberOfIndexes ) )
 
  542      delete simplifiedMesh;
 
  546    QVector<unsigned int> returnIndexes( indexes.size() );
 
  548    size_t size = meshopt_simplifySloppy(
 
  549                    returnIndexes.data(),
 
  555                    maxNumberOfIndexes );
 
  558    returnIndexes.resize( size );
 
  560    if ( size == 0 || 
int( size ) >= indexes.size() )
 
  562      QgsDebugError( QStringLiteral( 
"Mesh simplification failed after %1 path" ).arg( path + 1 ) );
 
  563      delete simplifiedMesh;
 
  570    newMesh.
faces.resize( returnIndexes.size() / 3 );
 
  571    for ( 
int i = 0; i < newMesh.
faces.size(); ++i )
 
  574      for ( 
size_t j = 0; j < 3 ; ++j )
 
  575        f[j] = returnIndexes.at( i * 3 + j ) ;
 
  576      newMesh.
faces[i ] = f;
 
  579    simplifiedMesh->mTriangularMesh = newMesh;
 
  580    simplifiedMesh->mSpatialFaceIndex = 
QgsMeshSpatialIndex( simplifiedMesh->mTriangularMesh );
 
  581    simplifiedMesh->finalizeTriangles();
 
  582    simplifiedMeshes.push_back( simplifiedMesh );
 
  586    simplifiedMesh->mTrianglesToNativeFaces = QVector<int>( simplifiedMesh->
triangles().count(), 0 );
 
  587    for ( 
int i = 0; i < simplifiedMesh->mTrianglesToNativeFaces.count(); ++i )
 
  592      for ( 
size_t j = 0; j < 3 ; ++j )
 
  594        x += mTriangularMesh.
vertex( triangle[j] ).
x();
 
  595        y += mTriangularMesh.
vertex( triangle[j] ).
y();
 
  602      if ( indexInBaseMesh == -1 )
 
  607        while ( indexInBaseMesh == -1 && j < 3 )
 
  611      if ( indexInBaseMesh > -1 && indexInBaseMesh < mTrianglesToNativeFaces.count() )
 
  612        simplifiedMesh->mTrianglesToNativeFaces[i] = mTrianglesToNativeFaces[indexInBaseMesh];
 
  615    simplifiedMesh->mLod = path + 1;
 
  616    simplifiedMesh->mBaseTriangularMesh = 
this;
 
  618    if ( simplifiedMesh->
triangles().count() <  minimumTrianglesCount )
 
  621    indexes = returnIndexes;
 
  625  return simplifiedMeshes;
 
 
  628std::unique_ptr< QgsPolygon > QgsMeshUtils::toPolygon( 
const QgsMeshFace &face, 
const QVector<QgsMeshVertex> &vertices )
 
  630  QVector<QgsPoint> ring;
 
  631  for ( 
int j = 0; j < face.size(); ++j )
 
  633    int vertexId = face[j];
 
  634    Q_ASSERT( vertexId < vertices.size() );
 
  635    const QgsPoint &vertex = vertices[vertexId];
 
  636    ring.append( vertex );
 
  638  auto polygon = std::make_unique< QgsPolygon >();
 
  645  return QgsGeometry( QgsMeshUtils::toPolygon( face, vertices ) );
 
  648static QSet<int> _nativeElementsFromElements( 
const QList<int> &indexes, 
const QVector<int> &elementToNativeElements )
 
  650  QSet<int> nativeElements;
 
  651  for ( 
const int index : indexes )
 
  653    if ( index < elementToNativeElements.count() )
 
  655      const int nativeIndex = elementToNativeElements[index];
 
  656      nativeElements.insert( nativeIndex );
 
  659  return nativeElements;
 
  662QSet<int> QgsMeshUtils::nativeFacesFromTriangles( 
const QList<int> &triangleIndexes, 
const QVector<int> &trianglesToNativeFaces )
 
  664  return _nativeElementsFromElements( triangleIndexes, trianglesToNativeFaces );
 
  667QSet<int> QgsMeshUtils::nativeEdgesFromEdges( 
const QList<int> &edgesIndexes, 
const QVector<int> &edgesToNativeEdges )
 
  669  return _nativeElementsFromElements( edgesIndexes, edgesToNativeEdges );
 
  675  return ( p2.
x() - p1.
x() ) * ( p.
y() - p1.
y() ) - ( p.
x() - p1.
x() ) * ( p2.
y() - p1.
y() );
 
  678static bool _isInTriangle2D( 
const QgsPoint &p, 
const QVector<QgsMeshVertex> &triangle )
 
  680  return ( ( _isLeft2D( triangle[2], triangle[0], p ) * _isLeft2D( triangle[2], triangle[0], triangle[1] ) >= 0 )
 
  681           && ( _isLeft2D( triangle[0], triangle[1], p ) * _isLeft2D( triangle[0], triangle[1], triangle[2] ) >= 0 )
 
  682           && ( _isLeft2D( triangle[2], triangle[1], p ) * _isLeft2D( triangle[2], triangle[1], triangle[0] ) >= 0 ) );
 
  685bool QgsMeshUtils::isInTriangleFace( 
const QgsPointXY point, 
const QgsMeshFace &face, 
const QVector<QgsMeshVertex> &vertices )
 
  687  if ( face.count() != 3 )
 
  690  QVector<QgsMeshVertex> triangle( 3 );
 
  691  for ( 
int i = 0; i < 3; ++i )
 
  693    if ( face[i] >= vertices.count() )
 
  695    triangle[i] = vertices[face[i]];
 
  700  return _isInTriangle2D( p, triangle );
 
  703QSet<int> QgsMeshUtils::nativeVerticesFromTriangles( 
const QList<int> &triangleIndexes, 
const QVector<QgsMeshFace> &triangles )
 
  705  QSet<int> uniqueVertices;
 
  706  for ( 
int triangleIndex : triangleIndexes )
 
  708    const QgsMeshFace triangle = triangles[triangleIndex];
 
  709    for ( 
int i : triangle )
 
  711      uniqueVertices.insert( i );
 
  714  return uniqueVertices;
 
  717QSet<int> QgsMeshUtils::nativeVerticesFromEdges( 
const QList<int> &edgesIndexes, 
const QVector<QgsMeshEdge> &edges )
 
  719  QSet<int> uniqueVertices;
 
  720  for ( 
int edgeIndex : edgesIndexes )
 
  723    uniqueVertices.insert( edge.first );
 
  724    uniqueVertices.insert( edge.second );
 
  726  return uniqueVertices;
 
  732  if ( changes.mRemovedTriangleIndexes.isEmpty() && !changes.mNativeFaceIndexesToRemove.isEmpty() )
 
  734    for ( 
int nf = 0; nf < changes.mNativeFaceIndexesToRemove.count(); ++nf )
 
  736      int nativeIndex = changes.mNativeFaceIndexesToRemove.at( nf );
 
  737      const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( nf );
 
  738      Q_ASSERT( !nativeFace.isEmpty() );
 
  740      QgsRectangle nativeFaceExtent( mTriangularMesh.
vertex( nativeFace.at( 0 ) ), mTriangularMesh.
vertex( nativeFace.at( 0 ) ) );
 
  741      for ( 
int i = 1; i < nativeFace.count(); ++i )
 
  744        nativeFaceExtent.
include( triangularVertex );
 
  749      for ( 
int i = 0; i < concernedTriangle.count(); ++i )
 
  751        int triangleIndex = concernedTriangle.at( i );
 
  752        if ( mTrianglesToNativeFaces.at( triangleIndex ) == nativeIndex )
 
  753          changes.mRemovedTriangleIndexes.append( triangleIndex );
 
  758  if ( changes.mOldZValue.isEmpty() && !changes.mNewZValue.isEmpty() )
 
  760    changes.mOldZValue.reserve( changes.mNewZValue.count() );
 
  761    for ( 
int i = 0; i < changes.mNewZValue.count(); ++i )
 
  762      changes.mOldZValue.append( mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
 
  765  if ( changes.mTriangleIndexesGeometryChanged.isEmpty() && !changes.mNativeFaceIndexesGeometryChanged.isEmpty() )
 
  767    for ( 
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
 
  769      const QgsMeshFace &nativeFace = changes.mNativeFacesGeometryChanged.at( i );
 
  770      if ( nativeFace.count() < 2 )
 
  774      for ( 
int i = 2; i < nativeFace.count(); ++i )
 
  779      while ( pos < triangleIndexes.count() )
 
  782             changes.mNativeFaceIndexesGeometryChanged.at( i ) )
 
  783          triangleIndexes.removeAt( pos );
 
  787      changes.mTriangleIndexesGeometryChanged.append( triangleIndexes );
 
  792  for ( 
const QgsMeshVertex &vertex : std::as_const( changes.mAddedVertices ) )
 
  796  if ( !changes.mNativeFacesToAdd.isEmpty() )
 
  798    changes.mTrianglesAddedStartIndex = mTriangularMesh.
faceCount();
 
  799    int firstNewNativeFacesIndex = mNativeMeshFaceCentroids.count();
 
  800    for ( 
int i = 0; i < changes.mNativeFacesToAdd.count(); ++i )
 
  802      const QgsMeshFace &nativeFace = changes.mNativeFacesToAdd.at( i );
 
  803      triangulate( nativeFace, firstNewNativeFacesIndex + i );
 
  804      mNativeMeshFaceCentroids.append( calculateCentroid( nativeFace ) );
 
  807    for ( 
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
 
  808      mSpatialFaceIndex.
addFace( i, mTriangularMesh );
 
  812  for ( 
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
 
  814    int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
 
  815    mTrianglesToNativeFaces[triangleIndex] = -1;
 
  816    mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
 
  820  for ( 
int i = 0; i < changes.mNativeFaceIndexesToRemove.count(); ++i )
 
  821    mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = 
QgsMeshVertex();
 
  824  for ( 
int i = 0; i < changes.mVerticesIndexesToRemove.count(); ++i )
 
  827  if ( !changes.mVerticesIndexesToRemove.isEmpty() )
 
  828    mIsExtentValid = 
false;
 
  831  for ( 
int i = 0; i < changes.mNewZValue.count(); ++i )
 
  833    int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
 
  834    mTriangularMesh.
vertices[vertexIndex].setZ( changes.mNewZValue.at( i ) );
 
  838  for ( 
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
 
  839    mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
 
  842  for ( 
int i = 0; i < changes.mNewXYValue.count(); ++i )
 
  844    const QgsPointXY &nativeCoordinates = changes.mNewXYValue.at( i );
 
  846                                      nativeCoordinates.
y(),
 
  847                                      mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
 
  853  for ( 
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
 
  854    mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
 
  857  for ( 
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
 
  858    mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
 
 
  864  if ( !changes.mNativeFacesToAdd.isEmpty() )
 
  866    for ( 
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
 
  867      mSpatialFaceIndex.
removeFace( i, mTriangularMesh );
 
  869    int initialNativeFacesCount = mNativeMeshFaceCentroids.count() - changes.mNativeFacesToAdd.count();
 
  871    mTriangularMesh.
faces.resize( changes.mTrianglesAddedStartIndex );
 
  872    mTrianglesToNativeFaces.resize( changes.mTrianglesAddedStartIndex );
 
  873    mNativeMeshFaceCentroids.resize( initialNativeFacesCount );
 
  876  int initialVerticesCount = mTriangularMesh.
vertices.count() - changes.mAddedVertices.count();
 
  877  mTriangularMesh.
vertices.resize( initialVerticesCount );
 
  879  if ( !changes.mAddedVertices.isEmpty() )
 
  880    mIsExtentValid = 
false;
 
  883  for ( 
const int i : std::as_const( changes.mVerticesIndexesToRemove ) )
 
  886  if ( !changes.mVerticesIndexesToRemove.isEmpty() )
 
  887    mIsExtentValid = 
false;
 
  890  QVector<QgsMeshFace> restoredTriangles;
 
  891  QVector<int> restoredTriangularToNative;
 
  892  for ( 
int i = 0; i < changes.mNativeFacesToRemove.count(); ++i )
 
  894    const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( i );
 
  895    triangulateFaces( nativeFace,
 
  896                      changes.mNativeFaceIndexesToRemove.at( i ),
 
  898                      restoredTriangularToNative,
 
  900    mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = calculateCentroid( nativeFace );
 
  902  for ( 
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
 
  904    int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
 
  905    mTriangularMesh.
faces[triangleIndex] = restoredTriangles.at( i );
 
  906    mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
 
  907    mTrianglesToNativeFaces[triangleIndex] = restoredTriangularToNative.at( i );
 
  911  for ( 
int i = 0; i < changes.mOldZValue.count(); ++i )
 
  913    int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
 
  914    mTriangularMesh.
vertices[vertexIndex].setZ( changes.mOldZValue.at( i ) );
 
  918  for ( 
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
 
  919    mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
 
  922  for ( 
int i = 0; i < changes.mOldXYValue.count(); ++i )
 
  924    const QgsPointXY &nativeCoordinates = changes.mOldXYValue.at( i );
 
  926                                      nativeCoordinates.
y(),
 
  927                                      mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
 
  933  for ( 
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
 
  934    mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
 
  937  for ( 
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
 
  938    mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
 
 
  946  mNativeFacesToAdd = topologicalChanges.
addedFaces();
 
  947  mNativeFacesToRemove = topologicalChanges.
removedFaces();
 
  955  mNativeFacesGeometryChanged.resize( mNativeFaceIndexesGeometryChanged.count() );
 
  956  for ( 
int i = 0; i < mNativeFaceIndexesGeometryChanged.count(); ++i )
 
  957    mNativeFacesGeometryChanged[i] = nativeMesh.
face( mNativeFaceIndexesGeometryChanged.at( i ) );
 
 
  962  QVector<QPointF> points( face.size() );
 
  963  for ( 
int j = 0; j < face.size(); ++j )
 
  965    int index = face.at( j );
 
  969  QPolygonF poly( points );
 
  971  ENP_centroid( poly, cx, cy );
 
  979  double ux = v1.
x() - v0.
x();
 
  980  double uy = v1.
y() - v0.
y();
 
  981  double vx = v2.
x() - v0.
x();
 
  982  double vy = v2.
y() - v0.
y();
 
  984  double crossProduct = ux * vy - uy * vx;
 
  985  if ( crossProduct < 0 ) 
 
  987    std::swap( triangle[1], triangle[2] );
 
TransformDirection
Indicates the direction (forward or inverse) of a transform.
 
@ Forward
Forward transform (from source to destination)
 
@ Reverse
Reverse/inverse transform (from destination to source)
 
Custom exception class for Coordinate Reference System related exceptions.
 
A geometry is the spatial representation of a feature.
 
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
 
Line string geometry type, with support for z-dimension and m-values.
 
A spatial index for QgsMeshFace or QgsMeshEdge objects.
 
QList< int > intersects(const QgsRectangle &rectangle) const
Returns a list of face ids with a bounding box which intersects the specified rectangle.
 
void addFace(int faceIndex, const QgsMesh &mesh)
Adds a face with faceIndex from the mesh in the spatial index.
 
void removeFace(int faceIndex, const QgsMesh &mesh)
Removes a face with faceIndex from the mesh in the spatial index.
 
A class to represent a 2D point.
 
Point geometry type, with support for z-dimension and m-values.
 
QPointF toQPointF() const
Returns the point as a QPointF.
 
bool isEmpty() const override
Returns true if the geometry is empty.
 
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override
Transforms the geometry using a coordinate transform.
 
A rectangle specified with double values.
 
void include(const QgsPointXY &p)
Updates the rectangle to include the specified point.
 
void setNull()
Mark a rectangle as being null (holding no spatial information).
 
Class that contains topological differences between two states of a topological mesh,...
 
QVector< QgsMeshFace > removedFaces() const
Returns the faces that are removed with this changes.
 
QVector< QgsMeshVertex > addedVertices() const
Returns the added vertices with this changes.
 
QList< int > changedCoordinatesVerticesIndexes() const
Returns the indexes of vertices that have changed coordinates.
 
QList< int > removedFaceIndexes() const
Returns the indexes of the faces that are removed with this changes.
 
QList< double > newVerticesZValues() const
Returns the new Z values of vertices that have changed their coordinates.
 
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.
 
QList< QgsPointXY > newVerticesXYValues() const
Returns the new (X,Y) values of vertices that have changed their coordinates.
 
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.
 
The Changes class is used to make changes of the triangular and to keep traces of this changes If a C...
 
Changes()=default
Default constructor, no changes.
 
Triangular/Derived Mesh is mesh with vertices in map coordinates.
 
const QVector< QgsMeshVertex > & edgeCentroids() const
Returns centroids of the native edges in map CRS.
 
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
 
QVector< QgsTriangularMesh * > simplifyMesh(double reductionFactor, int minimumTrianglesCount=10) const
Returns simplified meshes.
 
QgsRectangle nativeExtent()
Returns the extent of the mesh in the native mesh coordinates system, returns empty extent if the tra...
 
QgsPointXY transformFromLayerToTrianglesCoordinates(const QgsPointXY &point) const
Transforms a point from layer coordinates system to triangular Mesh coordinates system.
 
int levelOfDetail() const
Returns the corresponding index of level of detail on which this mesh is associated.
 
QgsRectangle extent() const
Returns the extent of the triangular mesh in map coordinates.
 
int faceIndexForPoint(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing.
 
int nativeFaceIndexForPoint(const QgsPointXY &point) const
Finds index of native face at given point It uses spatial indexing.
 
double averageTriangleSize() const
Returns the average size of triangles in map unit.
 
void reverseChanges(const Changes &changes, const QgsMesh &nativeMesh)
Reverses the changes on the triangular mesh (see Changes)
 
void applyChanges(const Changes &changes)
Applies the changes on the triangular mesh (see Changes)
 
QList< int > edgeIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of edges intersecting given bounding box It uses spatial indexing.
 
Q_DECL_DEPRECATED const QVector< QgsMeshVertex > & centroids() const
Returns centroids of the native faces in map CRS.
 
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
 
const QVector< QgsMeshEdge > & edges() const
Returns edges.
 
bool contains(const QgsMesh::ElementType &type) const
Returns whether the mesh contains mesh elements of given type.
 
QgsMeshVertex triangularToNativeCoordinates(const QgsMeshVertex &vertex) const
Transforms the vertex from triangular mesh coordinates system to native coordinates system.
 
QVector< QVector3D > vertexNormals(float vertScale) const
Calculates and returns normal vector on each vertex that is part of any face.
 
QgsMeshVertex nativeToTriangularCoordinates(const QgsMeshVertex &vertex) const
Transforms the vertex from native coordinates system to triangular mesh coordinates system.
 
bool update(QgsMesh *nativeMesh, const QgsCoordinateTransform &transform)
Constructs triangular mesh from layer's native mesh and transform to destination CRS.
 
const QVector< QgsMeshVertex > & faceCentroids() const
Returns centroids of the native faces in map CRS.
 
QList< int > nativeFaceIndexForRectangle(const QgsRectangle &rectangle) const
Finds indexes of native faces which bounding boxes intersect given bounding box It uses spatial index...
 
const QVector< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
 
const QVector< int > & edgesToNativeEdges() const
Returns mapping between edges and original edges.
 
QList< int > faceIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of triangles intersecting given bounding box It uses spatial indexing.
 
int faceIndexForPoint_v2(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing and don't use geos to be faster.
 
#define QgsDebugMsgLevel(str, level)
 
#define QgsDebugError(str)
 
QVector< int > QgsMeshFace
List of vertex indexes.
 
QPair< int, int > QgsMeshEdge
Edge is a straight line seqment between 2 points.
 
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.
 
ElementType
Defines type of mesh elements.
 
QgsMeshVertex vertex(int index) const
Returns a vertex at the index.
 
int edgeCount() const
Returns number of edge.
 
QVector< QgsMeshEdge > edges