27#include "meshOptimizer/meshoptimizer.h"
29static void triangulateFaces(
const QgsMeshFace &face,
31 QVector<QgsMeshFace> &destinationFaces,
32 QVector<int> &triangularToNative,
33 const QgsMesh &verticesMeshSource )
35 int vertexCount = face.size();
36 if ( vertexCount < 3 )
39 while ( vertexCount > 3 )
42 const QgsMeshFace ear = { face[vertexCount - 2], face[vertexCount - 1], face[0] };
43 if ( !( std::isnan( verticesMeshSource.
vertex( ear[0] ).
x() ) ||
44 std::isnan( verticesMeshSource.
vertex( ear[1] ).
x() ) ||
45 std::isnan( verticesMeshSource.
vertex( ear[2] ).
x() ) ) )
47 destinationFaces.push_back( ear );
48 triangularToNative.push_back( nativeIndex );
53 const QgsMeshFace triangle = { face[1], face[2], face[0] };
54 if ( !( std::isnan( verticesMeshSource.
vertex( triangle[0] ).
x() ) ||
55 std::isnan( verticesMeshSource.
vertex( triangle[1] ).
x() ) ||
56 std::isnan( verticesMeshSource.
vertex( triangle[2] ).
x() ) ) )
58 destinationFaces.push_back( triangle );
59 triangularToNative.push_back( nativeIndex );
63void QgsTriangularMesh::triangulate(
const QgsMeshFace &face,
int nativeIndex )
65 triangulateFaces( face, nativeIndex, mTriangularMesh.
faces, mTrianglesToNativeFaces, mTriangularMesh );
72 if ( mCoordinateTransform.
isValid() )
76 transformedVertex.
transform( mCoordinateTransform, direction );
86 return transformedVertex;
96 return mAverageTriangleSize;
104 Q_ASSERT( nativeMesh );
106 bool needUpdateVerticesCoordinates = mTriangularMesh.
vertices.size() != nativeMesh->
vertices.size() ||
112 bool needUpdateFrame = mTriangularMesh.
vertices.size() != nativeMesh->
vertices.size() ||
113 mNativeMeshFaceCentroids.size() != nativeMesh->
faces.size() ||
114 mTriangularMesh.
faces.size() < nativeMesh->
faces.size() ||
115 mTriangularMesh.
edges.size() != nativeMesh->
edges.size();
119 if ( ! needUpdateVerticesCoordinates && !needUpdateFrame )
124 if ( needUpdateFrame )
126 mTriangularMesh.
faces.clear();
127 mTriangularMesh.
edges.clear();
128 mEdgesToNativeEdges.clear();
129 mTrianglesToNativeFaces.clear();
133 mCoordinateTransform = transform;
136 for (
int i = 0; i < nativeMesh->
vertices.size(); ++i )
142 if ( needUpdateFrame )
145 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
148 triangulate( face, i );
153 mNativeMeshFaceCentroids.resize( nativeMesh->
faces.size() );
154 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
157 mNativeMeshFaceCentroids[i] = calculateCentroid( face );
163 if ( needUpdateFrame )
171 if ( needUpdateFrame )
173 const QVector<QgsMeshEdge>
edges = nativeMesh->
edges;
174 for (
int nativeIndex = 0; nativeIndex <
edges.size(); ++nativeIndex )
177 if ( !( std::isnan( mTriangularMesh.
vertex( edge.first ).
x() ) ||
178 std::isnan( mTriangularMesh.
vertex( edge.second ).
x() ) ) )
180 mTriangularMesh.
edges.push_back( edge );
181 mEdgesToNativeEdges.push_back( nativeIndex );
187 mNativeMeshEdgeCentroids.resize( nativeMesh->
edgeCount() );
188 for (
int i = 0; i < nativeMesh->
edgeCount(); ++i )
193 mNativeMeshEdgeCentroids[i] =
QgsMeshVertex( ( a.
x() + b.
x() ) / 2.0, ( a.
y() + b.
y() ) / 2.0, ( a.
z() + b.
z() ) / 2.0 );
204 return update( nativeMesh, mCoordinateTransform );
207void QgsTriangularMesh::finalizeTriangles()
209 mAverageTriangleSize = 0;
210 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
218 QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( v0, v1, v2 );
220 mAverageTriangleSize += std::fmax( bbox.
width(), bbox.
height() );
224 mAverageTriangleSize /= mTriangularMesh.
faceCount();
262 if ( !mIsExtentValid )
265 for (
int i = 0; i < mTriangularMesh.
vertices.size(); ++i )
266 if ( !mTriangularMesh.
vertices.at( i ).isEmpty() )
269 mIsExtentValid =
true;
294void QgsTriangularMesh::addVertex(
const QgsMeshVertex &vertex )
297 mTriangularMesh.
vertices.append( vertexInTriangularCoordinates );
298 if ( !vertexInTriangularCoordinates.
isEmpty() )
299 mExtent.
include( vertexInTriangularCoordinates );
309 return mTriangularMesh.
faces;
314 return mTriangularMesh.
edges;
324 return mNativeMeshFaceCentroids;
329 return mNativeMeshEdgeCentroids;
334 return mTrianglesToNativeFaces;
339 return mEdgesToNativeEdges;
345 if ( mCoordinateTransform.
isValid() )
349 mapPoint = mCoordinateTransform.
transform( point );
367 for (
const int faceIndex : faceIndexes )
380 if ( triangleIndex == -1 )
383 if ( triangleIndex < mTrianglesToNativeFaces.count() )
384 return mTrianglesToNativeFaces.at( triangleIndex );
394 return concernedFaceIndex.values();
401 for (
const int faceIndex : faceIndexes )
412 return mSpatialFaceIndex.
intersects( rectangle );
417 return mSpatialEdgeIndex.
intersects( rectangle );
422 QVector<QVector3D> normals(
vertices().count(), QVector3D( 0, 0, 0 ) );
426 if ( face.isEmpty() )
429 for (
int i = 0; i < 3; i++ )
431 int index1( face.at( i ) );
432 int index2( face.at( ( i + 1 ) % 3 ) );
433 int index3( face.at( ( i + 2 ) % 3 ) );
439 QVector3D v1(
float( otherVert1.
x() - vert.
x() ),
float( otherVert1.
y() - vert.
y() ), vertScale *
float( otherVert1.
z() - vert.
z() ) );
440 QVector3D v2(
float( otherVert2.
x() - vert.
x() ),
float( otherVert2.
y() - vert.
y() ), vertScale *
float( otherVert2.
z() - vert.
z() ) );
442 normals[index1] += QVector3D::crossProduct( v1, v2 );
450 QVector<QgsTriangularMesh *> simplifiedMeshes;
453 return simplifiedMeshes;
455 if ( !( reductionFactor > 1 ) )
456 return simplifiedMeshes;
458 size_t verticesCount = size_t( mTriangularMesh.
vertices.count() );
460 unsigned int baseIndexCount = mTriangularMesh.
faceCount() * 3;
462 QVector<unsigned int> indexes( mTriangularMesh.
faces.count() * 3 );
463 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
466 for (
int j = 0; j < 3; ++j )
467 indexes[i * 3 + j] = f.at( j );
471 for (
int i = 0; i < mTriangularMesh.
vertices.count(); ++i )
483 size_t maxNumberOfIndexes = baseIndexCount / pow( reductionFactor, path + 1 );
485 if ( indexes.size() <=
int( maxNumberOfIndexes ) )
487 delete simplifiedMesh;
491 QVector<unsigned int> returnIndexes( indexes.size() );
493 size_t size = meshopt_simplifySloppy(
494 returnIndexes.data(),
500 maxNumberOfIndexes );
503 returnIndexes.resize( size );
505 if ( size == 0 ||
int( size ) >= indexes.size() )
507 QgsDebugError( QStringLiteral(
"Mesh simplification failed after %1 path" ).arg( path + 1 ) );
508 delete simplifiedMesh;
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 )
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 )
618 for (
int i = 2; i < nativeFace.count(); ++i )
623 while ( pos < triangleIndexes.count() )
626 changes.mNativeFaceIndexesGeometryChanged.at( i ) )
627 triangleIndexes.removeAt( pos );
631 changes.mTriangleIndexesGeometryChanged.append( triangleIndexes );
636 for (
const QgsMeshVertex &vertex : std::as_const( changes.mAddedVertices ) )
640 if ( !changes.mNativeFacesToAdd.isEmpty() )
642 changes.mTrianglesAddedStartIndex = mTriangularMesh.
faceCount();
643 int firstNewNativeFacesIndex = mNativeMeshFaceCentroids.count();
644 for (
int i = 0; i < changes.mNativeFacesToAdd.count(); ++i )
646 const QgsMeshFace &nativeFace = changes.mNativeFacesToAdd.at( i );
647 triangulate( nativeFace, firstNewNativeFacesIndex + i );
648 mNativeMeshFaceCentroids.append( calculateCentroid( nativeFace ) );
651 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
652 mSpatialFaceIndex.
addFace( i, mTriangularMesh );
656 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
658 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
659 mTrianglesToNativeFaces[triangleIndex] = -1;
660 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
664 for (
int i = 0; i < changes.mNativeFaceIndexesToRemove.count(); ++i )
665 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] =
QgsMeshVertex();
668 for (
int i = 0; i < changes.mVerticesIndexesToRemove.count(); ++i )
671 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
672 mIsExtentValid =
false;
675 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
677 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
678 mTriangularMesh.
vertices[vertexIndex].setZ( changes.mNewZValue.at( i ) );
682 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
683 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
686 for (
int i = 0; i < changes.mNewXYValue.count(); ++i )
688 const QgsPointXY &nativeCoordinates = changes.mNewXYValue.at( i );
690 nativeCoordinates.
y(),
691 mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
697 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
698 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
701 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
702 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
708 if ( !changes.mNativeFacesToAdd.isEmpty() )
710 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
711 mSpatialFaceIndex.
removeFace( i, mTriangularMesh );
713 int initialNativeFacesCount = mNativeMeshFaceCentroids.count() - changes.mNativeFacesToAdd.count();
715 mTriangularMesh.
faces.resize( changes.mTrianglesAddedStartIndex );
716 mTrianglesToNativeFaces.resize( changes.mTrianglesAddedStartIndex );
717 mNativeMeshFaceCentroids.resize( initialNativeFacesCount );
720 int initialVerticesCount = mTriangularMesh.
vertices.count() - changes.mAddedVertices.count();
721 mTriangularMesh.
vertices.resize( initialVerticesCount );
723 if ( !changes.mAddedVertices.isEmpty() )
724 mIsExtentValid =
false;
727 for (
const int i : std::as_const( changes.mVerticesIndexesToRemove ) )
730 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
731 mIsExtentValid =
false;
734 QVector<QgsMeshFace> restoredTriangles;
735 QVector<int> restoredTriangularToNative;
736 for (
int i = 0; i < changes.mNativeFacesToRemove.count(); ++i )
738 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( i );
739 triangulateFaces( nativeFace,
740 changes.mNativeFaceIndexesToRemove.at( i ),
742 restoredTriangularToNative,
744 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = calculateCentroid( nativeFace );
746 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
748 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
749 mTriangularMesh.
faces[triangleIndex] = restoredTriangles.at( i );
750 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
751 mTrianglesToNativeFaces[triangleIndex] = restoredTriangularToNative.at( i );
755 for (
int i = 0; i < changes.mOldZValue.count(); ++i )
757 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
758 mTriangularMesh.
vertices[vertexIndex].setZ( changes.mOldZValue.at( i ) );
762 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
763 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
766 for (
int i = 0; i < changes.mOldXYValue.count(); ++i )
768 const QgsPointXY &nativeCoordinates = changes.mOldXYValue.at( i );
770 nativeCoordinates.
y(),
771 mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
777 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
778 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
781 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
782 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
790 mNativeFacesToAdd = topologicalChanges.
addedFaces();
791 mNativeFacesToRemove = topologicalChanges.
removedFaces();
799 mNativeFacesGeometryChanged.resize( mNativeFaceIndexesGeometryChanged.count() );
800 for (
int i = 0; i < mNativeFaceIndexesGeometryChanged.count(); ++i )
801 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)
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.
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.
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.
void setNull()
Mark a rectangle as being null (holding no spatial information).
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.
A triangular/derived 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