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