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 ) )
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 >();
643 static 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() );
673 static 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] );