QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
qgstriangulatedsurface.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgstriangulatedsurface.cpp
3 ---------------------
4 begin : August 2024
5 copyright : (C) 2024 by Jean Felder
6 email : jean dot felder at oslandia dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
19
20#include <memory>
21#include <nlohmann/json.hpp>
22
23#include "qgsgeometryutils.h"
24#include "qgslogger.h"
26#include "qgstriangle.h"
27#include "qgsvertexid.h"
28
33
38
40{
41 auto result = std::make_unique< QgsTriangulatedSurface >();
42 result->mWkbType = mWkbType;
43 return result.release();
44}
45
47{
48 return QStringLiteral( "TIN" );
49}
50
57
58// cppcheck-suppress operatorEqVarError
60{
61 if ( &p != this )
62 {
64 }
65 return *this;
66}
67
72
74{
76 qDeleteAll( mPatches );
77 mPatches.clear();
78 clearCache();
79}
80
81
83{
84 clear();
85
86 if ( !wkbPtr )
87 {
88 return false;
89 }
90
91 Qgis::WkbType type = wkbPtr.readHeader();
93 {
94 return false;
95 }
96 mWkbType = type;
97
98 int nTriangles;
99 wkbPtr >> nTriangles;
100 std::unique_ptr< QgsTriangle > currentTriangle;
101 for ( int i = 0; i < nTriangles; ++i )
102 {
103 Qgis::WkbType triangleType = wkbPtr.readHeader();
104 wkbPtr -= 1 + sizeof( int );
105 Qgis::WkbType flatTriangleType = QgsWkbTypes::flatType( triangleType );
106 if ( flatTriangleType == Qgis::WkbType::Triangle )
107 {
108 currentTriangle = std::make_unique<QgsTriangle>( );
109 }
110 else
111 {
112 return false;
113 }
114 currentTriangle->fromWkb( wkbPtr ); // also updates wkbPtr
115 mPatches.append( currentTriangle.release() );
116 }
117
118 return true;
119}
120
121bool QgsTriangulatedSurface::fromWkt( const QString &wkt )
122{
123 clear();
124
125 QPair<Qgis::WkbType, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
126
128 return false;
129
130 mWkbType = parts.first;
131
132 QString secondWithoutParentheses = parts.second;
133 secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
134 if ( ( parts.second.compare( QLatin1String( "EMPTY" ), Qt::CaseInsensitive ) == 0 ) ||
135 secondWithoutParentheses.isEmpty() )
136 return true;
137
138 QString defaultChildWkbType = QStringLiteral( "Triangle%1%2" ).arg( is3D() ? QStringLiteral( "Z" ) : QString(), isMeasure() ? QStringLiteral( "M" ) : QString() );
139
140 const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
141 for ( const QString &childWkt : blocks )
142 {
143 QPair<Qgis::WkbType, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
144
145 if ( QgsWkbTypes::flatType( childParts.first ) == Qgis::WkbType::Triangle )
146 {
147 mPatches.append( new QgsTriangle() );
148 }
149 else
150 {
151 clear();
152 return false;
153 }
154
155 if ( !mPatches.back()->fromWkt( childWkt ) )
156 {
157 clear();
158 return false;
159 }
160 }
161
162 return true;
163}
164
165QDomElement QgsTriangulatedSurface::asGml2( QDomDocument &, int, const QString &, const AxisOrder ) const
166{
167 QgsDebugError( QStringLiteral( "gml version 2 does not support TIN geometry" ) );
168 return QDomElement();
169}
170
171QDomElement QgsTriangulatedSurface::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
172{
173 QDomElement elemTriangulatedSurface = doc.createElementNS( ns, QStringLiteral( "TriangulatedSurface" ) );
174
175 if ( isEmpty() )
176 return elemTriangulatedSurface;
177
178 QDomElement elemPatches = doc.createElementNS( ns, QStringLiteral( "patches" ) );
179 for ( QgsPolygon *patch : mPatches )
180 {
181 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
182 if ( !triangle )
183 continue;
184
185 QDomElement elemTriangle = triangle->asGml3( doc, precision, ns, axisOrder );
186 elemPatches.appendChild( elemTriangle );
187 }
188 elemTriangulatedSurface.appendChild( elemPatches );
189
190 return elemTriangulatedSurface;
191}
192
194{
195 QgsDebugError( QStringLiteral( "kml format does not support TIN geometry" ) );
196 return QString( "" );
197}
198
200{
201 for ( QgsPolygon *patch : mPatches )
202 {
203 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
204 if ( !triangle )
205 continue;
206
207 QgsCurve *exteriorRing = triangle->exteriorRing();
208 if ( !exteriorRing )
209 continue;
210
211 exteriorRing->normalize();
212 }
213}
214
215QgsTriangulatedSurface *QgsTriangulatedSurface::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing, bool removeRedundantPoints ) const
216{
217 std::unique_ptr< QgsTriangulatedSurface > surface( createEmptyWithSameType() );
218
219 for ( QgsPolygon *patch : mPatches )
220 {
221 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
222 if ( !triangle )
223 continue;
224
225 std::unique_ptr<QgsCurve> exteriorRing( qgsgeometry_cast< QgsCurve *>( triangle->exteriorRing()->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
226 if ( !exteriorRing )
227 {
228 return nullptr;
229 }
230
231 auto gridifiedTriangle = std::make_unique<QgsTriangle>();
232 gridifiedTriangle->setExteriorRing( exteriorRing.release() );
233 surface->addPatch( gridifiedTriangle.release() );
234 }
235
236 return surface.release();
237}
238
239void QgsTriangulatedSurface::setTriangles( const QVector<QgsTriangle *> &triangles )
240{
241 qDeleteAll( mPatches );
242 mPatches.clear();
243
244 for ( QgsTriangle *triangle : triangles )
245 {
246 addPatch( triangle );
247 }
248
249 clearCache();
250}
251
253{
254 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
255 if ( !triangle )
256 {
257 if ( patch )
258 {
259 delete patch;
260 }
261 return;
262 }
263
264 if ( mPatches.empty() )
265 {
267 }
268
269 // Ensure dimensionality of patch matches TIN
270 if ( !is3D() )
271 triangle->dropZValue();
272 else if ( !triangle->is3D() )
273 triangle->addZValue();
274
275 if ( !isMeasure() )
276 triangle->dropMValue();
277 else if ( !triangle->isMeasure() )
278 triangle->addMValue();
279
280 mPatches.append( triangle );
281 clearCache();
282}
283
285{
286 addPatch( triangle );
287}
288
293
295{
297}
298
300{
301 Q_UNUSED( vId )
302 Q_UNUSED( vertex )
303 return false;
304}
305
307{
308 Q_UNUSED( vId )
309 return false;
310}
311
313{
314 const QgsTriangulatedSurface *otherTriangulatedSurface = qgsgeometry_cast<const QgsTriangulatedSurface *>( other );
315 if ( !otherTriangulatedSurface )
316 return -1;
317
318 const int nTriangles1 = mPatches.size();
319 const int nTriangles2 = otherTriangulatedSurface->mPatches.size();
320 if ( nTriangles1 < nTriangles2 )
321 {
322 return -1;
323 }
324 if ( nTriangles1 > nTriangles2 )
325 {
326 return 1;
327 }
328
329 for ( int i = 0; i < nTriangles1; i++ )
330 {
331 const int triangleComp = mPatches.at( i )->compareTo( otherTriangulatedSurface->mPatches.at( i ) );
332 if ( triangleComp != 0 )
333 {
334 return triangleComp;
335 }
336 }
337
338 return 0;
339}
@ Polygon
Polygons.
Definition qgis.h:361
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:277
@ TIN
TIN.
Definition qgis.h:293
@ Triangle
Triangle.
Definition qgis.h:282
virtual QgsAbstractGeometry * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0, bool removeRedundantPoints=false) const =0
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
bool isMeasure() const
Returns true if the geometry contains m values.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, Qgis::WkbType baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
QgsAbstractGeometry()=default
QgsGeometryConstPartIterator parts() const
Returns Java-style iterator for traversal of parts of the geometry.
A const WKB pointer.
Definition qgswkbptr.h:139
Qgis::WkbType readHeader() const
readHeader
Definition qgswkbptr.cpp:56
bool addZValue(double zValue=0) override
Adds a z-dimension to the geometry, initialized to a preset value.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
bool addMValue(double mValue=0) override
Adds a measure to the geometry, initialized to a preset value.
bool dropZValue() override
Drops any z-dimensions which exist in the geometry.
bool dropMValue() override
Drops any measure values which exist in the geometry.
Abstract base class for curved geometry type.
Definition qgscurve.h:36
void normalize() final
Reorganizes the geometry into a normalized form (or "canonical" form).
Definition qgscurve.cpp:212
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType=QString())
Parses a WKT string and returns of list of blocks contained in the WKT.
static QPair< Qgis::WkbType, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
Polygon geometry type.
Definition qgspolygon.h:33
QVector< QgsPolygon * > mPatches
bool isEmpty() const override
Returns true if the geometry is empty.
const QgsPolygon * patchN(int i) const
Retrieves a patch from the polyhedral surface.
QgsPolyhedralSurface & operator=(const QgsPolyhedralSurface &p)
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
Triangle geometry type.
Definition qgstriangle.h:33
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool insertVertex(QgsVertexId position, const QgsPoint &vertex) override
Inserts a vertex into the geometry.
QString asKml(int precision=17) const override
Returns a KML representation of the geometry.
void setTriangles(const QVector< QgsTriangle * > &triangles)
Sets all triangles, transferring ownership to the polyhedral surface.
void addTriangle(QgsTriangle *triangle)
Adds a triangle to the geometry, transferring ownership to the polyhedral surface.
QgsTriangulatedSurface * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
QgsTriangle * triangleN(int index)
Returns the triangle with the specified index.
bool deleteVertex(QgsVertexId position) override
Deletes a vertex within the geometry.
void addPatch(QgsPolygon *patch) override
Adds a patch to the geometry, transferring ownership to the polyhedral surface.
QgsTriangulatedSurface * clone() const override
Clones the geometry by performing a deep copy.
QgsTriangulatedSurface * snappedToGrid(double hSpacing, double vSpacing, double dSpacing=0, double mSpacing=0, bool removeRedundantPoints=false) const override
Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
int compareToSameClass(const QgsAbstractGeometry *other) const final
Compares to an other geometry of the same class, and returns a integer for sorting of the two geometr...
void normalize() override
Reorganizes the geometry into a normalized form (or "canonical" form).
bool fromWkb(QgsConstWkbPtr &wkb) override
Sets the geometry from a WKB string.
QgsTriangulatedSurface & operator=(const QgsTriangulatedSurface &p)
static Qgis::GeometryType geometryType(Qgis::WkbType type)
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
T qgsgeometry_cast(QgsAbstractGeometry *geom)
#define QgsDebugError(str)
Definition qgslogger.h:57
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:30