30 #include "meshOptimizer/meshoptimizer.h"
32 static 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;
50 static 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 );
84 static 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 );
118 void QgsTriangularMesh::triangulate(
const QgsMeshFace &face,
int nativeIndex )
120 triangulateFaces( face, nativeIndex, mTriangularMesh.
faces, mTrianglesToNativeFaces, mTriangularMesh );
127 if ( mCoordinateTransform.
isValid() )
131 transformedVertex.
transform( mCoordinateTransform, direction );
136 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
141 return transformedVertex;
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 );
216 mSpatialFaceIndex =
QgsMeshSpatialIndex( mTriangularMesh,
nullptr, QgsMesh::ElementType::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 );
252 mSpatialEdgeIndex =
QgsMeshSpatialIndex( mTriangularMesh,
nullptr, QgsMesh::ElementType::Edge );
257 void QgsTriangularMesh::finalizeTriangles()
259 mAverageTriangleSize = 0;
260 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
268 QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( v0, v1, v2 );
270 mAverageTriangleSize += std::fmax( bbox.
width(), bbox.
height() );
274 mAverageTriangleSize /= mTriangularMesh.
faceCount();
279 return transformVertex( vertex, Qgis::TransformDirection::Forward );
284 return transformVertex( vertex, Qgis::TransformDirection::Reverse );
301 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
312 if ( !mIsExtentValid )
315 for (
int i = 0; i < mTriangularMesh.
vertices.size(); ++i )
316 if ( !mTriangularMesh.
vertices.at( i ).isEmpty() )
319 mIsExtentValid =
true;
333 case QgsMesh::ElementType::Vertex:
335 case QgsMesh::ElementType::Edge:
337 case QgsMesh::ElementType::Face:
344 void QgsTriangularMesh::addVertex(
const QgsMeshVertex &vertex )
347 mTriangularMesh.
vertices.append( vertexInTriangularCoordinates );
348 if ( !vertexInTriangularCoordinates.
isEmpty() )
349 mExtent.
include( vertexInTriangularCoordinates );
359 return mTriangularMesh.
faces;
364 return mTriangularMesh.
edges;
374 return mNativeMeshFaceCentroids;
379 return mNativeMeshEdgeCentroids;
384 return mTrianglesToNativeFaces;
389 return mEdgesToNativeEdges;
395 if ( mCoordinateTransform.
isValid() )
399 mapPoint = mCoordinateTransform.
transform( point );
404 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
417 for (
const int faceIndex : faceIndexes )
430 if ( triangleIndex == -1 )
433 if ( triangleIndex < mTrianglesToNativeFaces.count() )
434 return mTrianglesToNativeFaces.at( triangleIndex );
444 return concernedFaceIndex.values();
451 for (
const int faceIndex : faceIndexes )
462 return mSpatialFaceIndex.
intersects( rectangle );
467 return mSpatialEdgeIndex.
intersects( rectangle );
472 QVector<QVector3D> normales(
vertices().count(), QVector3D( 0, 0, 0 ) );
476 if ( face.isEmpty() )
479 for (
int i = 0; i < 3; i++ )
481 int index1( face.at( i ) );
482 int index2( face.at( ( i + 1 ) % 3 ) );
483 int index3( face.at( ( i + 2 ) % 3 ) );
489 QVector3D v1(
float( otherVert1.
x() - vert.
x() ),
float( otherVert1.
y() - vert.
y() ), vertScale *
float( otherVert1.
z() - vert.
z() ) );
490 QVector3D v2(
float( otherVert2.
x() - vert.
x() ),
float( otherVert2.
y() - vert.
y() ), vertScale *
float( otherVert2.
z() - vert.
z() ) );
492 normales[index1] += QVector3D::crossProduct( v1, v2 );
500 QVector<QgsTriangularMesh *> simplifiedMeshes;
503 return simplifiedMeshes;
505 if ( !( reductionFactor > 1 ) )
506 return simplifiedMeshes;
508 size_t verticesCount = size_t( mTriangularMesh.
vertices.count() );
510 unsigned int baseIndexCount = mTriangularMesh.
faceCount() * 3;
512 QVector<unsigned int> indexes( mTriangularMesh.
faces.count() * 3 );
513 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
516 for (
int j = 0; j < 3; ++j )
517 indexes[i * 3 + j] = f.at( j );
521 for (
int i = 0; i < mTriangularMesh.
vertices.count(); ++i )
533 size_t maxNumberOfIndexes = baseIndexCount / pow( reductionFactor, path + 1 );
535 if ( indexes.size() <=
int( maxNumberOfIndexes ) )
538 QVector<unsigned int> returnIndexes( indexes.size() );
540 size_t size = meshopt_simplifySloppy(
541 returnIndexes.data(),
547 maxNumberOfIndexes );
550 returnIndexes.resize( size );
552 if ( size == 0 ||
int( size ) >= indexes.size() )
554 QgsDebugMsg( QStringLiteral(
"Mesh simplification failed after %1 path" ).arg( path + 1 ) );
561 newMesh.
faces.resize( returnIndexes.size() / 3 );
562 for (
int i = 0; i < newMesh.
faces.size(); ++i )
565 for (
size_t j = 0; j < 3 ; ++j )
566 f[j] = returnIndexes.at( i * 3 + j ) ;
567 newMesh.
faces[i ] = f;
570 simplifiedMesh->mTriangularMesh = newMesh;
571 simplifiedMesh->mSpatialFaceIndex =
QgsMeshSpatialIndex( simplifiedMesh->mTriangularMesh );
572 simplifiedMesh->finalizeTriangles();
573 simplifiedMeshes.push_back( simplifiedMesh );
575 QgsDebugMsg( QStringLiteral(
"Simplified mesh created with %1 triangles" ).arg( newMesh.
faceCount() ) );
577 simplifiedMesh->mTrianglesToNativeFaces = QVector<int>( simplifiedMesh->
triangles().count(), 0 );
578 for (
int i = 0; i < simplifiedMesh->mTrianglesToNativeFaces.count(); ++i )
583 for (
size_t j = 0; j < 3 ; ++j )
585 x += mTriangularMesh.
vertex( triangle[j] ).
x();
586 y += mTriangularMesh.
vertex( triangle[j] ).
y();
593 if ( indexInBaseMesh == -1 )
598 while ( indexInBaseMesh == -1 && j < 3 )
602 if ( indexInBaseMesh > -1 && indexInBaseMesh < mTrianglesToNativeFaces.count() )
603 simplifiedMesh->mTrianglesToNativeFaces[i] = mTrianglesToNativeFaces[indexInBaseMesh];
606 simplifiedMesh->mLod = path + 1;
607 simplifiedMesh->mBaseTriangularMesh =
this;
609 if ( simplifiedMesh->
triangles().count() < minimumTrianglesCount )
612 indexes = returnIndexes;
616 return simplifiedMeshes;
621 QVector<QgsPoint> ring;
622 for (
int j = 0; j < face.size(); ++j )
624 int vertexId = face[j];
625 Q_ASSERT( vertexId < vertices.size() );
626 const QgsPoint &vertex = vertices[vertexId];
627 ring.append( vertex );
629 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
639 static QSet<int> _nativeElementsFromElements(
const QList<int> &indexes,
const QVector<int> &elementToNativeElements )
641 QSet<int> nativeElements;
642 for (
const int index : indexes )
644 if ( index < elementToNativeElements.count() )
646 const int nativeIndex = elementToNativeElements[index];
647 nativeElements.insert( nativeIndex );
650 return nativeElements;
655 return _nativeElementsFromElements( triangleIndexes, trianglesToNativeFaces );
660 return _nativeElementsFromElements( edgesIndexes, edgesToNativeEdges );
666 return ( p2.
x() - p1.
x() ) * ( p.
y() - p1.
y() ) - ( p.
x() - p1.
x() ) * ( p2.
y() - p1.
y() );
669 static bool _isInTriangle2D(
const QgsPoint &p,
const QVector<QgsMeshVertex> &triangle )
671 return ( ( _isLeft2D( triangle[2], triangle[0], p ) * _isLeft2D( triangle[2], triangle[0], triangle[1] ) >= 0 )
672 && ( _isLeft2D( triangle[0], triangle[1], p ) * _isLeft2D( triangle[0], triangle[1], triangle[2] ) >= 0 )
673 && ( _isLeft2D( triangle[2], triangle[1], p ) * _isLeft2D( triangle[2], triangle[1], triangle[0] ) >= 0 ) );
678 if ( face.count() != 3 )
681 QVector<QgsMeshVertex> triangle( 3 );
682 for (
int i = 0; i < 3; ++i )
684 if ( face[i] > vertices.count() )
686 triangle[i] = vertices[face[i]];
691 return _isInTriangle2D( p, triangle );
696 QSet<int> uniqueVertices;
697 for (
int triangleIndex : triangleIndexes )
699 const QgsMeshFace triangle = triangles[triangleIndex];
700 for (
int i : triangle )
702 uniqueVertices.insert( i );
705 return uniqueVertices;
710 QSet<int> uniqueVertices;
711 for (
int edgeIndex : edgesIndexes )
714 uniqueVertices.insert( edge.first );
715 uniqueVertices.insert( edge.second );
717 return uniqueVertices;
723 if ( changes.mRemovedTriangleIndexes.isEmpty() && !changes.mNativeFaceIndexesToRemove.isEmpty() )
725 for (
int nf = 0; nf < changes.mNativeFaceIndexesToRemove.count(); ++nf )
727 int nativeIndex = changes.mNativeFaceIndexesToRemove.at( nf );
728 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( nf );
729 Q_ASSERT( !nativeFace.isEmpty() );
731 QgsRectangle nativeFaceExtent( mTriangularMesh.
vertex( nativeFace.at( 0 ) ), mTriangularMesh.
vertex( nativeFace.at( 0 ) ) );
732 for (
int i = 1; i < nativeFace.count(); ++i )
735 nativeFaceExtent.
include( triangularVertex );
740 for (
int i = 0; i < concernedTriangle.count(); ++i )
742 int triangleIndex = concernedTriangle.at( i );
743 if ( mTrianglesToNativeFaces.at( triangleIndex ) == nativeIndex )
744 changes.mRemovedTriangleIndexes.append( triangleIndex );
749 if ( changes.mOldZValue.isEmpty() && !changes.mNewZValue.isEmpty() )
751 changes.mOldZValue.reserve( changes.mNewZValue.count() );
752 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
753 changes.mOldZValue.append( mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
756 if ( changes.mTriangleIndexesGeometryChanged.isEmpty() && !changes.mNativeFaceIndexesGeometryChanged.isEmpty() )
758 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
760 const QgsMeshFace &nativeFace = changes.mNativeFacesGeometryChanged.at( i );
761 if ( nativeFace.count() < 2 )
765 for (
int i = 2; i < nativeFace.count(); ++i )
770 while ( pos < triangleIndexes.count() )
773 changes.mNativeFaceIndexesGeometryChanged.at( i ) )
774 triangleIndexes.removeAt( pos );
778 changes.mTriangleIndexesGeometryChanged.append( triangleIndexes );
783 for (
const QgsMeshVertex &vertex : std::as_const( changes.mAddedVertices ) )
787 if ( !changes.mNativeFacesToAdd.isEmpty() )
789 changes.mTrianglesAddedStartIndex = mTriangularMesh.
faceCount();
790 int firstNewNativeFacesIndex = mNativeMeshFaceCentroids.count();
791 for (
int i = 0; i < changes.mNativeFacesToAdd.count(); ++i )
793 const QgsMeshFace &nativeFace = changes.mNativeFacesToAdd.at( i );
794 triangulate( nativeFace, firstNewNativeFacesIndex + i );
795 mNativeMeshFaceCentroids.append( calculateCentroid( nativeFace ) );
798 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
799 mSpatialFaceIndex.
addFace( i, mTriangularMesh );
803 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
805 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
806 mTrianglesToNativeFaces[triangleIndex] = -1;
807 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
811 for (
int i = 0; i < changes.mNativeFaceIndexesToRemove.count(); ++i )
812 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] =
QgsMeshVertex();
815 for (
int i = 0; i < changes.mVerticesIndexesToRemove.count(); ++i )
818 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
819 mIsExtentValid =
false;
822 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
824 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
825 mTriangularMesh.
vertices[vertexIndex].setZ( changes.mNewZValue.at( i ) );
829 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
830 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
833 for (
int i = 0; i < changes.mNewXYValue.count(); ++i )
835 const QgsPointXY &nativeCoordinates = changes.mNewXYValue.at( i );
837 nativeCoordinates.
y(),
838 mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
844 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
845 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
848 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
849 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
855 if ( !changes.mNativeFacesToAdd.isEmpty() )
857 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
858 mSpatialFaceIndex.
removeFace( i, mTriangularMesh );
860 int initialNativeFacesCount = mNativeMeshFaceCentroids.count() - changes.mNativeFacesToAdd.count();
862 mTriangularMesh.
faces.resize( changes.mTrianglesAddedStartIndex );
863 mTrianglesToNativeFaces.resize( changes.mTrianglesAddedStartIndex );
864 mNativeMeshFaceCentroids.resize( initialNativeFacesCount );
867 int initialVerticesCount = mTriangularMesh.
vertices.count() - changes.mAddedVertices.count();
868 mTriangularMesh.
vertices.resize( initialVerticesCount );
870 if ( !changes.mAddedVertices.isEmpty() )
871 mIsExtentValid =
false;
874 for (
const int i : std::as_const( changes.mVerticesIndexesToRemove ) )
877 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
878 mIsExtentValid =
false;
881 QVector<QgsMeshFace> restoredTriangles;
882 QVector<int> restoredTriangularToNative;
883 for (
int i = 0; i < changes.mNativeFacesToRemove.count(); ++i )
885 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( i );
886 triangulateFaces( nativeFace,
887 changes.mNativeFaceIndexesToRemove.at( i ),
889 restoredTriangularToNative,
891 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = calculateCentroid( nativeFace );
893 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
895 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
896 mTriangularMesh.
faces[triangleIndex] = restoredTriangles.at( i );
897 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
898 mTrianglesToNativeFaces[triangleIndex] = restoredTriangularToNative.at( i );
902 for (
int i = 0; i < changes.mOldZValue.count(); ++i )
904 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
905 mTriangularMesh.
vertices[vertexIndex].setZ( changes.mOldZValue.at( i ) );
909 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
910 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
913 for (
int i = 0; i < changes.mOldXYValue.count(); ++i )
915 const QgsPointXY &nativeCoordinates = changes.mOldXYValue.at( i );
917 nativeCoordinates.
y(),
918 mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
924 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
925 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
928 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
929 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
937 mNativeFacesToAdd = topologicalChanges.
addedFaces();
938 mNativeFacesToRemove = topologicalChanges.
removedFaces();
946 mNativeFacesGeometryChanged.resize( mNativeFaceIndexesGeometryChanged.count() );
947 for (
int i = 0; i < mNativeFaceIndexesGeometryChanged.count(); ++i )
948 mNativeFacesGeometryChanged[i] = nativeMesh.
face( mNativeFaceIndexesGeometryChanged.at( i ) );
953 QVector<QPointF> points( face.size() );
954 for (
int j = 0; j < face.size(); ++j )
956 int index = face.at( j );
960 QPolygonF poly( points );
962 ENP_centroid( poly, cx, cy );
970 double ux = v1.
x() - v0.
x();
971 double uy = v1.
y() - v0.
y();
972 double vx = v2.
x() - v0.
x();
973 double vy = v2.
y() - v0.
y();
975 double crossProduct = ux * vy - uy * vx;
976 if ( crossProduct < 0 )
978 std::swap( triangle[1], triangle[2] );
TransformDirection
Indicates the direction (forward or inverse) of a transform.
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.
void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false) override SIP_THROW(QgsCsException)
Transforms the geometry using a coordinate transform.
QPointF toQPointF() const SIP_HOLDGIL
Returns the point as a QPointF.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
A rectangle specified with double values.
void include(const QgsPointXY &p)
Updates the rectangle to include the specified point.
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
void setMinimal() SIP_HOLDGIL
Set a rectangle so that min corner is at max and max corner is at min.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
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.
bool update(QgsMesh *nativeMesh, const QgsCoordinateTransform &transform=QgsCoordinateTransform())
Constructs triangular mesh from layer's native mesh and transform to destination CRS.
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 normale 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.
~QgsTriangularMesh()
Dtor.
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.
bool isInTriangleFace(const QgsPointXY point, const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Tests if point p is on the face defined with vertices.
CORE_EXPORT QSet< int > nativeEdgesFromEdges(const QList< int > &edgesIndexes, const QVector< int > &edgesToNativeEdges)
Returns unique native faces indexes from list of triangle indexes.
CORE_EXPORT std::unique_ptr< QgsPolygon > toPolygon(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry, caller is responsible for delete.
CORE_EXPORT QgsGeometry toGeometry(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry.
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.
CORE_EXPORT QSet< int > nativeVerticesFromEdges(const QList< int > &edgesIndexes, const QVector< QgsMeshEdge > &edges)
Returns unique native faces indexes from list of vertices of triangles.
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
CORE_EXPORT QSet< int > nativeVerticesFromTriangles(const QList< int > &triangleIndexes, const QVector< QgsMeshFace > &triangles)
Returns unique native vertex indexes from list of vertices of triangles.
CORE_EXPORT QSet< int > nativeFacesFromTriangles(const QList< int > &triangleIndexes, const QVector< int > &trianglesToNativeFaces)
Returns unique native faces indexes from list of triangle indexes.
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