QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
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
29#include <QString>
30
31using namespace Qt::StringLiterals;
32
37
42
44{
45 auto result = std::make_unique< QgsTriangulatedSurface >();
46 result->mWkbType = mWkbType;
47 return result.release();
48}
49
51{
52 return u"TIN"_s;
53}
54
61
62// cppcheck-suppress operatorEqVarError
64{
65 if ( &p != this )
66 {
68 }
69 return *this;
70}
71
76
78{
80 qDeleteAll( mPatches );
81 mPatches.clear();
82 clearCache();
83}
84
85
87{
88 clear();
89
90 if ( !wkbPtr )
91 {
92 return false;
93 }
94
95 Qgis::WkbType type = wkbPtr.readHeader();
97 {
98 return false;
99 }
100 mWkbType = type;
101
102 int nTriangles;
103 wkbPtr >> nTriangles;
104 std::unique_ptr< QgsTriangle > currentTriangle;
105 for ( int i = 0; i < nTriangles; ++i )
106 {
107 Qgis::WkbType triangleType = wkbPtr.readHeader();
108 wkbPtr -= 1 + sizeof( int );
109 Qgis::WkbType flatTriangleType = QgsWkbTypes::flatType( triangleType );
110 if ( flatTriangleType == Qgis::WkbType::Triangle )
111 {
112 currentTriangle = std::make_unique<QgsTriangle>();
113 }
114 else
115 {
116 return false;
117 }
118 currentTriangle->fromWkb( wkbPtr ); // also updates wkbPtr
119 mPatches.append( currentTriangle.release() );
120 }
121
122 return true;
123}
124
125bool QgsTriangulatedSurface::fromWkt( const QString &wkt )
126{
127 clear();
128
129 QPair<Qgis::WkbType, QString> parts = QgsGeometryUtils::wktReadBlock( wkt );
130
132 return false;
133
134 mWkbType = parts.first;
135
136 QString secondWithoutParentheses = parts.second;
137 secondWithoutParentheses = secondWithoutParentheses.remove( '(' ).remove( ')' ).simplified().remove( ' ' );
138 if ( ( parts.second.compare( "EMPTY"_L1, Qt::CaseInsensitive ) == 0 ) || secondWithoutParentheses.isEmpty() )
139 return true;
140
141 QString defaultChildWkbType = u"Triangle%1%2"_s.arg( is3D() ? u"Z"_s : QString(), isMeasure() ? u"M"_s : QString() );
142
143 const QStringList blocks = QgsGeometryUtils::wktGetChildBlocks( parts.second, defaultChildWkbType );
144 for ( const QString &childWkt : blocks )
145 {
146 QPair<Qgis::WkbType, QString> childParts = QgsGeometryUtils::wktReadBlock( childWkt );
147
148 if ( QgsWkbTypes::flatType( childParts.first ) == Qgis::WkbType::Triangle )
149 {
150 mPatches.append( new QgsTriangle() );
151 }
152 else
153 {
154 clear();
155 return false;
156 }
157
158 if ( !mPatches.back()->fromWkt( childWkt ) )
159 {
160 clear();
161 return false;
162 }
163 }
164
165 return true;
166}
167
168QDomElement QgsTriangulatedSurface::asGml2( QDomDocument &, int, const QString &, const AxisOrder ) const
169{
170 QgsDebugError( u"gml version 2 does not support TIN geometry"_s );
171 return QDomElement();
172}
173
174QDomElement QgsTriangulatedSurface::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
175{
176 QDomElement elemTriangulatedSurface = doc.createElementNS( ns, u"TriangulatedSurface"_s );
177
178 if ( isEmpty() )
179 return elemTriangulatedSurface;
180
181 QDomElement elemPatches = doc.createElementNS( ns, u"patches"_s );
182 for ( QgsPolygon *patch : mPatches )
183 {
184 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
185 if ( !triangle )
186 continue;
187
188 QDomElement elemTriangle = triangle->asGml3( doc, precision, ns, axisOrder );
189 elemPatches.appendChild( elemTriangle );
190 }
191 elemTriangulatedSurface.appendChild( elemPatches );
192
193 return elemTriangulatedSurface;
194}
195
197{
198 QgsDebugError( u"kml format does not support TIN geometry"_s );
199 return QString( "" );
200}
201
203{
204 for ( QgsPolygon *patch : mPatches )
205 {
206 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
207 if ( !triangle )
208 continue;
209
210 QgsCurve *exteriorRing = triangle->exteriorRing();
211 if ( !exteriorRing )
212 continue;
213
214 exteriorRing->normalize();
215 }
216}
217
218QgsTriangulatedSurface *QgsTriangulatedSurface::snappedToGrid( double hSpacing, double vSpacing, double dSpacing, double mSpacing, bool removeRedundantPoints ) const
219{
220 std::unique_ptr< QgsTriangulatedSurface > surface( createEmptyWithSameType() );
221
222 for ( QgsPolygon *patch : mPatches )
223 {
224 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
225 if ( !triangle )
226 continue;
227
228 std::unique_ptr<QgsCurve> exteriorRing( qgsgeometry_cast< QgsCurve *>( triangle->exteriorRing()->snappedToGrid( hSpacing, vSpacing, dSpacing, mSpacing, removeRedundantPoints ) ) );
229 if ( !exteriorRing )
230 {
231 return nullptr;
232 }
233
234 auto gridifiedTriangle = std::make_unique<QgsTriangle>();
235 gridifiedTriangle->setExteriorRing( exteriorRing.release() );
236 surface->addPatch( gridifiedTriangle.release() );
237 }
238
239 return surface.release();
240}
241
242void QgsTriangulatedSurface::setTriangles( const QVector<QgsTriangle *> &triangles )
243{
244 qDeleteAll( mPatches );
245 mPatches.clear();
246
247 for ( QgsTriangle *triangle : triangles )
248 {
249 addPatch( triangle );
250 }
251
252 clearCache();
253}
254
256{
257 QgsTriangle *triangle = qgsgeometry_cast<QgsTriangle *>( patch );
258 if ( !triangle )
259 {
260 if ( patch )
261 {
262 delete patch;
263 }
264 return;
265 }
266
267 if ( mPatches.empty() )
268 {
270 }
271
272 // Ensure dimensionality of patch matches TIN
273 if ( !is3D() )
274 triangle->dropZValue();
275 else if ( !triangle->is3D() )
276 triangle->addZValue();
277
278 if ( !isMeasure() )
279 triangle->dropMValue();
280 else if ( !triangle->isMeasure() )
281 triangle->addMValue();
282
283 mPatches.append( triangle );
284 clearCache();
285}
286
288{
289 addPatch( triangle );
290}
291
296
298{
300}
301
303{
304 Q_UNUSED( vId )
305 Q_UNUSED( vertex )
306 return false;
307}
308
310{
311 Q_UNUSED( vId )
312 return false;
313}
314
316{
317 const QgsTriangulatedSurface *otherTriangulatedSurface = qgsgeometry_cast<const QgsTriangulatedSurface *>( other );
318 if ( !otherTriangulatedSurface )
319 return -1;
320
321 const int nTriangles1 = mPatches.size();
322 const int nTriangles2 = otherTriangulatedSurface->mPatches.size();
323 if ( nTriangles1 < nTriangles2 )
324 {
325 return -1;
326 }
327 if ( nTriangles1 > nTriangles2 )
328 {
329 return 1;
330 }
331
332 for ( int i = 0; i < nTriangles1; i++ )
333 {
334 const int triangleComp = mPatches.at( i )->compareTo( otherTriangulatedSurface->mPatches.at( i ) );
335 if ( triangleComp != 0 )
336 {
337 return triangleComp;
338 }
339 }
340
341 return 0;
342}
@ Polygon
Polygons.
Definition qgis.h:382
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:294
@ TIN
TIN.
Definition qgis.h:310
@ Triangle
Triangle.
Definition qgis.h:299
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:211
Qgis::WkbType readHeader() const
readHeader
Definition qgswkbptr.cpp:60
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:211
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:53
Polygon geometry type.
Definition qgspolygon.h:37
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:59
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:34