20#include "meshoptimizer.h"
31static void triangulateFaces(
const QgsMeshFace &face,
33 QVector<QgsMeshFace> &destinationFaces,
34 QVector<int> &triangularToNative,
35 const QgsMesh &verticesMeshSource )
37 int vertexCount = face.size();
38 if ( vertexCount < 3 )
41 while ( vertexCount > 3 )
44 const QgsMeshFace ear = { face[vertexCount - 2], face[vertexCount - 1], face[0] };
45 if ( !( std::isnan( verticesMeshSource.
vertex( ear[0] ).
x() ) ||
46 std::isnan( verticesMeshSource.
vertex( ear[1] ).
x() ) ||
47 std::isnan( verticesMeshSource.
vertex( ear[2] ).
x() ) ) )
49 destinationFaces.push_back( ear );
50 triangularToNative.push_back( nativeIndex );
55 const QgsMeshFace triangle = { face[1], face[2], face[0] };
56 if ( !( std::isnan( verticesMeshSource.
vertex( triangle[0] ).
x() ) ||
57 std::isnan( verticesMeshSource.
vertex( triangle[1] ).
x() ) ||
58 std::isnan( verticesMeshSource.
vertex( triangle[2] ).
x() ) ) )
60 destinationFaces.push_back( triangle );
61 triangularToNative.push_back( nativeIndex );
65void QgsTriangularMesh::triangulate(
const QgsMeshFace &face,
int nativeIndex )
67 triangulateFaces( face, nativeIndex, mTriangularMesh.faces, mTrianglesToNativeFaces, mTriangularMesh );
74 if ( mCoordinateTransform.isValid() )
78 transformedVertex.
transform( mCoordinateTransform, direction );
80 catch ( QgsCsException &cse )
88 return transformedVertex;
98 return mAverageTriangleSize;
106 Q_ASSERT( nativeMesh );
108 bool needUpdateVerticesCoordinates = mTriangularMesh.vertices.size() != nativeMesh->
vertices.size() ||
109 ( ( mCoordinateTransform.isValid() || transform.
isValid() ) &&
110 ( mCoordinateTransform.sourceCrs() != transform.
sourceCrs() ||
111 mCoordinateTransform.destinationCrs() != transform.
destinationCrs() ||
114 bool needUpdateFrame = mTriangularMesh.vertices.size() != nativeMesh->
vertices.size() ||
115 mNativeMeshFaceCentroids.size() != nativeMesh->
faces.size() ||
116 mTriangularMesh.faces.size() < nativeMesh->
faces.size() ||
117 mTriangularMesh.edges.size() != nativeMesh->
edges.size();
121 if ( ! needUpdateVerticesCoordinates && !needUpdateFrame )
125 mTriangularMesh.vertices.clear();
126 if ( needUpdateFrame )
128 mTriangularMesh.faces.clear();
129 mTriangularMesh.edges.clear();
130 mEdgesToNativeEdges.clear();
131 mTrianglesToNativeFaces.clear();
135 mCoordinateTransform = transform;
136 mTriangularMesh.vertices.resize( nativeMesh->
vertices.size() );
138 for (
int i = 0; i < nativeMesh->
vertices.size(); ++i )
141 mExtent.include( mTriangularMesh.vertices.at( i ) );
144 if ( needUpdateFrame )
147 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
150 triangulate( face, i );
155 mNativeMeshFaceCentroids.resize( nativeMesh->
faces.size() );
156 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
159 mNativeMeshFaceCentroids[i] = calculateCentroid( face );
165 if ( needUpdateFrame )
173 if ( needUpdateFrame )
175 const QVector<QgsMeshEdge>
edges = nativeMesh->
edges;
176 for (
int nativeIndex = 0; nativeIndex <
edges.size(); ++nativeIndex )
179 if ( !( std::isnan( mTriangularMesh.vertex( edge.first ).x() ) ||
180 std::isnan( mTriangularMesh.vertex( edge.second ).x() ) ) )
182 mTriangularMesh.edges.push_back( edge );
183 mEdgesToNativeEdges.push_back( nativeIndex );
189 mNativeMeshEdgeCentroids.resize( nativeMesh->
edgeCount() );
190 for (
int i = 0; i < nativeMesh->
edgeCount(); ++i )
195 mNativeMeshEdgeCentroids[i] =
QgsMeshVertex( ( a.
x() + b.
x() ) / 2.0, ( a.
y() + b.
y() ) / 2.0, ( a.
z() + b.
z() ) / 2.0 );
206 return update( nativeMesh, mCoordinateTransform );
209void QgsTriangularMesh::finalizeTriangles()
211 mAverageTriangleSize = 0;
212 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
220 QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( v0, v1, v2 );
222 mAverageTriangleSize += std::fmax( bbox.
width(), bbox.
height() );
226 mAverageTriangleSize /= mTriangularMesh.faceCount();
242 if ( !mCoordinateTransform.isShortCircuited() )
264 if ( !mIsExtentValid )
267 for (
int i = 0; i < mTriangularMesh.vertices.size(); ++i )
268 if ( !mTriangularMesh.vertices.at( i ).isEmpty() )
269 mExtent.include( mTriangularMesh.vertices.at( i ) );
271 mIsExtentValid =
true;
286 return mTriangularMesh.vertexCount() != 0;
288 return mTriangularMesh.edgeCount() != 0;
290 return mTriangularMesh.faceCount() != 0;
296void QgsTriangularMesh::addVertex(
const QgsMeshVertex &vertex )
299 mTriangularMesh.
vertices.append( vertexInTriangularCoordinates );
300 if ( !vertexInTriangularCoordinates.
isEmpty() )
301 mExtent.
include( vertexInTriangularCoordinates );
306 return mTriangularMesh.vertices;
311 return mTriangularMesh.faces;
316 return mTriangularMesh.edges;
326 return mNativeMeshFaceCentroids;
331 return mNativeMeshEdgeCentroids;
336 return mTrianglesToNativeFaces;
341 return mEdgesToNativeEdges;
347 if ( mCoordinateTransform.isValid() )
351 mapPoint = mCoordinateTransform.transform( point );
368 const QList<int> faceIndexes = mSpatialFaceIndex.intersects(
QgsRectangle( point, point ) );
369 for (
const int faceIndex : faceIndexes )
371 const QgsMeshFace &face = mTriangularMesh.faces.at( faceIndex );
382 if ( triangleIndex == -1 )
385 if ( triangleIndex < mTrianglesToNativeFaces.count() )
386 return mTrianglesToNativeFaces.at( triangleIndex );
396 return concernedFaceIndex.values();
401 const QList<int> faceIndexes = mSpatialFaceIndex.intersects(
QgsRectangle( point, point ) );
403 for (
const int faceIndex : faceIndexes )
405 const QgsMeshFace &face = mTriangularMesh.faces.at( faceIndex );
414 return mSpatialFaceIndex.intersects( rectangle );
419 return mSpatialEdgeIndex.intersects( rectangle );
424 QVector<QVector3D> normals(
vertices().count(), QVector3D( 0, 0, 0 ) );
428 if ( face.isEmpty() )
431 for (
int i = 0; i < 3; i++ )
433 int index1( face.at( i ) );
434 int index2( face.at( ( i + 1 ) % 3 ) );
435 int index3( face.at( ( i + 2 ) % 3 ) );
441 QVector3D v1(
float( otherVert1.
x() - vert.
x() ),
float( otherVert1.
y() - vert.
y() ), vertScale *
float( otherVert1.
z() - vert.
z() ) );
442 QVector3D v2(
float( otherVert2.
x() - vert.
x() ),
float( otherVert2.
y() - vert.
y() ), vertScale *
float( otherVert2.
z() - vert.
z() ) );
444 normals[index1] += QVector3D::crossProduct( v1, v2 );
452 QVector<QgsTriangularMesh *> simplifiedMeshes;
454 if ( mTriangularMesh.edgeCount() != 0 )
455 return simplifiedMeshes;
457 if ( !( reductionFactor > 1 ) )
458 return simplifiedMeshes;
460 size_t verticesCount = size_t( mTriangularMesh.vertices.count() );
462 unsigned int baseIndexCount = mTriangularMesh.faceCount() * 3;
464 QVector<unsigned int> indexes( mTriangularMesh.faces.count() * 3 );
465 for (
int i = 0; i < mTriangularMesh.faceCount(); ++i )
468 for (
int j = 0; j < 3; ++j )
469 indexes[i * 3 + j] = f.at( j );
472 QVector<float>
vertices( mTriangularMesh.vertices.count() * 3 );
473 for (
int i = 0; i < mTriangularMesh.vertices.count(); ++i )
485 size_t maxNumberOfIndexes = baseIndexCount / pow( reductionFactor, path + 1 );
487 if ( indexes.size() <=
int( maxNumberOfIndexes ) )
489 delete simplifiedMesh;
493 QVector<unsigned int> returnIndexes( indexes.size() );
495 size_t size = meshopt_simplifySloppy(
496 returnIndexes.data(),
503#
if MESHOPTIMIZER_VERSION > 150
510 returnIndexes.resize( size );
512 if ( size == 0 ||
int( size ) >= indexes.size() )
514 QgsDebugError( QStringLiteral(
"Mesh simplification failed after %1 path" ).arg( path + 1 ) );
515 delete simplifiedMesh;
520 newMesh.
vertices = mTriangularMesh.vertices;
522 newMesh.
faces.resize( returnIndexes.size() / 3 );
523 for (
int i = 0; i < newMesh.
faces.size(); ++i )
526 for (
size_t j = 0; j < 3 ; ++j )
527 f[j] = returnIndexes.at( i * 3 + j ) ;
528 newMesh.
faces[i ] = f;
531 simplifiedMesh->mTriangularMesh = newMesh;
532 simplifiedMesh->mSpatialFaceIndex =
QgsMeshSpatialIndex( simplifiedMesh->mTriangularMesh );
533 simplifiedMesh->finalizeTriangles();
534 simplifiedMeshes.push_back( simplifiedMesh );
538 simplifiedMesh->mTrianglesToNativeFaces = QVector<int>( simplifiedMesh->
triangles().count(), 0 );
539 for (
int i = 0; i < simplifiedMesh->mTrianglesToNativeFaces.count(); ++i )
544 for (
size_t j = 0; j < 3 ; ++j )
546 x += mTriangularMesh.vertex( triangle[j] ).x();
547 y += mTriangularMesh.vertex( triangle[j] ).y();
554 if ( indexInBaseMesh == -1 )
559 while ( indexInBaseMesh == -1 && j < 3 )
563 if ( indexInBaseMesh > -1 && indexInBaseMesh < mTrianglesToNativeFaces.count() )
564 simplifiedMesh->mTrianglesToNativeFaces[i] = mTrianglesToNativeFaces[indexInBaseMesh];
567 simplifiedMesh->mLod = path + 1;
568 simplifiedMesh->mBaseTriangularMesh =
this;
570 if ( simplifiedMesh->
triangles().count() < minimumTrianglesCount )
573 indexes = returnIndexes;
577 return simplifiedMeshes;
583 if ( changes.mRemovedTriangleIndexes.isEmpty() && !changes.mNativeFaceIndexesToRemove.isEmpty() )
585 for (
int nf = 0; nf < changes.mNativeFaceIndexesToRemove.count(); ++nf )
587 int nativeIndex = changes.mNativeFaceIndexesToRemove.at( nf );
588 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( nf );
589 Q_ASSERT( !nativeFace.isEmpty() );
591 QgsRectangle nativeFaceExtent( mTriangularMesh.vertex( nativeFace.at( 0 ) ), mTriangularMesh.vertex( nativeFace.at( 0 ) ) );
592 for (
int i = 1; i < nativeFace.count(); ++i )
594 const QgsMeshVertex &triangularVertex = mTriangularMesh.vertex( nativeFace.at( i ) );
595 nativeFaceExtent.
include( triangularVertex );
600 for (
int i = 0; i < concernedTriangle.count(); ++i )
602 int triangleIndex = concernedTriangle.at( i );
603 if ( mTrianglesToNativeFaces.at( triangleIndex ) == nativeIndex )
604 changes.mRemovedTriangleIndexes.append( triangleIndex );
609 if ( changes.mOldZValue.isEmpty() && !changes.mNewZValue.isEmpty() )
611 changes.mOldZValue.reserve( changes.mNewZValue.count() );
612 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
613 changes.mOldZValue.append( mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
616 if ( changes.mTriangleIndexesGeometryChanged.isEmpty() && !changes.mNativeFaceIndexesGeometryChanged.isEmpty() )
618 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
620 const QgsMeshFace &nativeFace = changes.mNativeFacesGeometryChanged.at( i );
621 if ( nativeFace.count() < 2 )
623 QgsRectangle bbox( mTriangularMesh.vertices.at( nativeFace.at( 0 ) ), mTriangularMesh.vertices.at( nativeFace.at( 1 ) ) );
625 for (
int i = 2; i < nativeFace.count(); ++i )
626 bbox.
include( mTriangularMesh.vertices.at( nativeFace.at( i ) ) );
630 while ( pos < triangleIndexes.count() )
633 changes.mNativeFaceIndexesGeometryChanged.at( i ) )
634 triangleIndexes.removeAt( pos );
638 changes.mTriangleIndexesGeometryChanged.append( triangleIndexes );
643 for (
const QgsMeshVertex &vertex : std::as_const( changes.mAddedVertices ) )
647 if ( !changes.mNativeFacesToAdd.isEmpty() )
649 changes.mTrianglesAddedStartIndex = mTriangularMesh.faceCount();
650 int firstNewNativeFacesIndex = mNativeMeshFaceCentroids.count();
651 for (
int i = 0; i < changes.mNativeFacesToAdd.count(); ++i )
653 const QgsMeshFace &nativeFace = changes.mNativeFacesToAdd.at( i );
654 triangulate( nativeFace, firstNewNativeFacesIndex + i );
655 mNativeMeshFaceCentroids.append( calculateCentroid( nativeFace ) );
658 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.faceCount(); ++i )
659 mSpatialFaceIndex.addFace( i, mTriangularMesh );
663 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
665 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
666 mTrianglesToNativeFaces[triangleIndex] = -1;
667 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
668 mTriangularMesh.faces[triangleIndex] =
QgsMeshFace();
671 for (
int i = 0; i < changes.mNativeFaceIndexesToRemove.count(); ++i )
672 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] =
QgsMeshVertex();
675 for (
int i = 0; i < changes.mVerticesIndexesToRemove.count(); ++i )
676 mTriangularMesh.vertices[changes.mVerticesIndexesToRemove.at( i )] =
QgsMeshVertex();
678 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
679 mIsExtentValid =
false;
682 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
684 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
685 mTriangularMesh.vertices[vertexIndex].setZ( changes.mNewZValue.at( i ) );
689 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
690 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
693 for (
int i = 0; i < changes.mNewXYValue.count(); ++i )
695 const QgsPointXY &nativeCoordinates = changes.mNewXYValue.at( i );
697 nativeCoordinates.
y(),
698 mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
704 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
705 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
708 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
709 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
715 if ( !changes.mNativeFacesToAdd.isEmpty() )
717 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.faceCount(); ++i )
718 mSpatialFaceIndex.removeFace( i, mTriangularMesh );
720 int initialNativeFacesCount = mNativeMeshFaceCentroids.count() - changes.mNativeFacesToAdd.count();
722 mTriangularMesh.faces.resize( changes.mTrianglesAddedStartIndex );
723 mTrianglesToNativeFaces.resize( changes.mTrianglesAddedStartIndex );
724 mNativeMeshFaceCentroids.resize( initialNativeFacesCount );
727 int initialVerticesCount = mTriangularMesh.vertices.count() - changes.mAddedVertices.count();
728 mTriangularMesh.vertices.resize( initialVerticesCount );
730 if ( !changes.mAddedVertices.isEmpty() )
731 mIsExtentValid =
false;
734 for (
const int i : std::as_const( changes.mVerticesIndexesToRemove ) )
737 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
738 mIsExtentValid =
false;
741 QVector<QgsMeshFace> restoredTriangles;
742 QVector<int> restoredTriangularToNative;
743 for (
int i = 0; i < changes.mNativeFacesToRemove.count(); ++i )
745 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( i );
746 triangulateFaces( nativeFace,
747 changes.mNativeFaceIndexesToRemove.at( i ),
749 restoredTriangularToNative,
751 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = calculateCentroid( nativeFace );
753 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
755 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
756 mTriangularMesh.faces[triangleIndex] = restoredTriangles.at( i );
757 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
758 mTrianglesToNativeFaces[triangleIndex] = restoredTriangularToNative.at( i );
762 for (
int i = 0; i < changes.mOldZValue.count(); ++i )
764 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
765 mTriangularMesh.vertices[vertexIndex].setZ( changes.mOldZValue.at( i ) );
769 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
770 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
773 for (
int i = 0; i < changes.mOldXYValue.count(); ++i )
775 const QgsPointXY &nativeCoordinates = changes.mOldXYValue.at( i );
777 nativeCoordinates.
y(),
778 mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
784 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
785 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
788 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
789 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
797 mNativeFacesToAdd = topologicalChanges.
addedFaces();
798 mNativeFacesToRemove = topologicalChanges.
removedFaces();
806 mNativeFacesGeometryChanged.resize( mNativeFaceIndexesGeometryChanged.count() );
807 for (
int i = 0; i < mNativeFaceIndexesGeometryChanged.count(); ++i )
808 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