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;
63 for ( ; i < pX.size() - 1; ++i )
65 ENP_centroid_step( pX, cx, cy, signedArea, i, i + 1 );
69 ENP_centroid_step( pX, cx, cy, signedArea, i, 0 );
72 cx /= ( 6.0 * signedArea );
73 cy /= ( 6.0 * signedArea );
76 void QgsTriangularMesh::triangulate(
const QgsMeshFace &face,
int nativeIndex )
78 int vertexCount = face.size();
79 if ( vertexCount < 3 )
82 while ( vertexCount > 3 )
85 const QgsMeshFace ear = { face[vertexCount - 2], face[vertexCount - 1], face[0] };
86 if ( !( std::isnan( mTriangularMesh.
vertex( ear[0] ).
x() ) ||
87 std::isnan( mTriangularMesh.
vertex( ear[1] ).
x() ) ||
88 std::isnan( mTriangularMesh.
vertex( ear[2] ).
x() ) ) )
90 mTriangularMesh.
faces.push_back( ear );
91 mTrianglesToNativeFaces.push_back( nativeIndex );
96 const QgsMeshFace triangle = { face[1], face[2], face[0] };
97 if ( !( std::isnan( mTriangularMesh.
vertex( triangle[0] ).
x() ) ||
98 std::isnan( mTriangularMesh.
vertex( triangle[1] ).
x() ) ||
99 std::isnan( mTriangularMesh.
vertex( triangle[2] ).
x() ) ) )
101 mTriangularMesh.
faces.push_back( triangle );
102 mTrianglesToNativeFaces.push_back( nativeIndex );
108 return mAverageTriangleSize;
116 Q_ASSERT( nativeMesh );
120 mTriangularMesh.
faces.size() >= nativeMesh->
faces.size() &&
121 mTriangularMesh.
edges.size() == nativeMesh->
edges.size() &&
130 mTriangularMesh.
faces.clear();
131 mTriangularMesh.
edges.clear();
132 mTrianglesToNativeFaces.clear();
133 mEdgesToNativeEdges.clear();
134 mNativeMeshFaceCentroids.clear();
135 mNativeMeshEdgeCentroids.clear();
138 mCoordinateTransform = transform;
141 for (
int i = 0; i < nativeMesh->
vertices.size(); ++i )
144 if ( mCoordinateTransform.
isValid() )
151 mapVertex.
setM( vertex.
m() );
152 mTriangularMesh.
vertices[i] = mapVertex;
158 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
164 mTriangularMesh.
vertices[i] = vertex;
170 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
173 triangulate( face, i );
177 mNativeMeshFaceCentroids.resize( nativeMesh->
faces.size() );
178 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
181 QVector<QPointF> points;
182 points.reserve( face.size() );
183 for (
int j = 0; j < face.size(); ++j )
185 int index = face.at( j );
189 QPolygonF poly( points );
191 ENP_centroid( poly, cx, cy );
203 const QVector<QgsMeshEdge>
edges = nativeMesh->
edges;
204 for (
int nativeIndex = 0; nativeIndex <
edges.size(); ++nativeIndex )
207 if ( !( std::isnan( mTriangularMesh.
vertex( edge.first ).
x() ) ||
208 std::isnan( mTriangularMesh.
vertex( edge.second ).
x() ) ) )
210 mTriangularMesh.
edges.push_back( edge );
211 mEdgesToNativeEdges.push_back( nativeIndex );
216 mNativeMeshEdgeCentroids.resize( nativeMesh->
edgeCount() );
217 for (
int i = 0; i < nativeMesh->
edgeCount(); ++i )
222 mNativeMeshEdgeCentroids[i] =
QgsMeshVertex( ( a.
x() + b.
x() ) / 2.0, ( a.
y() + b.
y() ) / 2.0, ( a.
z() + b.
z() ) / 2.0 );
226 mSpatialEdgeIndex =
QgsMeshSpatialIndex( mTriangularMesh,
nullptr, QgsMesh::ElementType::Edge );
231 void QgsTriangularMesh::finalizeTriangles()
233 mAverageTriangleSize = 0;
234 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
242 QgsRectangle bbox = QgsMeshLayerUtils::triangleBoundingBox( v0, v1, v2 );
244 mAverageTriangleSize += std::fmax( bbox.
width(), bbox.
height() );
248 double ux = v1.
x() - v0.
x();
249 double uy = v1.
y() - v0.
y();
250 double vx = v2.
x() - v0.
x();
251 double vy = v2.
y() - v0.
y();
253 double crossProduct = ux * vy - uy * vx;
254 if ( crossProduct < 0 )
256 std::swap( face[1], face[2] );
259 mAverageTriangleSize /= mTriangularMesh.
faceCount();
276 case QgsMesh::ElementType::Vertex:
278 case QgsMesh::ElementType::Edge:
294 return mTriangularMesh.
faces;
299 return mTriangularMesh.
edges;
309 return mNativeMeshFaceCentroids;
314 return mNativeMeshEdgeCentroids;
319 return mTrianglesToNativeFaces;
324 return mEdgesToNativeEdges;
330 for (
const int faceIndex : faceIndexes )
344 for (
const int faceIndex : faceIndexes )
355 return mSpatialFaceIndex.
intersects( rectangle );
360 return mSpatialEdgeIndex.
intersects( rectangle );
365 QVector<QVector3D> normales(
vertices().count(), QVector3D( 0, 0, 0 ) );
369 for (
int i = 0; i < 3; i++ )
371 int index1( face.at( i ) );
372 int index2( face.at( ( i + 1 ) % 3 ) );
373 int index3( face.at( ( i + 2 ) % 3 ) );
379 QVector3D v1(
float( otherVert1.
x() - vert.
x() ),
float( otherVert1.
y() - vert.
y() ), vertScale *
float( otherVert1.
z() - vert.
z() ) );
380 QVector3D v2(
float( otherVert2.
x() - vert.
x() ),
float( otherVert2.
y() - vert.
y() ), vertScale *
float( otherVert2.
z() - vert.
z() ) );
382 normales[index1] += QVector3D::crossProduct( v1, v2 );
390 QVector<QgsTriangularMesh *> simplifiedMeshes;
393 return simplifiedMeshes;
395 if ( !( reductionFactor > 1 ) )
396 return simplifiedMeshes;
398 size_t verticesCount = size_t( mTriangularMesh.
vertices.count() );
400 unsigned int baseIndexCount = mTriangularMesh.
faceCount() * 3;
402 QVector<unsigned int> indexes( mTriangularMesh.
faces.count() * 3 );
403 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
406 for (
int j = 0; j < 3; ++j )
407 indexes[i * 3 + j] = f.at( j );
411 for (
int i = 0; i < mTriangularMesh.
vertices.count(); ++i )
423 size_t maxNumberOfIndexes = baseIndexCount / pow( reductionFactor, path + 1 );
425 if ( indexes.size() <=
int( maxNumberOfIndexes ) )
428 QVector<unsigned int> returnIndexes( indexes.size() );
430 size_t size = meshopt_simplifySloppy(
431 returnIndexes.data(),
437 maxNumberOfIndexes );
440 returnIndexes.resize( size );
442 if ( size == 0 ||
int( size ) >= indexes.size() )
444 QgsDebugMsg( QStringLiteral(
"Mesh simplification failed after %1 path" ).arg( path + 1 ) );
451 newMesh.
faces.resize( returnIndexes.size() / 3 );
452 for (
int i = 0; i < newMesh.
faces.size(); ++i )
455 for (
size_t j = 0; j < 3 ; ++j )
456 f[j] = returnIndexes.at( i * 3 + j ) ;
457 newMesh.
faces[i ] = f;
460 simplifiedMesh->mTriangularMesh = newMesh;
461 simplifiedMesh->mSpatialFaceIndex =
QgsMeshSpatialIndex( simplifiedMesh->mTriangularMesh );
462 simplifiedMesh->finalizeTriangles();
463 simplifiedMeshes.push_back( simplifiedMesh );
465 QgsDebugMsg( QStringLiteral(
"Simplified mesh created with %1 triangles" ).arg( newMesh.
faceCount() ) );
467 simplifiedMesh->mTrianglesToNativeFaces = QVector<int>( simplifiedMesh->
triangles().count(), 0 );
468 for (
int i = 0; i < simplifiedMesh->mTrianglesToNativeFaces.count(); ++i )
473 for (
size_t j = 0; j < 3 ; ++j )
475 x += mTriangularMesh.
vertex( triangle[j] ).
x();
476 y += mTriangularMesh.
vertex( triangle[j] ).
y();
483 if ( indexInBaseMesh == -1 )
488 while ( indexInBaseMesh == -1 && j < 3 )
492 if ( indexInBaseMesh > -1 && indexInBaseMesh < mTrianglesToNativeFaces.count() )
493 simplifiedMesh->mTrianglesToNativeFaces[i] = mTrianglesToNativeFaces[indexInBaseMesh];
496 simplifiedMesh->mLod = path + 1;
497 simplifiedMesh->mBaseTriangularMesh =
this;
499 if ( simplifiedMesh->
triangles().count() < minimumTrianglesCount )
502 indexes = returnIndexes;
506 return simplifiedMeshes;
511 QVector<QgsPoint> ring;
512 for (
int j = 0; j < face.size(); ++j )
514 int vertexId = face[j];
515 Q_ASSERT( vertexId < vertices.size() );
516 const QgsPoint &vertex = vertices[vertexId];
517 ring.append( vertex );
519 std::unique_ptr< QgsPolygon > polygon = qgis::make_unique< QgsPolygon >();
529 static QSet<int> _nativeElementsFromElements(
const QList<int> &indexes,
const QVector<int> &elementToNativeElements )
531 QSet<int> nativeElements;
532 for (
const int index : indexes )
534 const int nativeIndex = elementToNativeElements[index];
535 nativeElements.insert( nativeIndex );
537 return nativeElements;
542 return _nativeElementsFromElements( triangleIndexes, trianglesToNativeFaces );
547 return _nativeElementsFromElements( edgesIndexes, edgesToNativeEdges );
553 return ( p2.
x() - p1.
x() ) * ( p.
y() - p1.
y() ) - ( p.
x() - p1.
x() ) * ( p2.
y() - p1.
y() );
556 static bool _isInTriangle2D(
const QgsPoint &p,
const QVector<QgsMeshVertex> &triangle )
558 return ( ( _isLeft2D( triangle[2], triangle[0], p ) * _isLeft2D( triangle[2], triangle[0], triangle[1] ) >= 0 )
559 && ( _isLeft2D( triangle[0], triangle[1], p ) * _isLeft2D( triangle[0], triangle[1], triangle[2] ) >= 0 )
560 && ( _isLeft2D( triangle[2], triangle[1], p ) * _isLeft2D( triangle[2], triangle[1], triangle[0] ) >= 0 ) );
565 if ( face.count() != 3 )
568 QVector<QgsMeshVertex> triangle( 3 );
569 for (
int i = 0; i < 3; ++i )
571 if ( face[i] > vertices.count() )
573 triangle[i] = vertices[face[i]];
578 return _isInTriangle2D( p, triangle );
583 QSet<int> uniqueVertices;
584 for (
int triangleIndex : triangleIndexes )
586 const QgsMeshFace triangle = triangles[triangleIndex];
587 for (
int i : triangle )
589 uniqueVertices.insert( i );
592 return uniqueVertices;
597 QSet<int> uniqueVertices;
598 for (
int edgeIndex : edgesIndexes )
601 uniqueVertices.insert( edge.first );
602 uniqueVertices.insert( edge.second );
604 return uniqueVertices;