20#include "meshoptimizer.h"
32using namespace Qt::StringLiterals;
34static void triangulateFaces(
const QgsMeshFace &face,
36 QVector<QgsMeshFace> &destinationFaces,
37 QVector<int> &triangularToNative,
38 const QgsMesh &verticesMeshSource )
40 int vertexCount = face.size();
41 if ( vertexCount < 3 )
44 while ( vertexCount > 3 )
47 const QgsMeshFace ear = { face[vertexCount - 2], face[vertexCount - 1], face[0] };
48 if ( !( std::isnan( verticesMeshSource.
vertex( ear[0] ).
x() ) ||
49 std::isnan( verticesMeshSource.
vertex( ear[1] ).
x() ) ||
50 std::isnan( verticesMeshSource.
vertex( ear[2] ).
x() ) ) )
52 destinationFaces.push_back( ear );
53 triangularToNative.push_back( nativeIndex );
58 const QgsMeshFace triangle = { face[1], face[2], face[0] };
59 if ( !( std::isnan( verticesMeshSource.
vertex( triangle[0] ).
x() ) ||
60 std::isnan( verticesMeshSource.
vertex( triangle[1] ).
x() ) ||
61 std::isnan( verticesMeshSource.
vertex( triangle[2] ).
x() ) ) )
63 destinationFaces.push_back( triangle );
64 triangularToNative.push_back( nativeIndex );
68void QgsTriangularMesh::triangulate(
const QgsMeshFace &face,
int nativeIndex )
70 triangulateFaces( face, nativeIndex, mTriangularMesh.faces, mTrianglesToNativeFaces, mTriangularMesh );
77 if ( mCoordinateTransform.isValid() )
81 transformedVertex.
transform( mCoordinateTransform, direction );
83 catch ( QgsCsException &cse )
91 return transformedVertex;
101 return mAverageTriangleSize;
109 Q_ASSERT( nativeMesh );
111 bool needUpdateVerticesCoordinates = mTriangularMesh.vertices.size() != nativeMesh->
vertices.size() ||
112 ( ( mCoordinateTransform.isValid() || transform.
isValid() ) &&
113 ( mCoordinateTransform.sourceCrs() != transform.
sourceCrs() ||
114 mCoordinateTransform.destinationCrs() != transform.
destinationCrs() ||
117 bool needUpdateFrame = mTriangularMesh.vertices.size() != nativeMesh->
vertices.size() ||
118 mNativeMeshFaceCentroids.size() != nativeMesh->
faces.size() ||
119 mTriangularMesh.faces.size() < nativeMesh->
faces.size() ||
120 mTriangularMesh.edges.size() != nativeMesh->
edges.size();
124 if ( ! needUpdateVerticesCoordinates && !needUpdateFrame )
128 mTriangularMesh.vertices.clear();
129 if ( needUpdateFrame )
131 mTriangularMesh.faces.clear();
132 mTriangularMesh.edges.clear();
133 mEdgesToNativeEdges.clear();
134 mTrianglesToNativeFaces.clear();
138 mCoordinateTransform = transform;
139 mTriangularMesh.vertices.resize( nativeMesh->
vertices.size() );
141 for (
int i = 0; i < nativeMesh->
vertices.size(); ++i )
144 mExtent.include( mTriangularMesh.vertices.at( i ) );
147 if ( needUpdateFrame )
150 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
153 triangulate( face, i );
158 mNativeMeshFaceCentroids.resize( nativeMesh->
faces.size() );
159 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
162 mNativeMeshFaceCentroids[i] = calculateCentroid( face );
168 if ( needUpdateFrame )
176 if ( needUpdateFrame )
178 const QVector<QgsMeshEdge>
edges = nativeMesh->
edges;
179 for (
int nativeIndex = 0; nativeIndex <
edges.size(); ++nativeIndex )
182 if ( !( std::isnan( mTriangularMesh.vertex( edge.first ).x() ) ||
183 std::isnan( mTriangularMesh.vertex( edge.second ).x() ) ) )
185 mTriangularMesh.edges.push_back( edge );
186 mEdgesToNativeEdges.push_back( nativeIndex );
192 mNativeMeshEdgeCentroids.resize( nativeMesh->
edgeCount() );
193 for (
int i = 0; i < nativeMesh->
edgeCount(); ++i )
198 mNativeMeshEdgeCentroids[i] =
QgsMeshVertex( ( a.
x() + b.
x() ) / 2.0, ( a.
y() + b.
y() ) / 2.0, ( a.
z() + b.
z() ) / 2.0 );
209 return update( nativeMesh, mCoordinateTransform );
212void QgsTriangularMesh::finalizeTriangles()
214 mAverageTriangleSize = 0;
215 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
223 QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( v0, v1, v2 );
225 mAverageTriangleSize += std::fmax( bbox.
width(), bbox.
height() );
229 mAverageTriangleSize /= mTriangularMesh.faceCount();
245 if ( !mCoordinateTransform.isShortCircuited() )
267 if ( !mIsExtentValid )
270 for (
int i = 0; i < mTriangularMesh.vertices.size(); ++i )
271 if ( !mTriangularMesh.vertices.at( i ).isEmpty() )
272 mExtent.include( mTriangularMesh.vertices.at( i ) );
274 mIsExtentValid =
true;
289 return mTriangularMesh.vertexCount() != 0;
291 return mTriangularMesh.edgeCount() != 0;
293 return mTriangularMesh.faceCount() != 0;
299void QgsTriangularMesh::addVertex(
const QgsMeshVertex &vertex )
302 mTriangularMesh.
vertices.append( vertexInTriangularCoordinates );
303 if ( !vertexInTriangularCoordinates.
isEmpty() )
304 mExtent.
include( vertexInTriangularCoordinates );
309 return mTriangularMesh.vertices;
314 return mTriangularMesh.faces;
319 return mTriangularMesh.edges;
329 return mNativeMeshFaceCentroids;
334 return mNativeMeshEdgeCentroids;
339 return mTrianglesToNativeFaces;
344 return mEdgesToNativeEdges;
350 if ( mCoordinateTransform.isValid() )
354 mapPoint = mCoordinateTransform.transform( point );
371 const QList<int> faceIndexes = mSpatialFaceIndex.intersects(
QgsRectangle( point, point ) );
372 for (
const int faceIndex : faceIndexes )
374 const QgsMeshFace &face = mTriangularMesh.faces.at( faceIndex );
385 if ( triangleIndex == -1 )
388 if ( triangleIndex < mTrianglesToNativeFaces.count() )
389 return mTrianglesToNativeFaces.at( triangleIndex );
399 return concernedFaceIndex.values();
404 const QList<int> faceIndexes = mSpatialFaceIndex.intersects(
QgsRectangle( point, point ) );
406 for (
const int faceIndex : faceIndexes )
408 const QgsMeshFace &face = mTriangularMesh.faces.at( faceIndex );
417 return mSpatialFaceIndex.intersects( rectangle );
422 return mSpatialEdgeIndex.intersects( rectangle );
427 QVector<QVector3D> normals(
vertices().count(), QVector3D( 0, 0, 0 ) );
431 if ( face.isEmpty() )
434 for (
int i = 0; i < 3; i++ )
436 int index1( face.at( i ) );
437 int index2( face.at( ( i + 1 ) % 3 ) );
438 int index3( face.at( ( i + 2 ) % 3 ) );
444 QVector3D v1(
float( otherVert1.
x() - vert.
x() ),
float( otherVert1.
y() - vert.
y() ), vertScale *
float( otherVert1.
z() - vert.
z() ) );
445 QVector3D v2(
float( otherVert2.
x() - vert.
x() ),
float( otherVert2.
y() - vert.
y() ), vertScale *
float( otherVert2.
z() - vert.
z() ) );
447 normals[index1] += QVector3D::crossProduct( v1, v2 );
455 QVector<QgsTriangularMesh *> simplifiedMeshes;
457 if ( mTriangularMesh.edgeCount() != 0 )
458 return simplifiedMeshes;
460 if ( !( reductionFactor > 1 ) )
461 return simplifiedMeshes;
463 size_t verticesCount = size_t( mTriangularMesh.vertices.count() );
465 unsigned int baseIndexCount = mTriangularMesh.faceCount() * 3;
467 QVector<unsigned int> indexes( mTriangularMesh.faces.count() * 3 );
468 for (
int i = 0; i < mTriangularMesh.faceCount(); ++i )
471 for (
int j = 0; j < 3; ++j )
472 indexes[i * 3 + j] = f.at( j );
475 QVector<float>
vertices( mTriangularMesh.vertices.count() * 3 );
476 for (
int i = 0; i < mTriangularMesh.vertices.count(); ++i )
488 size_t maxNumberOfIndexes = baseIndexCount / pow( reductionFactor, path + 1 );
490 if ( indexes.size() <=
int( maxNumberOfIndexes ) )
492 delete simplifiedMesh;
496 QVector<unsigned int> returnIndexes( indexes.size() );
498 size_t size = meshopt_simplifySloppy(
499 returnIndexes.data(),
506#
if MESHOPTIMIZER_VERSION > 150
513 returnIndexes.resize( size );
515 if ( size == 0 ||
int( size ) >= indexes.size() )
517 QgsDebugError( u
"Mesh simplification failed after %1 path"_s.arg( path + 1 ) );
518 delete simplifiedMesh;
523 newMesh.
vertices = mTriangularMesh.vertices;
525 newMesh.
faces.resize( returnIndexes.size() / 3 );
526 for (
int i = 0; i < newMesh.
faces.size(); ++i )
529 for (
size_t j = 0; j < 3 ; ++j )
530 f[j] = returnIndexes.at( i * 3 + j ) ;
531 newMesh.
faces[i ] = f;
534 simplifiedMesh->mTriangularMesh = newMesh;
535 simplifiedMesh->mSpatialFaceIndex =
QgsMeshSpatialIndex( simplifiedMesh->mTriangularMesh );
536 simplifiedMesh->finalizeTriangles();
537 simplifiedMeshes.push_back( simplifiedMesh );
541 simplifiedMesh->mTrianglesToNativeFaces = QVector<int>( simplifiedMesh->
triangles().count(), 0 );
542 for (
int i = 0; i < simplifiedMesh->mTrianglesToNativeFaces.count(); ++i )
547 for (
size_t j = 0; j < 3 ; ++j )
549 x += mTriangularMesh.vertex( triangle[j] ).x();
550 y += mTriangularMesh.vertex( triangle[j] ).y();
557 if ( indexInBaseMesh == -1 )
562 while ( indexInBaseMesh == -1 && j < 3 )
566 if ( indexInBaseMesh > -1 && indexInBaseMesh < mTrianglesToNativeFaces.count() )
567 simplifiedMesh->mTrianglesToNativeFaces[i] = mTrianglesToNativeFaces[indexInBaseMesh];
570 simplifiedMesh->mLod = path + 1;
571 simplifiedMesh->mBaseTriangularMesh =
this;
573 if ( simplifiedMesh->
triangles().count() < minimumTrianglesCount )
576 indexes = returnIndexes;
580 return simplifiedMeshes;
586 if ( changes.mRemovedTriangleIndexes.isEmpty() && !changes.mNativeFaceIndexesToRemove.isEmpty() )
588 for (
int nf = 0; nf < changes.mNativeFaceIndexesToRemove.count(); ++nf )
590 int nativeIndex = changes.mNativeFaceIndexesToRemove.at( nf );
591 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( nf );
592 Q_ASSERT( !nativeFace.isEmpty() );
594 QgsRectangle nativeFaceExtent( mTriangularMesh.vertex( nativeFace.at( 0 ) ), mTriangularMesh.vertex( nativeFace.at( 0 ) ) );
595 for (
int i = 1; i < nativeFace.count(); ++i )
597 const QgsMeshVertex &triangularVertex = mTriangularMesh.vertex( nativeFace.at( i ) );
598 nativeFaceExtent.
include( triangularVertex );
603 for (
int i = 0; i < concernedTriangle.count(); ++i )
605 int triangleIndex = concernedTriangle.at( i );
606 if ( mTrianglesToNativeFaces.at( triangleIndex ) == nativeIndex )
607 changes.mRemovedTriangleIndexes.append( triangleIndex );
612 if ( changes.mOldZValue.isEmpty() && !changes.mNewZValue.isEmpty() )
614 changes.mOldZValue.reserve( changes.mNewZValue.count() );
615 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
616 changes.mOldZValue.append( mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
619 if ( changes.mTriangleIndexesGeometryChanged.isEmpty() && !changes.mNativeFaceIndexesGeometryChanged.isEmpty() )
621 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
623 const QgsMeshFace &nativeFace = changes.mNativeFacesGeometryChanged.at( i );
624 if ( nativeFace.count() < 2 )
626 QgsRectangle bbox( mTriangularMesh.vertices.at( nativeFace.at( 0 ) ), mTriangularMesh.vertices.at( nativeFace.at( 1 ) ) );
628 for (
int i = 2; i < nativeFace.count(); ++i )
629 bbox.
include( mTriangularMesh.vertices.at( nativeFace.at( i ) ) );
633 while ( pos < triangleIndexes.count() )
636 changes.mNativeFaceIndexesGeometryChanged.at( i ) )
637 triangleIndexes.removeAt( pos );
641 changes.mTriangleIndexesGeometryChanged.append( triangleIndexes );
646 for (
const QgsMeshVertex &vertex : std::as_const( changes.mAddedVertices ) )
650 if ( !changes.mNativeFacesToAdd.isEmpty() )
652 changes.mTrianglesAddedStartIndex = mTriangularMesh.faceCount();
653 int firstNewNativeFacesIndex = mNativeMeshFaceCentroids.count();
654 for (
int i = 0; i < changes.mNativeFacesToAdd.count(); ++i )
656 const QgsMeshFace &nativeFace = changes.mNativeFacesToAdd.at( i );
657 triangulate( nativeFace, firstNewNativeFacesIndex + i );
658 mNativeMeshFaceCentroids.append( calculateCentroid( nativeFace ) );
661 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.faceCount(); ++i )
662 mSpatialFaceIndex.addFace( i, mTriangularMesh );
666 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
668 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
669 mTrianglesToNativeFaces[triangleIndex] = -1;
670 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
671 mTriangularMesh.faces[triangleIndex] =
QgsMeshFace();
674 for (
int i = 0; i < changes.mNativeFaceIndexesToRemove.count(); ++i )
675 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] =
QgsMeshVertex();
678 for (
int i = 0; i < changes.mVerticesIndexesToRemove.count(); ++i )
679 mTriangularMesh.vertices[changes.mVerticesIndexesToRemove.at( i )] =
QgsMeshVertex();
681 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
682 mIsExtentValid =
false;
685 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
687 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
688 mTriangularMesh.vertices[vertexIndex].setZ( changes.mNewZValue.at( i ) );
692 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
693 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
696 for (
int i = 0; i < changes.mNewXYValue.count(); ++i )
698 const QgsPointXY &nativeCoordinates = changes.mNewXYValue.at( i );
700 nativeCoordinates.
y(),
701 mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
707 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
708 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
711 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
712 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
718 if ( !changes.mNativeFacesToAdd.isEmpty() )
720 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.faceCount(); ++i )
721 mSpatialFaceIndex.removeFace( i, mTriangularMesh );
723 int initialNativeFacesCount = mNativeMeshFaceCentroids.count() - changes.mNativeFacesToAdd.count();
725 mTriangularMesh.faces.resize( changes.mTrianglesAddedStartIndex );
726 mTrianglesToNativeFaces.resize( changes.mTrianglesAddedStartIndex );
727 mNativeMeshFaceCentroids.resize( initialNativeFacesCount );
730 int initialVerticesCount = mTriangularMesh.vertices.count() - changes.mAddedVertices.count();
731 mTriangularMesh.vertices.resize( initialVerticesCount );
733 if ( !changes.mAddedVertices.isEmpty() )
734 mIsExtentValid =
false;
737 for (
const int i : std::as_const( changes.mVerticesIndexesToRemove ) )
740 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
741 mIsExtentValid =
false;
744 QVector<QgsMeshFace> restoredTriangles;
745 QVector<int> restoredTriangularToNative;
746 for (
int i = 0; i < changes.mNativeFacesToRemove.count(); ++i )
748 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( i );
749 triangulateFaces( nativeFace,
750 changes.mNativeFaceIndexesToRemove.at( i ),
752 restoredTriangularToNative,
754 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = calculateCentroid( nativeFace );
756 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
758 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
759 mTriangularMesh.faces[triangleIndex] = restoredTriangles.at( i );
760 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
761 mTrianglesToNativeFaces[triangleIndex] = restoredTriangularToNative.at( i );
765 for (
int i = 0; i < changes.mOldZValue.count(); ++i )
767 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
768 mTriangularMesh.vertices[vertexIndex].setZ( changes.mOldZValue.at( i ) );
772 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
773 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
776 for (
int i = 0; i < changes.mOldXYValue.count(); ++i )
778 const QgsPointXY &nativeCoordinates = changes.mOldXYValue.at( i );
780 nativeCoordinates.
y(),
781 mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
787 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
788 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
791 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
792 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
800 mNativeFacesToAdd = topologicalChanges.
addedFaces();
801 mNativeFacesToRemove = topologicalChanges.
removedFaces();
809 mNativeFacesGeometryChanged.resize( mNativeFaceIndexesGeometryChanged.count() );
810 for (
int i = 0; i < mNativeFaceIndexesGeometryChanged.count(); ++i )
811 mNativeFacesGeometryChanged[i] = nativeMesh.
face( mNativeFaceIndexesGeometryChanged.at( i ) );
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).
QgsVertexIterator vertices() const
Returns a read-only, Java-style iterator for traversal of vertices of all the geometry,...
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
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.
A spatial index for QgsMeshFace or QgsMeshEdge objects.
static bool isInTriangleFace(const QgsPointXY point, const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Tests if point p is on the face defined with vertices.
static QgsGeometry toGeometry(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry.
static void setCounterClockwise(QgsMeshFace &triangle, const QgsMeshVertex &v0, const QgsMeshVertex &v1, const QgsMeshVertex &v2)
Checks if the triangle is counter clockwise, if not sets it counter clockwise.
static QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
static QSet< int > nativeFacesFromTriangles(const QList< int > &triangleIndexes, const QVector< int > &trianglesToNativeFaces)
Returns unique native faces indexes from list of triangle indexes.
Point geometry type, with support for z-dimension and m-values.
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.
Contains topological differences between two states of a topological mesh, only accessible from the Q...
QVector< QgsMeshFace > removedFaces() const
Returns the faces that are removed with this changes.
QVector< QgsMeshVertex > addedVertices() const
Returns the added vertices with this changes.
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.
Makes changes to a triangular mesh and keeps track of these changes.
Changes()=default
Default constructor, no changes.
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.
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