30 static void ENP_centroid_step(
const QPolygonF &pX,
double &cx,
double &cy,
double &signedArea,
int i,
int i1 )
42 a = x0 * y1 - x1 * y0;
44 cx += ( x0 + x1 ) * a;
45 cy += ( y0 + y1 ) * a;
48 static void ENP_centroid(
const QPolygonF &pX,
double &cx,
double &cy )
57 double signedArea = 0.0;
61 for ( ; i < pX.size() - 1; ++i )
63 ENP_centroid_step( pX, cx, cy, signedArea, i, i + 1 );
67 ENP_centroid_step( pX, cx, cy, signedArea, i, 0 );
70 cx /= ( 6.0 * signedArea );
71 cy /= ( 6.0 * signedArea );
75 void QgsTriangularMesh::triangulate(
const QgsMeshFace &face,
int nativeIndex )
77 int vertexCount = face.size();
78 if ( vertexCount < 3 )
81 while ( vertexCount > 3 )
84 const QgsMeshFace ear = { face[vertexCount - 2], face[vertexCount - 1], face[0] };
85 if ( !( std::isnan( mTriangularMesh.
vertex( ear[0] ).
x() ) ||
86 std::isnan( mTriangularMesh.
vertex( ear[1] ).
x() ) ||
87 std::isnan( mTriangularMesh.
vertex( ear[2] ).
x() ) ) )
89 mTriangularMesh.
faces.push_back( ear );
90 mTrianglesToNativeFaces.push_back( nativeIndex );
95 const QgsMeshFace triangle = { face[1], face[2], face[0] };
96 if ( !( std::isnan( mTriangularMesh.
vertex( triangle[0] ).
x() ) ||
97 std::isnan( mTriangularMesh.
vertex( triangle[1] ).
x() ) ||
98 std::isnan( mTriangularMesh.
vertex( triangle[2] ).
x() ) ) )
100 mTriangularMesh.
faces.push_back( triangle );
101 mTrianglesToNativeFaces.push_back( nativeIndex );
106 void QgsTriangularMesh::setTrianglesCounterClockWise(
QgsMeshFace &face )
108 if ( face.size() != 3 )
115 double ux = v1.
x() - v0.
x();
116 double uy = v1.
y() - v0.
y();
117 double vx = v2.
x() - v0.
x();
118 double vy = v2.
y() - v0.
y();
120 double crossProduct = ux * vy - uy * vx;
121 if ( crossProduct < 0 )
123 std::swap( face[1], face[2] );
132 Q_ASSERT( nativeMesh );
137 mTriangularMesh.
faces.size() >= nativeMesh->
faces.size() &&
144 mTriangularMesh.
faces.clear();
145 mTrianglesToNativeFaces.clear();
146 mNativeMeshFaceCentroids.clear();
151 for (
int i = 0; i < nativeMesh->
vertices.size(); ++i )
154 if ( mCoordinateTransform.
isValid() )
161 mapVertex.
setM( vertex.
m() );
162 mTriangularMesh.
vertices[i] = mapVertex;
167 QgsDebugMsg( QStringLiteral(
"Caught CRS exception %1" ).arg( cse.
what() ) );
173 mTriangularMesh.
vertices[i] = vertex;
178 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
181 triangulate( face, i );
185 mNativeMeshFaceCentroids.resize( nativeMesh->
faces.size() );
186 for (
int i = 0; i < nativeMesh->
faces.size(); ++i )
189 QVector<QPointF> points;
190 points.reserve( face.size() );
191 for (
int j = 0; j < face.size(); ++j )
193 int index = face.at( j );
197 QPolygonF poly( points );
199 ENP_centroid( poly, cx, cy );
207 for (
int i = 0; i < mTriangularMesh.
faceCount(); ++i )
209 setTrianglesCounterClockWise( mTriangularMesh.
faces[i] );
220 return mTriangularMesh.
faces;
225 return mNativeMeshFaceCentroids;
230 return mTrianglesToNativeFaces;
236 for (
const int faceIndex : faceIndexes )
250 for (
const int faceIndex : faceIndexes )
266 QVector<QVector3D> normales(
vertices().count(), QVector3D( 0, 0, 0 ) );
270 for (
int i = 0; i < 3; i++ )
272 int index1( face.at( i ) );
273 int index2( face.at( ( i + 1 ) % 3 ) );
274 int index3( face.at( ( i + 2 ) % 3 ) );
280 QVector3D v1(
float( otherVert1.
x() - vert.x() ),
float( otherVert1.
y() - vert.y() ), vertScale *
float( otherVert1.
z() - vert.z() ) );
281 QVector3D v2(
float( otherVert2.
x() - vert.x() ),
float( otherVert2.
y() - vert.y() ), vertScale *
float( otherVert2.
z() - vert.z() ) );
283 normales[index1] += QVector3D::crossProduct( v1, v2 );
291 QVector<QgsPoint> ring;
292 for (
int j = 0; j < face.size(); ++j )
294 int vertexId = face[j];
295 Q_ASSERT( vertexId < vertices.size() );
296 const QgsPoint &vertex = vertices[vertexId];
297 ring.append( vertex );
299 std::unique_ptr< QgsPolygon > polygon = qgis::make_unique< QgsPolygon >();
311 QSet<int> nativeFaces;
312 for (
const int triangleIndex : triangleIndexes )
314 const int nativeIndex = trianglesToNativeFaces[triangleIndex];
315 nativeFaces.insert( nativeIndex );
317 return nativeFaces.toList();
322 return ( p2.
x() - p1.
x() ) * ( p.
y() - p1.
y() ) - ( p.
x() - p1.
x() ) * ( p2.
y() - p1.
y() );
325 static bool _isInTriangle2D(
const QgsPoint &p,
const QVector<QgsMeshVertex> &triangle )
327 return ( ( _isLeft2D( triangle[2], triangle[0], p ) * _isLeft2D( triangle[2], triangle[0], triangle[1] ) >= 0 )
328 && ( _isLeft2D( triangle[0], triangle[1], p ) * _isLeft2D( triangle[0], triangle[1], triangle[2] ) >= 0 )
329 && ( _isLeft2D( triangle[2], triangle[1], p ) * _isLeft2D( triangle[2], triangle[1], triangle[0] ) >= 0 ) );
334 if ( face.count() != 3 )
337 QVector<QgsMeshVertex> triangle( 3 );
338 for (
int i = 0; i < 3; ++i )
340 if ( face[i] > vertices.count() )
342 triangle[i] = vertices[face[i]];
347 return _isInTriangle2D( p, triangle );
CORE_EXPORT QgsGeometry toGeometry(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry.
A rectangle specified with double values.
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
QPointF toQPointF() const
Returns the point as a QPointF.
QgsMeshVertex vertex(int index) const
Returns a vertex at the index.
int faceIndexForPoint(const QgsPointXY &point) const
Finds index of triangle at given point It uses spatial indexing.
A class to represent a 2D point.
QList< int > intersects(const QgsRectangle &rectangle) const
Returns a list of face ids with a bounding box which intersects the specified rectangle.
A geometry is the spatial representation of a feature.
QVector< QgsMeshVertex > vertices
vertices
const QVector< QgsMeshFace > & triangles() const
Returns triangles.
void setM(double m)
Sets the point's m-value.
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 std::unique_ptr< QgsPolygon > toPolygon(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry, caller is responsible for delete.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
~QgsTriangularMesh()
Dtor.
Point geometry type, with support for z-dimension and m-values.
CORE_EXPORT QList< int > nativeFacesFromTriangles(const QList< int > &triangleIndexes, const QVector< int > &trianglesToNativeFaces)
Returns unique native faces indexes from list of triangle indexes.
QList< int > faceIndexesForRectangle(const QgsRectangle &rectangle) const
Finds indexes of triangles intersecting given bounding box It uses spatial indexing.
A spatial index for QgsMeshFace objects.
void update(QgsMesh *nativeMesh, QgsRenderContext *context)
Constructs triangular mesh from layer's native mesh and context.
Contains information about the context of a rendering operation.
Mesh - vertices and faces.
Line string geometry type, with support for z-dimension and m-values.
QVector< int > QgsMeshFace
List of vertex indexes.
QVector< QgsMeshFace > faces
faces
QVector< QVector3D > vertexNormals(float vertScale) const
Calculates and returns normale vector on each vertex.
Custom exception class for Coordinate Reference System related exceptions.
int faceCount() const
Returns number of faces.
bool contains(const QgsPointXY *p) const
Returns true if the geometry contains the point p.
const QVector< int > & trianglesToNativeFaces() const
Returns mapping between triangles and original faces.
const QVector< QgsMeshVertex > & vertices() const
Returns vertices in map coordinate system.
const QVector< QgsMeshVertex > & centroids() const
Returns centroids of the native faces in map CRS.
QgsPoint QgsMeshVertex
xyz coords of vertex