QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgspolyhedralsurface.h
Go to the documentation of this file.
1/***************************************************************************
2 qgspolyhedralsurface.h
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
18#ifndef QGSPOLYHEDRALSURFACE_H
19#define QGSPOLYHEDRALSURFACE_H
20
21#include "qgis_core.h"
22#include "qgis_sip.h"
23#include "qgsmultipolygon.h"
24#include "qgspolygon.h"
25#include "qgssurface.h"
26
27#include <QString>
28
29using namespace Qt::StringLiterals;
30
40class CORE_EXPORT QgsPolyhedralSurface: public QgsSurface
41{
42 public:
45
46
50 QgsPolyhedralSurface( const QgsMultiPolygon *multiPolygon );
51
53
54#ifndef SIP_RUN
55 private:
56 bool fuzzyHelper( const QgsAbstractGeometry &other, double epsilon, bool useDistance ) const
57 {
59 if ( !otherPolygon )
60 return false;
61
62 //run cheap checks first
63 if ( mWkbType != otherPolygon->mWkbType )
64 return false;
65
66 if ( mPatches.count() != otherPolygon->mPatches.count() )
67 return false;
68
69 for ( int i = 0; i < mPatches.count(); ++i )
70 {
71 if ( ( !mPatches.at( i ) && otherPolygon->mPatches.at( i ) ) ||
72 ( mPatches.at( i ) && !otherPolygon->mPatches.at( i ) ) )
73 return false;
74
75 if ( useDistance )
76 {
77 if ( mPatches.at( i ) && otherPolygon->mPatches.at( i ) &&
78 !( *mPatches.at( i ) ).fuzzyDistanceEqual( *otherPolygon->mPatches.at( i ), epsilon ) )
79 return false;
80 }
81 else
82 {
83 if ( mPatches.at( i ) && otherPolygon->mPatches.at( i ) &&
84 !( *mPatches.at( i ) ).fuzzyEqual( *otherPolygon->mPatches.at( i ), epsilon ) )
85 return false;
86 }
87 }
88
89 return true;
90 }
91#endif
92
93 public:
94 bool fuzzyEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
95 {
96 return fuzzyHelper( other, epsilon, false );
97 }
98 bool fuzzyDistanceEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
99 {
100 return fuzzyHelper( other, epsilon, true );
101 }
102
103 bool operator==( const QgsAbstractGeometry &other ) const override
104 {
105 return fuzzyEqual( other, 1e-8 );
106 }
107
108 bool operator!=( const QgsAbstractGeometry &other ) const override
109 {
110 return !operator==( other );
111 }
112
113 ~QgsPolyhedralSurface() override;
114
115 QString geometryType() const override SIP_HOLDGIL;
116 int dimension() const final SIP_HOLDGIL;
117 QgsPolyhedralSurface *clone() const override SIP_FACTORY;
118 void clear() override;
119
120 bool fromWkb( QgsConstWkbPtr &wkb ) override;
121 bool fromWkt( const QString &wkt ) override;
122
123 bool isValid( QString &error SIP_OUT, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const override;
124
125 int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
126 QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
127 QString asWkt( int precision = 17 ) const override;
128 QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
129 QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
130 json asJsonObject( int precision = 17 ) const override SIP_SKIP;
131 QString asKml( int precision = 17 ) const override;
132 void normalize() override SIP_HOLDGIL;
133
134 //surface interface
135 double area() const override SIP_HOLDGIL;
136 double area3D() const override SIP_HOLDGIL;
137 double perimeter() const override SIP_HOLDGIL;
138 QgsAbstractGeometry *boundary() const override SIP_FACTORY;
139 QgsPolyhedralSurface *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0, bool removeRedundantPoints = false ) const override SIP_FACTORY;
140 QgsPolyhedralSurface *simplifyByDistance( double tolerance ) const override SIP_FACTORY;
141 bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
142
143 using QgsSurface::boundingBoxIntersects;
144 bool boundingBoxIntersects( const QgsBox3D &box3d ) const override SIP_HOLDGIL;
145
152 {
153 return mPatches.size();
154 }
155
156#ifndef SIP_RUN
157
163 const QgsPolygon *patchN( int i ) const
164 {
165 if ( i < 0 || i >= mPatches.size() )
166 {
167 return nullptr;
168 }
169 return mPatches.at( i );
170 }
171
178 {
179 if ( i < 0 || i >= mPatches.size() )
180 {
181 return nullptr;
182 }
183 return mPatches.at( i );
184 }
185#else
186
194 SIP_PYOBJECT patchN( int i ) SIP_HOLDGIL SIP_TYPEHINT( QgsPolygon );
195 % MethodCode
196 if ( a0 < 0 || a0 >= sipCpp->numPatches() )
197 {
198 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
199 sipIsErr = 1;
200 }
201 else
202 {
203 return sipConvertFromType( const_cast< QgsPolygon * >( sipCpp->patchN( a0 ) ), sipType_QgsPolygon, NULL );
204 }
205 % End
206#endif
207
211 virtual void setPatches( const QVector<QgsPolygon *> &patches SIP_TRANSFER );
212
216 virtual void addPatch( QgsPolygon *patch SIP_TRANSFER );
217
218#ifndef SIP_RUN
219
226 bool removePatch( int patchIndex );
227#else
228
236 bool removePatch( int ringIndex );
237 % MethodCode
238 if ( a0 < 0 || a0 >= sipCpp->numPatches() )
239 {
240 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
241 sipIsErr = 1;
242 }
243 else
244 {
245 return PyBool_FromLong( sipCpp->removePatch( a0 ) );
246 }
247 % End
248#endif
249
250 QPainterPath asQPainterPath() const override;
251 void draw( QPainter &p ) const override;
252 void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward, bool transformZ = false ) override SIP_THROW( QgsCsException );
253 void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
254
255 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
256 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
257 bool deleteVertex( QgsVertexId position ) override;
258
259 QgsCoordinateSequence coordinateSequence() const override;
260 int nCoordinates() const override;
261 int vertexNumberFromVertexId( QgsVertexId id ) const override;
262 bool isEmpty() const override SIP_HOLDGIL;
263 double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT, QgsVertexId &vertexAfter SIP_OUT, int *leftOf SIP_OUT = nullptr, double epsilon = 4 * std::numeric_limits<double>::epsilon() ) const override;
264
265 bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override;
266 void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
267 bool hasCurvedSegments() const final;
268
274 QgsAbstractGeometry *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
275
281 double vertexAngle( QgsVertexId vertex ) const override;
282
283 int vertexCount( int part = 0, int ring = 0 ) const override;
284 int ringCount( int part = 0 ) const override SIP_HOLDGIL;
285 int partCount() const override SIP_HOLDGIL;
286 QgsPoint vertexAt( QgsVertexId id ) const override;
287 double segmentLength( QgsVertexId startVertex ) const override;
288
289 bool addZValue( double zValue = 0 ) override;
290 bool addMValue( double mValue = 0 ) override;
291 bool dropZValue() override;
292 bool dropMValue() override;
293 void swapXy() override;
294
295 QgsMultiSurface *toCurveType() const override SIP_FACTORY;
296
297 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
298
303 QgsMultiPolygon *toMultiPolygon() const SIP_FACTORY;
304
305#ifndef SIP_RUN
306 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
307 void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
308
317 inline static const QgsPolyhedralSurface *cast( const QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
318 {
319 if ( !geom )
320 return nullptr;
321
322 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
323 if ( flatType == Qgis::WkbType::PolyhedralSurface
324 || flatType == Qgis::WkbType::TIN )
325 return static_cast<const QgsPolyhedralSurface *>( geom );
326
327 return nullptr;
328 }
329
338 inline static QgsPolyhedralSurface *cast( QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
339 {
340 if ( !geom )
341 return nullptr;
342
343 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
344 if ( flatType == Qgis::WkbType::PolyhedralSurface
345 || flatType == Qgis::WkbType::TIN )
346 return static_cast<QgsPolyhedralSurface *>( geom );
347
348 return nullptr;
349 }
350#endif
351
353
354#ifdef SIP_RUN
355 SIP_PYOBJECT __repr__();
356 % MethodCode
357 QString wkt = sipCpp->asWkt();
358 if ( wkt.length() > 1000 )
359 wkt = wkt.left( 1000 ) + u"..."_s;
360 QString str = u"<QgsPolyhedralSurface: %1>"_s.arg( wkt );
361 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
362 % End
363
367 int __len__() const;
368 % MethodCode
369 sipRes = sipCpp->numPatches();
370 % End
371
380 SIP_PYOBJECT __getitem__( int index ) SIP_TYPEHINT( QgsPolygon );
381 % MethodCode
382 const int count = sipCpp->numPatches();
383 if ( a0 < -count || a0 >= count )
384 {
385 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
386 sipIsErr = 1;
387 }
388 else if ( a0 >= 0 )
389 {
390 return sipConvertFromType( sipCpp->patchN( a0 ), sipType_QgsPolygon, NULL );
391 }
392 else
393 {
394 return sipConvertFromType( sipCpp->patchN( count + a0 ), sipType_QgsPolygon, NULL );
395 }
396 % End
397#endif
398
399 protected:
400
401 int childCount() const override;
402 QgsAbstractGeometry *childGeometry( int index ) const override;
403 int compareToSameClass( const QgsAbstractGeometry *other ) const override;
404 QgsBox3D calculateBoundingBox3D() const override;
405
406 QVector< QgsPolygon * > mPatches;
407};
408
409// clazy:excludeall=qstring-allocations
410
411#endif // QGSPOLYHEDRALSURFACE_H
Provides global constants and enumerations for use throughout the application.
Definition qgis.h:59
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:280
@ TIN
TIN.
Definition qgis.h:296
@ PolyhedralSurface
PolyhedralSurface.
Definition qgis.h:295
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition qgis.h:2729
@ Forward
Forward transform (from source to destination).
Definition qgis.h:2730
Abstract base class for all geometries.
virtual QgsBox3D calculateBoundingBox3D() const
Calculates the minimal 3D bounding box for the geometry.
virtual void draw(QPainter &p) const =0
Draws the geometry using the specified QPainter.
virtual int childCount() const
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
virtual void transformVertices(const std::function< QgsPoint(const QgsPoint &) > &transform)
Transforms the vertices from the geometry in place, applying the transform function to every vertex.
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
virtual QgsAbstractGeometry * createEmptyWithSameType() const =0
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
QgsAbstractGeometry & operator=(const QgsAbstractGeometry &geom)
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
virtual bool fuzzyEqual(const QgsAbstractGeometry &other, double epsilon=1e-8) const =0
Performs fuzzy comparison between this geometry and other using an epsilon.
virtual QPainterPath asQPainterPath() const =0
Returns the geometry represented as a QPainterPath.
virtual void transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection d=Qgis::TransformDirection::Forward, bool transformZ=false)=0
Transforms the geometry using a coordinate transform.
virtual void filterVertices(const std::function< bool(const QgsPoint &) > &filter)
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
virtual QgsAbstractGeometry * childGeometry(int index) const
Returns pointer to child geometry (for geometries with child geometries - i.e.
virtual bool operator==(const QgsAbstractGeometry &other) const =0
QgsAbstractGeometry()=default
virtual int compareToSameClass(const QgsAbstractGeometry *other) const =0
Compares to an other geometry of the same class, and returns a integer for sorting of the two geometr...
A 3-dimensional box composed of x, y, z coordinates.
Definition qgsbox3d.h:45
A const WKB pointer.
Definition qgswkbptr.h:139
Multi polygon geometry collection.
Polygon geometry type.
Definition qgspolygon.h:37
Polyhedral surface geometry type.
bool operator!=(const QgsAbstractGeometry &other) const override
QVector< QgsPolygon * > mPatches
int numPatches() const
Returns the number of patches contained with the polyhedral surface.
bool fuzzyDistanceEqual(const QgsAbstractGeometry &other, double epsilon=1e-8) const override
Performs fuzzy distance comparison between this geometry and other using an epsilon.
static QgsPolyhedralSurface * cast(QgsAbstractGeometry *geom)
Cast the geom to a QgsPolyhedralSurface.
static const QgsPolyhedralSurface * cast(const QgsAbstractGeometry *geom)
Cast the geom to a QgsPolyhedralSurface.
QgsPolygon * patchN(int i)
Retrieves a patch from the polyhedral surface.
bool fuzzyEqual(const QgsAbstractGeometry &other, double epsilon=1e-8) const override
Performs fuzzy comparison between this geometry and other using an epsilon.
bool operator==(const QgsAbstractGeometry &other) const override
const QgsPolygon * patchN(int i) const
Retrieves a patch from the polyhedral surface.
Surface geometry type.
Definition qgssurface.h:34
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
#define SIP_TYPEHINT(type)
Definition qgis_sip.h:240
#define SIP_SKIP
Definition qgis_sip.h:134
#define SIP_TRANSFER
Definition qgis_sip.h:36
#define SIP_OUT
Definition qgis_sip.h:58
#define SIP_HOLDGIL
Definition qgis_sip.h:179
#define SIP_FACTORY
Definition qgis_sip.h:84
#define SIP_THROW(name,...)
Definition qgis_sip.h:211
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsRingSequence > QgsCoordinateSequence
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition qgstracer.cpp:75