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 );
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 );
257void 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:
344void 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 ) )
537 delete simplifiedMesh;
541 QVector<unsigned int> returnIndexes( indexes.size() );
543 size_t size = meshopt_simplifySloppy(
544 returnIndexes.data(),
550 maxNumberOfIndexes );
553 returnIndexes.resize( size );
555 if ( size == 0 ||
int( size ) >= indexes.size() )
557 QgsDebugMsg( QStringLiteral(
"Mesh simplification failed after %1 path" ).arg( path + 1 ) );
558 delete simplifiedMesh;
565 newMesh.
faces.resize( returnIndexes.size() / 3 );
566 for (
int i = 0; i < newMesh.
faces.size(); ++i )
569 for (
size_t j = 0; j < 3 ; ++j )
570 f[j] = returnIndexes.at( i * 3 + j ) ;
571 newMesh.
faces[i ] = f;
574 simplifiedMesh->mTriangularMesh = newMesh;
575 simplifiedMesh->mSpatialFaceIndex =
QgsMeshSpatialIndex( simplifiedMesh->mTriangularMesh );
576 simplifiedMesh->finalizeTriangles();
577 simplifiedMeshes.push_back( simplifiedMesh );
581 simplifiedMesh->mTrianglesToNativeFaces = QVector<int>( simplifiedMesh->
triangles().count(), 0 );
582 for (
int i = 0; i < simplifiedMesh->mTrianglesToNativeFaces.count(); ++i )
587 for (
size_t j = 0; j < 3 ; ++j )
589 x += mTriangularMesh.
vertex( triangle[j] ).
x();
590 y += mTriangularMesh.
vertex( triangle[j] ).
y();
597 if ( indexInBaseMesh == -1 )
602 while ( indexInBaseMesh == -1 && j < 3 )
606 if ( indexInBaseMesh > -1 && indexInBaseMesh < mTrianglesToNativeFaces.count() )
607 simplifiedMesh->mTrianglesToNativeFaces[i] = mTrianglesToNativeFaces[indexInBaseMesh];
610 simplifiedMesh->mLod = path + 1;
611 simplifiedMesh->mBaseTriangularMesh =
this;
613 if ( simplifiedMesh->
triangles().count() < minimumTrianglesCount )
616 indexes = returnIndexes;
620 return simplifiedMeshes;
625 QVector<QgsPoint> ring;
626 for (
int j = 0; j < face.size(); ++j )
628 int vertexId = face[j];
629 Q_ASSERT( vertexId < vertices.size() );
630 const QgsPoint &vertex = vertices[vertexId];
631 ring.append( vertex );
633 std::unique_ptr< QgsPolygon > polygon = std::make_unique< QgsPolygon >();
643static QSet<int> _nativeElementsFromElements(
const QList<int> &indexes,
const QVector<int> &elementToNativeElements )
645 QSet<int> nativeElements;
646 for (
const int index : indexes )
648 if ( index < elementToNativeElements.count() )
650 const int nativeIndex = elementToNativeElements[index];
651 nativeElements.insert( nativeIndex );
654 return nativeElements;
659 return _nativeElementsFromElements( triangleIndexes, trianglesToNativeFaces );
664 return _nativeElementsFromElements( edgesIndexes, edgesToNativeEdges );
670 return ( p2.
x() - p1.
x() ) * ( p.
y() - p1.
y() ) - ( p.
x() - p1.
x() ) * ( p2.
y() - p1.
y() );
673static bool _isInTriangle2D(
const QgsPoint &p,
const QVector<QgsMeshVertex> &triangle )
675 return ( ( _isLeft2D( triangle[2], triangle[0], p ) * _isLeft2D( triangle[2], triangle[0], triangle[1] ) >= 0 )
676 && ( _isLeft2D( triangle[0], triangle[1], p ) * _isLeft2D( triangle[0], triangle[1], triangle[2] ) >= 0 )
677 && ( _isLeft2D( triangle[2], triangle[1], p ) * _isLeft2D( triangle[2], triangle[1], triangle[0] ) >= 0 ) );
682 if ( face.count() != 3 )
685 QVector<QgsMeshVertex> triangle( 3 );
686 for (
int i = 0; i < 3; ++i )
688 if ( face[i] > vertices.count() )
690 triangle[i] = vertices[face[i]];
695 return _isInTriangle2D( p, triangle );
700 QSet<int> uniqueVertices;
701 for (
int triangleIndex : triangleIndexes )
703 const QgsMeshFace triangle = triangles[triangleIndex];
704 for (
int i : triangle )
706 uniqueVertices.insert( i );
709 return uniqueVertices;
714 QSet<int> uniqueVertices;
715 for (
int edgeIndex : edgesIndexes )
718 uniqueVertices.insert( edge.first );
719 uniqueVertices.insert( edge.second );
721 return uniqueVertices;
727 if ( changes.mRemovedTriangleIndexes.isEmpty() && !changes.mNativeFaceIndexesToRemove.isEmpty() )
729 for (
int nf = 0; nf < changes.mNativeFaceIndexesToRemove.count(); ++nf )
731 int nativeIndex = changes.mNativeFaceIndexesToRemove.at( nf );
732 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( nf );
733 Q_ASSERT( !nativeFace.isEmpty() );
735 QgsRectangle nativeFaceExtent( mTriangularMesh.
vertex( nativeFace.at( 0 ) ), mTriangularMesh.
vertex( nativeFace.at( 0 ) ) );
736 for (
int i = 1; i < nativeFace.count(); ++i )
739 nativeFaceExtent.
include( triangularVertex );
744 for (
int i = 0; i < concernedTriangle.count(); ++i )
746 int triangleIndex = concernedTriangle.at( i );
747 if ( mTrianglesToNativeFaces.at( triangleIndex ) == nativeIndex )
748 changes.mRemovedTriangleIndexes.append( triangleIndex );
753 if ( changes.mOldZValue.isEmpty() && !changes.mNewZValue.isEmpty() )
755 changes.mOldZValue.reserve( changes.mNewZValue.count() );
756 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
757 changes.mOldZValue.append( mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
760 if ( changes.mTriangleIndexesGeometryChanged.isEmpty() && !changes.mNativeFaceIndexesGeometryChanged.isEmpty() )
762 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
764 const QgsMeshFace &nativeFace = changes.mNativeFacesGeometryChanged.at( i );
765 if ( nativeFace.count() < 2 )
769 for (
int i = 2; i < nativeFace.count(); ++i )
774 while ( pos < triangleIndexes.count() )
777 changes.mNativeFaceIndexesGeometryChanged.at( i ) )
778 triangleIndexes.removeAt( pos );
782 changes.mTriangleIndexesGeometryChanged.append( triangleIndexes );
787 for (
const QgsMeshVertex &vertex : std::as_const( changes.mAddedVertices ) )
791 if ( !changes.mNativeFacesToAdd.isEmpty() )
793 changes.mTrianglesAddedStartIndex = mTriangularMesh.
faceCount();
794 int firstNewNativeFacesIndex = mNativeMeshFaceCentroids.count();
795 for (
int i = 0; i < changes.mNativeFacesToAdd.count(); ++i )
797 const QgsMeshFace &nativeFace = changes.mNativeFacesToAdd.at( i );
798 triangulate( nativeFace, firstNewNativeFacesIndex + i );
799 mNativeMeshFaceCentroids.append( calculateCentroid( nativeFace ) );
802 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
803 mSpatialFaceIndex.
addFace( i, mTriangularMesh );
807 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
809 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
810 mTrianglesToNativeFaces[triangleIndex] = -1;
811 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
815 for (
int i = 0; i < changes.mNativeFaceIndexesToRemove.count(); ++i )
816 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] =
QgsMeshVertex();
819 for (
int i = 0; i < changes.mVerticesIndexesToRemove.count(); ++i )
822 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
823 mIsExtentValid =
false;
826 for (
int i = 0; i < changes.mNewZValue.count(); ++i )
828 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
829 mTriangularMesh.
vertices[vertexIndex].setZ( changes.mNewZValue.at( i ) );
833 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
834 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
837 for (
int i = 0; i < changes.mNewXYValue.count(); ++i )
839 const QgsPointXY &nativeCoordinates = changes.mNewXYValue.at( i );
841 nativeCoordinates.
y(),
842 mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
848 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
849 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
852 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
853 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
859 if ( !changes.mNativeFacesToAdd.isEmpty() )
861 for (
int i = changes.mTrianglesAddedStartIndex; i < mTriangularMesh.
faceCount(); ++i )
862 mSpatialFaceIndex.
removeFace( i, mTriangularMesh );
864 int initialNativeFacesCount = mNativeMeshFaceCentroids.count() - changes.mNativeFacesToAdd.count();
866 mTriangularMesh.
faces.resize( changes.mTrianglesAddedStartIndex );
867 mTrianglesToNativeFaces.resize( changes.mTrianglesAddedStartIndex );
868 mNativeMeshFaceCentroids.resize( initialNativeFacesCount );
871 int initialVerticesCount = mTriangularMesh.
vertices.count() - changes.mAddedVertices.count();
872 mTriangularMesh.
vertices.resize( initialVerticesCount );
874 if ( !changes.mAddedVertices.isEmpty() )
875 mIsExtentValid =
false;
878 for (
const int i : std::as_const( changes.mVerticesIndexesToRemove ) )
881 if ( !changes.mVerticesIndexesToRemove.isEmpty() )
882 mIsExtentValid =
false;
885 QVector<QgsMeshFace> restoredTriangles;
886 QVector<int> restoredTriangularToNative;
887 for (
int i = 0; i < changes.mNativeFacesToRemove.count(); ++i )
889 const QgsMeshFace &nativeFace = changes.mNativeFacesToRemove.at( i );
890 triangulateFaces( nativeFace,
891 changes.mNativeFaceIndexesToRemove.at( i ),
893 restoredTriangularToNative,
895 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesToRemove.at( i )] = calculateCentroid( nativeFace );
897 for (
int i = 0; i < changes.mRemovedTriangleIndexes.count(); ++i )
899 int triangleIndex = changes.mRemovedTriangleIndexes.at( i );
900 mTriangularMesh.
faces[triangleIndex] = restoredTriangles.at( i );
901 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
902 mTrianglesToNativeFaces[triangleIndex] = restoredTriangularToNative.at( i );
906 for (
int i = 0; i < changes.mOldZValue.count(); ++i )
908 int vertexIndex = changes.mChangedVerticesCoordinates.at( i );
909 mTriangularMesh.
vertices[vertexIndex].setZ( changes.mOldZValue.at( i ) );
913 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
914 mSpatialFaceIndex.
removeFace( triangleIndex, mTriangularMesh );
917 for (
int i = 0; i < changes.mOldXYValue.count(); ++i )
919 const QgsPointXY &nativeCoordinates = changes.mOldXYValue.at( i );
921 nativeCoordinates.
y(),
922 mTriangularMesh.
vertices.at( changes.mChangedVerticesCoordinates.at( i ) ).z() );
928 for (
const int triangleIndex : std::as_const( changes.mTriangleIndexesGeometryChanged ) )
929 mSpatialFaceIndex.
addFace( triangleIndex, mTriangularMesh );
932 for (
int i = 0; i < changes.mNativeFaceIndexesGeometryChanged.count(); ++i )
933 mNativeMeshFaceCentroids[changes.mNativeFaceIndexesGeometryChanged.at( i )] = calculateCentroid( changes.mNativeFacesGeometryChanged.at( i ) );
941 mNativeFacesToAdd = topologicalChanges.
addedFaces();
942 mNativeFacesToRemove = topologicalChanges.
removedFaces();
950 mNativeFacesGeometryChanged.resize( mNativeFaceIndexesGeometryChanged.count() );
951 for (
int i = 0; i < mNativeFaceIndexesGeometryChanged.count(); ++i )
952 mNativeFacesGeometryChanged[i] = nativeMesh.
face( mNativeFaceIndexesGeometryChanged.at( i ) );
957 QVector<QPointF> points( face.size() );
958 for (
int j = 0; j < face.size(); ++j )
960 int index = face.at( j );
964 QPolygonF poly( points );
966 ENP_centroid( poly, cx, cy );
974 double ux = v1.
x() - v0.
x();
975 double uy = v1.
y() - v0.
y();
976 double vx = v2.
x() - v0.
x();
977 double vy = v2.
y() - v0.
y();
979 double crossProduct = ux * vy - uy * vx;
980 if ( crossProduct < 0 )
982 std::swap( triangle[1], triangle[2] );
TransformDirection
Flags for raster layer temporal capabilities.
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.
#define QgsDebugMsgLevel(str, level)
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