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;
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 );
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() );
279 mAverageTriangleSize /= mTriangularMesh.
faceCount();
284 return transformVertex( vertex, Qgis::TransformDirection::Forward );
289 return transformVertex( vertex, Qgis::TransformDirection::Reverse );
317 if ( !mIsExtentValid )
320 for (
int i = 0; i < mTriangularMesh.
vertices.size(); ++i )
321 if ( !mTriangularMesh.
vertices.at( i ).isEmpty() )
324 mIsExtentValid =
true;
338 case QgsMesh::ElementType::Vertex:
340 case QgsMesh::ElementType::Edge:
342 case QgsMesh::ElementType::Face:
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 );
449 return concernedFaceIndex.values();
456 for (
const int faceIndex : faceIndexes )
467 return mSpatialFaceIndex.
intersects( rectangle );
472 return mSpatialEdgeIndex.
intersects( rectangle );
477 QVector<QVector3D> normales(
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 normales[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;
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 >();
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;
664 return _nativeElementsFromElements( triangleIndexes, trianglesToNativeFaces );
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 ) );
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 );
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;
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
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.
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.
bool update(QgsMesh *nativeMesh, const QgsCoordinateTransform &transform)
Constructs triangular mesh from layer's native mesh and transform to destination CRS.
~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)
#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