QGIS API Documentation 3.99.0-Master (2fe06baccd8)
Loading...
Searching...
No Matches
qgscurvepolygon.h
Go to the documentation of this file.
1/***************************************************************************
2 qgscurvepolygon.h
3 -------------------
4 begin : September 2014
5 copyright : (C) 2014 by Marco Hugentobler
6 email : marco at sourcepole dot ch
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 QGSCURVEPOLYGON_H
19#define QGSCURVEPOLYGON_H
20
21#include <memory>
22
23#include "qgis_core.h"
24#include "qgis_sip.h"
25#include "qgscurve.h"
26#include "qgssurface.h"
27
28class QgsPolygon;
29
35class CORE_EXPORT QgsCurvePolygon: public QgsSurface
36{
37 public:
41
42#ifndef SIP_RUN
43 private:
44 bool fuzzyHelper( const QgsAbstractGeometry &other, double epsilon, bool useDistance ) const
45 {
47 if ( !otherPolygon )
48 return false;
49
50 //run cheap checks first
51 if ( mWkbType != otherPolygon->mWkbType )
52 return false;
53
54 if ( ( !mExteriorRing && otherPolygon->mExteriorRing ) || ( mExteriorRing && !otherPolygon->mExteriorRing ) )
55 return false;
56
57 if ( mInteriorRings.count() != otherPolygon->mInteriorRings.count() )
58 return false;
59
60 // compare rings
61 if ( mExteriorRing && otherPolygon->mExteriorRing )
62 {
63 if ( useDistance )
64 {
65 if ( !( *mExteriorRing ).fuzzyDistanceEqual( *otherPolygon->mExteriorRing, epsilon ) )
66 return false;
67 }
68 else
69 {
70 if ( !( *mExteriorRing ).fuzzyEqual( *otherPolygon->mExteriorRing, epsilon ) )
71 return false;
72 }
73 }
74
75 for ( int i = 0; i < mInteriorRings.count(); ++i )
76 {
77 if ( ( !mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) ) ||
78 ( mInteriorRings.at( i ) && !otherPolygon->mInteriorRings.at( i ) ) )
79 return false;
80
81 if ( useDistance )
82 {
83 if ( mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) &&
84 !( *mInteriorRings.at( i ) ).fuzzyDistanceEqual( *otherPolygon->mInteriorRings.at( i ), epsilon ) )
85 return false;
86 }
87 else
88 {
89 if ( mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) &&
90 !( *mInteriorRings.at( i ) ).fuzzyEqual( *otherPolygon->mInteriorRings.at( i ), epsilon ) )
91 return false;
92 }
93 }
94
95 return true;
96 }
97#endif
98 public:
99 bool fuzzyEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
100 {
101 return fuzzyHelper( other, epsilon, false );
102 }
103 bool fuzzyDistanceEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
104 {
105 return fuzzyHelper( other, epsilon, true );
106 }
107 bool operator==( const QgsAbstractGeometry &other ) const override
108 {
109 return fuzzyEqual( other, 1e-8 );
110 }
111
112 bool operator!=( const QgsAbstractGeometry &other ) const override
113 {
114 return !operator==( other );
115 }
116
117 ~QgsCurvePolygon() override;
118
119 QString geometryType() const override SIP_HOLDGIL;
120 int dimension() const override SIP_HOLDGIL;
121 QgsCurvePolygon *clone() const override SIP_FACTORY;
122 void clear() override;
123
124 bool fromWkb( QgsConstWkbPtr &wkb ) override;
125 bool fromWkt( const QString &wkt ) override;
126
127 int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
128 QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
129 QString asWkt( int precision = 17 ) const override;
130 QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
131 QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
132 json asJsonObject( int precision = 17 ) const override SIP_SKIP;
133 QString asKml( int precision = 17 ) const override;
134 void normalize() final SIP_HOLDGIL;
135
140 virtual QgsPolygon *surfaceToPolygon() const SIP_FACTORY;
141
142 //surface interface
143 double area() const override SIP_HOLDGIL;
144 double perimeter() const override SIP_HOLDGIL;
145 QgsAbstractGeometry *boundary() const override SIP_FACTORY;
146 QgsCurvePolygon *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0, bool removeRedundantPoints = false ) const override SIP_FACTORY;
147 QgsCurvePolygon *simplifyByDistance( double tolerance ) const override SIP_FACTORY;
148 bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
149 bool boundingBoxIntersects( const QgsBox3D &box3d ) const override SIP_HOLDGIL;
150
156 double roundness() const;
157
158 //curve polygon interface
159
166 {
167 return mInteriorRings.size();
168 }
169
176 {
177 return mExteriorRing.get();
178 }
179
189 {
190 return mExteriorRing.get();
191 }
192
193#ifndef SIP_RUN
194
201 const QgsCurve *interiorRing( int i ) const SIP_HOLDGIL
202 {
203 if ( i < 0 || i >= mInteriorRings.size() )
204 {
205 return nullptr;
206 }
207 return mInteriorRings.at( i );
208 }
209
219 {
220 if ( i < 0 || i >= mInteriorRings.size() )
221 {
222 return nullptr;
223 }
224 return mInteriorRings.at( i );
225 }
226#else
227
236 SIP_PYOBJECT interiorRing( int i ) SIP_HOLDGIL SIP_TYPEHINT( QgsCurve );
237 % MethodCode
238 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
239 {
240 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
241 sipIsErr = 1;
242 }
243 else
244 {
245 return sipConvertFromType( const_cast< QgsCurve * >( sipCpp->interiorRing( a0 ) ), sipType_QgsCurve, NULL );
246 }
247 % End
248#endif
249
256 virtual QgsPolygon *toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
257
266 virtual void setExteriorRing( QgsCurve *ring SIP_TRANSFER );
267
269 void setInteriorRings( const QVector<QgsCurve *> &rings SIP_TRANSFER );
271 virtual void addInteriorRing( QgsCurve *ring SIP_TRANSFER );
272
273#ifndef SIP_RUN
274
281 bool removeInteriorRing( int ringIndex );
282#else
283
293 bool removeInteriorRing( int i );
294 % MethodCode
295 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
296 {
297 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
298 sipIsErr = 1;
299 }
300 else
301 {
302 return PyBool_FromLong( sipCpp->removeInteriorRing( a0 ) );
303 }
304 % End
305#endif
306
313 void removeInteriorRings( double minimumAllowedArea = -1 );
314
321 void removeInvalidRings();
322
336 void forceRHR();
337
346 void forceClockwise();
347
356 void forceCounterClockwise();
357
358 QPainterPath asQPainterPath() const override;
359 void draw( QPainter &p ) const override;
360 void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward, bool transformZ = false ) override SIP_THROW( QgsCsException );
361 void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
362
363 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
364 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
365 bool deleteVertex( QgsVertexId position ) override;
366
367 QgsCoordinateSequence coordinateSequence() const override;
368 int nCoordinates() const override;
369 int vertexNumberFromVertexId( QgsVertexId id ) const override;
370 bool isEmpty() const override SIP_HOLDGIL;
371 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;
372
373 bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override;
374 void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
375 bool hasCurvedSegments() const override;
376
382 QgsAbstractGeometry *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
383
389 double vertexAngle( QgsVertexId vertex ) const override;
390
391 int vertexCount( int part = 0, int ring = 0 ) const override;
392 int ringCount( int part = 0 ) const override SIP_HOLDGIL;
393 int partCount() const override SIP_HOLDGIL;
394 QgsPoint vertexAt( QgsVertexId id ) const override;
395 double segmentLength( QgsVertexId startVertex ) const override;
396
397 bool addZValue( double zValue = 0 ) override;
398 bool addMValue( double mValue = 0 ) override;
399 bool dropZValue() override;
400 bool dropMValue() override;
401 void swapXy() override;
402
403 QgsCurvePolygon *toCurveType() const override SIP_FACTORY;
404
405 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
406
407#ifndef SIP_RUN
408 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
409 void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
410
419 inline static const QgsCurvePolygon *cast( const QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
420 {
421 if ( !geom )
422 return nullptr;
423
424 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
425 if ( flatType == Qgis::WkbType::CurvePolygon
426 || flatType == Qgis::WkbType::Polygon
427 || flatType == Qgis::WkbType::Triangle )
428 return static_cast<const QgsCurvePolygon *>( geom );
429 return nullptr;
430 }
431
440 inline static QgsCurvePolygon *cast( QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
441 {
442 if ( !geom )
443 return nullptr;
444
445 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
446 if ( flatType == Qgis::WkbType::CurvePolygon
447 || flatType == Qgis::WkbType::Polygon
448 || flatType == Qgis::WkbType::Triangle )
449 return static_cast<QgsCurvePolygon *>( geom );
450 return nullptr;
451 }
452#endif
453
455
456#ifdef SIP_RUN
457 SIP_PYOBJECT __repr__();
458 % MethodCode
459 QString wkt = sipCpp->asWkt();
460 if ( wkt.length() > 1000 )
461 wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
462 QString str = QStringLiteral( "<QgsCurvePolygon: %1>" ).arg( wkt );
463 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
464 % End
465#endif
466
467 protected:
468
469 int childCount() const override;
470 QgsAbstractGeometry *childGeometry( int index ) const override;
471 int compareToSameClass( const QgsAbstractGeometry *other ) const final;
472
473 protected:
474
475 std::unique_ptr< QgsCurve > mExteriorRing;
476 QVector<QgsCurve *> mInteriorRings;
477
478 QgsBox3D calculateBoundingBox3D() const override;
479};
480
481// clazy:excludeall=qstring-allocations
482
483#endif // QGSCURVEPOLYGON_H
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:277
@ Polygon
Polygon.
Definition qgis.h:281
@ Triangle
Triangle.
Definition qgis.h:282
@ CurvePolygon
CurvePolygon.
Definition qgis.h:289
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition qgis.h:2671
@ Forward
Forward transform (from source to destination).
Definition qgis.h:2672
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:42
A const WKB pointer.
Definition qgswkbptr.h:139
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
QVector< QgsCurve * > mInteriorRings
bool operator!=(const QgsAbstractGeometry &other) const override
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
QgsCurve * interiorRing(int i)
Retrieves an interior ring from the curve polygon.
static const QgsCurvePolygon * cast(const QgsAbstractGeometry *geom)
Cast the geom to a QgsCurvePolygon.
bool fuzzyEqual(const QgsAbstractGeometry &other, double epsilon=1e-8) const override
Performs fuzzy comparison between this geometry and other using an epsilon.
bool fuzzyDistanceEqual(const QgsAbstractGeometry &other, double epsilon=1e-8) const override
Performs fuzzy distance comparison between this geometry and other using an epsilon.
static QgsCurvePolygon * cast(QgsAbstractGeometry *geom)
Cast the geom to a QgsCurvePolygon.
QgsCurve * exteriorRing()
Returns a non-const pointer to the curve polygon's exterior ring.
bool operator==(const QgsAbstractGeometry &other) const override
std::unique_ptr< QgsCurve > mExteriorRing
Abstract base class for curved geometry type.
Definition qgscurve.h:36
Polygon geometry type.
Definition qgspolygon.h:33
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:72