20#include "meshoptimizer.h"
32using namespace Qt::StringLiterals;
34static void triangulateFaces(
const QgsMeshFace &face,
int nativeIndex, QVector<QgsMeshFace> &destinationFaces, QVector<int> &triangularToNative,
const QgsMesh &verticesMeshSource )
36 int vertexCount = face.size();
37 if ( vertexCount < 3 )
40 while ( vertexCount > 3 )
43 const QgsMeshFace ear = { face[vertexCount - 2], face[vertexCount - 1], face[0] };
44 if ( !( std::isnan( verticesMeshSource.
vertex( ear[0] ).
x() ) || std::isnan( verticesMeshSource.
vertex( ear[1] ).
x() ) || std::isnan( verticesMeshSource.
vertex( ear[2] ).
x() ) ) )
46 destinationFaces.push_back( ear );
47 triangularToNative.push_back( nativeIndex );
52 const QgsMeshFace triangle = { face[1], face[2], face[0] };
53 if ( !( std::isnan( verticesMeshSource.
vertex( triangle[0] ).
x() ) || std::isnan( verticesMeshSource.
vertex( triangle[1] ).
x() ) || std::isnan( verticesMeshSource.
vertex( triangle[2] ).
x() ) ) )
55 destinationFaces.push_back( triangle );
56 triangularToNative.push_back( nativeIndex );
60void QgsTriangularMesh::triangulate(
const QgsMeshFace &face,
int nativeIndex )
62 triangulateFaces( face, nativeIndex, mTriangularMesh.faces, mTrianglesToNativeFaces, mTriangularMesh );
69 if ( mCoordinateTransform.isValid() )
73 transformedVertex.
transform( mCoordinateTransform, direction );
75 catch ( QgsCsException &cse )
83 return transformedVertex;
93 return mAverageTriangleSize;
101 Q_ASSERT( nativeMesh );
103 bool needUpdateVerticesCoordinates = mTriangularMesh.vertices.size() != nativeMesh->
vertices.size() ||
104 ( ( mCoordinateTransform.isValid() || transform.
isValid() ) &&
105 ( mCoordinateTransform.sourceCrs() != transform.
sourceCrs() ||
106 mCoordinateTransform.destinationCrs() != transform.
destinationCrs() ||
109 bool needUpdateFrame = mTriangularMesh.vertices.size() != nativeMesh->
vertices.size()
110 || mNativeMeshFaceCentroids.size() != nativeMesh->
faces.size()
111 || mTriangularMesh.faces.size() < nativeMesh->
faces.size()
112 || mTriangularMesh.edges.size() != nativeMesh->
edges.size();
116 if ( !needUpdateVerticesCoordinates && !needUpdateFrame )
120 mTriangularMesh.vertices.clear();
121 if ( needUpdateFrame )
123 mTriangularMesh.faces.clear();
124 mTriangularMesh.edges.clear();
125 mEdgesToNativeEdges.clear();
126 mTrianglesToNativeFaces.clear();
130 mCoordinateTransform = transform;
131 mTriangularMesh.vertices.resize( nativeMesh->
vertices.size() );
133 for (
int i = 0; i < nativeMesh->
vertices.size(); ++i )
136 mExtent.include( mTriangularMesh.vertices.at( i ) );
139 if ( needUpdateFrame )
142 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
145 triangulate( face, i );
150 mNativeMeshFaceCentroids.resize( nativeMesh->
faces.size() );
151 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
154 mNativeMeshFaceCentroids[i] = calculateCentroid( face );
160 if ( needUpdateFrame )
168 if ( needUpdateFrame )
170 const QVector<QgsMeshEdge>
edges = nativeMesh->
edges;
171 for (
int nativeIndex = 0; nativeIndex <
edges.size(); ++nativeIndex )
174 if ( !( std::isnan( mTriangularMesh.vertex( edge.first ).x() ) || std::isnan( mTriangularMesh.vertex( edge.second ).x() ) ) )
176 mTriangularMesh.edges.push_back( edge );
177 mEdgesToNativeEdges.push_back( nativeIndex );
183 mNativeMeshEdgeCentroids.resize( nativeMesh->
edgeCount() );
184 for (
int i = 0; i < nativeMesh->
edgeCount(); ++i )
189 mNativeMeshEdgeCentroids[i] =
QgsMeshVertex( ( a.
x() + b.
x() ) / 2.0, ( a.
y() + b.
y() ) / 2.0, ( a.
z() + b.
z() ) / 2.0 );
200 return update( nativeMesh, mCoordinateTransform );
203void QgsTriangularMesh::finalizeTriangles()
205 mAverageTriangleSize = 0;
206 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
214 QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( v0, v1, v2 );
216 mAverageTriangleSize += std::fmax( bbox.
width(), bbox.
height() );
220 mAverageTriangleSize /= mTriangularMesh.faceCount();
236 if ( !mCoordinateTransform.isShortCircuited() )
258 if ( !mIsExtentValid )
261 for (
int i = 0; i < mTriangularMesh.vertices.size(); ++i )
262 if ( !mTriangularMesh.vertices.at( i ).isEmpty() )
263 mExtent.include( mTriangularMesh.vertices.at( i ) );
265 mIsExtentValid =
true;
280 return mTriangularMesh.vertexCount() != 0;
282 return mTriangularMesh.edgeCount() != 0;
284 return mTriangularMesh.faceCount() != 0;
290void QgsTriangularMesh::addVertex(
const QgsMeshVertex &vertex )
293 mTriangularMesh.
vertices.append( vertexInTriangularCoordinates );
294 if ( !vertexInTriangularCoordinates.
isEmpty() )
295 mExtent.
include( vertexInTriangularCoordinates );
300 return mTriangularMesh.vertices;
305 return mTriangularMesh.faces;
310 return mTriangularMesh.edges;
320 return mNativeMeshFaceCentroids;
325 return mNativeMeshEdgeCentroids;
330 return mTrianglesToNativeFaces;
335 return mEdgesToNativeEdges;
341 if ( mCoordinateTransform.isValid() )
345 mapPoint = mCoordinateTransform.transform( point );
362 const QList<int> faceIndexes = mSpatialFaceIndex.intersects(
QgsRectangle( point, point ) );
363 for (
const int faceIndex : faceIndexes )
365 const QgsMeshFace &face = mTriangularMesh.faces.at( faceIndex );
376 if ( triangleIndex == -1 )
379 if ( triangleIndex < mTrianglesToNativeFaces.count() )
380 return mTrianglesToNativeFaces.at( triangleIndex );
388 return concernedFaceIndex.values();
393 const QList<int> faceIndexes = mSpatialFaceIndex.intersects(
QgsRectangle( point, point ) );
395 for (
const int faceIndex : faceIndexes )
397 const QgsMeshFace &face = mTriangularMesh.faces.at( faceIndex );
406 return mSpatialFaceIndex.intersects( rectangle );
411 return mSpatialEdgeIndex.intersects( rectangle );
416 QVector<QVector3D> normals(
vertices().count(), QVector3D( 0, 0, 0 ) );
420 if ( face.isEmpty() )
423 for (
int i = 0; i < 3; i++ )
425 int index1( face.at( i ) );
426 int index2( face.at( ( i + 1 ) % 3 ) );
427 int index3( face.at( ( i + 2 ) % 3 ) );
433 QVector3D v1(
float( otherVert1.
x() - vert.
x() ),
float( otherVert1.
y() - vert.
y() ), vertScale *
float( otherVert1.
z() - vert.
z() ) );
434 QVector3D v2(
float( otherVert2.
x() - vert.
x() ),
float( otherVert2.
y() - vert.
y() ), vertScale *
float( otherVert2.
z() - vert.
z() ) );
436 normals[index1] += QVector3D::crossProduct( v1, v2 );
444 QVector<QgsTriangularMesh *> simplifiedMeshes;
446 if ( mTriangularMesh.edgeCount() != 0 )
447 return simplifiedMeshes;
449 if ( !( reductionFactor > 1 ) )
450 return simplifiedMeshes;
452 size_t verticesCount = size_t( mTriangularMesh.vertices.count() );
454 unsigned int baseIndexCount = mTriangularMesh.faceCount() * 3;
456 QVector<unsigned int> indexes( mTriangularMesh.faces.count() * 3 );
457 for (
int i = 0; i < mTriangularMesh.faceCount(); ++i )
460 for (
int j = 0; j < 3; ++j )
461 indexes[i * 3 + j] = f.at( j );
464 QVector<float>
vertices( mTriangularMesh.vertices.count() * 3 );
465 for (
int i = 0; i < mTriangularMesh.vertices.count(); ++i )
477 size_t maxNumberOfIndexes = baseIndexCount / pow( reductionFactor, path + 1 );
479 if ( indexes.size() <=
int( maxNumberOfIndexes ) )
481 delete simplifiedMesh;
485 QVector<unsigned int> returnIndexes( indexes.size() );
487 size_t size = meshopt_simplifySloppy(
488 returnIndexes.data(),
495#
if MESHOPTIMIZER_VERSION > 150
503 returnIndexes.resize( size );
505 if ( size == 0 ||
int( size ) >= indexes.size() )
507 QgsDebugError( u
"Mesh simplification failed after %1 path"_s.arg( path + 1 ) );
508 delete simplifiedMesh;
513 newMesh.
vertices = mTriangularMesh.vertices;
515 newMesh.
faces.resize( returnIndexes.size() / 3 );
516 for (
int i = 0; i < newMesh.
faces.size(); ++i )
519 for (
size_t j = 0; j < 3; ++j )
520 f[j] = returnIndexes.at( i * 3 + j );
521 newMesh.
faces[i] = f;
524 simplifiedMesh->mTriangularMesh = newMesh;
525 simplifiedMesh->mSpatialFaceIndex =
QgsMeshSpatialIndex( simplifiedMesh->mTriangularMesh );
526 simplifiedMesh->finalizeTriangles();
527 simplifiedMeshes.push_back( simplifiedMesh );
531 simplifiedMesh->mTrianglesToNativeFaces = QVector<int>( simplifiedMesh->
triangles().count(), 0 );
532 for (
int i = 0; i < simplifiedMesh->mTrianglesToNativeFaces.count(); ++i )
537 for (
size_t j = 0; j < 3; ++j )
539 x += mTriangularMesh.vertex( triangle[j] ).x();
540 y += mTriangularMesh.vertex( triangle[j] ).y();
547 if ( indexInBaseMesh == -1 )
552 while ( indexInBaseMesh == -1 && j < 3 )
556 if ( indexInBaseMesh > -1 && indexInBaseMesh < mTrianglesToNativeFaces.count() )
557 simplifiedMesh->mTrianglesToNativeFaces[i] = mTrianglesToNativeFaces[indexInBaseMesh];
560 simplifiedMesh->mLod = path + 1;
561 simplifiedMesh->mBaseTriangularMesh =
this;
563 if ( simplifiedMesh->
triangles().count() < minimumTrianglesCount )
566 indexes = returnIndexes;
570 return simplifiedMeshes;
576 if ( changes.mRemovedTriangleIndexes.isEmpty() && !changes.mNativeFaceIndexesToRemove.isEmpty() )
578 for (
int nf = 0; nf < changes.mNativeFaceIndexesToRemove.count(); ++nf )
580 int nativeIndex = changes.mNativeFaceIndexesToRemove.at( nf );
581 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( nf );
582 Q_ASSERT( !nativeFace.isEmpty() );
584 QgsRectangle nativeFaceExtent( mTriangularMesh.vertex( nativeFace.at( 0 ) ), mTriangularMesh.vertex( nativeFace.at( 0 ) ) );
585 for (
int i = 1; i < nativeFace.count(); ++i )
587 const QgsMeshVertex &triangularVertex = mTriangularMesh.vertex( nativeFace.at( i ) );
588 nativeFaceExtent.
include( triangularVertex );
593 for (
int i = 0; i < concernedTriangle.count(); ++i )
595 int triangleIndex = concernedTriangle.at( i );
596 if ( mTrianglesToNativeFaces.at( triangleIndex ) == nativeIndex )
597 changes.mRemovedTriangleIndexes.append( triangleIndex );
602 if ( changes.mOldZValue.isEmpty() && !changes.mNewZValue.isEmpty() )
604 changes.mOldZValue.reserve( changes.mNewZValue.count() );
605 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
606 changes.mOldZValue.append( mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
609 if ( changes.mTriangleIndexesGeometryChanged.isEmpty() && !changes.mNativeFaceIndexesGeometryChanged.isEmpty() )
611 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
613 const QgsMeshFace &nativeFace = changes.mNativeFacesGeometryChanged.at( i );
614 if ( nativeFace.count() < 2 )
616 QgsRectangle bbox( mTriangularMesh.vertices.at( nativeFace.at( 0 ) ), mTriangularMesh.vertices.at( nativeFace.at( 1 ) ) );
618 for (
int i = 2; i < nativeFace.count(); ++i )
619 bbox.
include( mTriangularMesh.vertices.at( nativeFace.at( i ) ) );
623 while ( pos < triangleIndexes.count() )
625 if (
trianglesToNativeFaces().at( triangleIndexes.at( pos ) ) != changes.mNativeFaceIndexesGeometryChanged.at( i ) )
626 triangleIndexes.removeAt( pos );
630 changes.mTriangleIndexesGeometryChanged.append( triangleIndexes );
635 for (
const QgsMeshVertex &vertex : std::as_const( changes.mAddedVertices ) )
639 if ( !changes.mNativeFacesToAdd.isEmpty() )
641 changes.mTrianglesAddedStartIndex = mTriangularMesh.faceCount();
642 int firstNewNativeFacesIndex = mNativeMeshFaceCentroids.count();
643 for (
int i = 0; i < changes.mNativeFacesToAdd.count(); ++i )
645 const QgsMeshFace &nativeFace = changes.mNativeFacesToAdd.at( i );
646 triangulate( nativeFace, firstNewNativeFacesIndex + i );
647 mNativeMeshFaceCentroids.append( calculateCentroid( nativeFace ) );
650 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.faceCount(); ++i )
651 mSpatialFaceIndex.addFace( i, mTriangularMesh );
655 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
657 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
658 mTrianglesToNativeFaces[triangleIndex] = -1;
659 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
660 mTriangularMesh.faces[triangleIndex] =
QgsMeshFace();
663 for (
int i = 0; i < changes.mNativeFaceIndexesToRemove.count(); ++i )
664 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] =
QgsMeshVertex();
667 for (
int i = 0; i < changes.mVerticesIndexesToRemove.count(); ++i )
668 mTriangularMesh.vertices[changes.mVerticesIndexesToRemove.at( i )] =
QgsMeshVertex();
670 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
671 mIsExtentValid =
false;
674 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
676 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
677 mTriangularMesh.vertices[vertexIndex].setZ( changes.mNewZValue.at( i ) );
681 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
682 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
685 for (
int i = 0; i < changes.mNewXYValue.count(); ++i )
687 const QgsPointXY &nativeCoordinates = changes.mNewXYValue.at( i );
688 const QgsMeshVertex nativeVertex( nativeCoordinates.
x(), nativeCoordinates.
y(), mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
694 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
695 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
698 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
699 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
705 if ( !changes.mNativeFacesToAdd.isEmpty() )
707 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.faceCount(); ++i )
708 mSpatialFaceIndex.removeFace( i, mTriangularMesh );
710 int initialNativeFacesCount = mNativeMeshFaceCentroids.count() - changes.mNativeFacesToAdd.count();
712 mTriangularMesh.faces.resize( changes.mTrianglesAddedStartIndex );
713 mTrianglesToNativeFaces.resize( changes.mTrianglesAddedStartIndex );
714 mNativeMeshFaceCentroids.resize( initialNativeFacesCount );
717 int initialVerticesCount = mTriangularMesh.vertices.count() - changes.mAddedVertices.count();
718 mTriangularMesh.vertices.resize( initialVerticesCount );
720 if ( !changes.mAddedVertices.isEmpty() )
721 mIsExtentValid =
false;
724 for (
const int i : std::as_const( changes.mVerticesIndexesToRemove ) )
727 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
728 mIsExtentValid =
false;
731 QVector<QgsMeshFace> restoredTriangles;
732 QVector<int> restoredTriangularToNative;
733 for (
int i = 0; i < changes.mNativeFacesToRemove.count(); ++i )
735 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( i );
736 triangulateFaces( nativeFace, changes.mNativeFaceIndexesToRemove.at( i ), restoredTriangles, restoredTriangularToNative, mTriangularMesh );
737 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = calculateCentroid( nativeFace );
739 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
741 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
742 mTriangularMesh.faces[triangleIndex] = restoredTriangles.at( i );
743 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
744 mTrianglesToNativeFaces[triangleIndex] = restoredTriangularToNative.at( i );
748 for (
int i = 0; i < changes.mOldZValue.count(); ++i )
750 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
751 mTriangularMesh.vertices[vertexIndex].setZ( changes.mOldZValue.at( i ) );
755 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
756 mSpatialFaceIndex.removeFace( triangleIndex, mTriangularMesh );
759 for (
int i = 0; i < changes.mOldXYValue.count(); ++i )
761 const QgsPointXY &nativeCoordinates = changes.mOldXYValue.at( i );
762 const QgsMeshVertex nativeVertex( nativeCoordinates.
x(), nativeCoordinates.
y(), mTriangularMesh.vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
768 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
769 mSpatialFaceIndex.addFace( triangleIndex, mTriangularMesh );
772 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
773 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
780 mNativeFacesToAdd = topologicalChanges.
addedFaces();
781 mNativeFacesToRemove = topologicalChanges.
removedFaces();
789 mNativeFacesGeometryChanged.resize( mNativeFaceIndexesGeometryChanged.count() );
790 for (
int i = 0; i < mNativeFaceIndexesGeometryChanged.count(); ++i )
791 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