QGIS API Documentation 4.1.0-Master (60fea48833c)
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 <limits>
22#include <memory>
23
24#include "qgis_core.h"
25#include "qgis_sip.h"
26#include "qgscurve.h"
27#include "qgssurface.h"
28
29#include <QString>
30
31using namespace Qt::StringLiterals;
32
33class QgsPolygon;
34
40class CORE_EXPORT QgsCurvePolygon : public QgsSurface
41{
42 public:
46
47#ifndef SIP_RUN
48 private:
49 bool fuzzyHelper( const QgsAbstractGeometry &other, double epsilon, bool useDistance ) const
50 {
52 if ( !otherPolygon )
53 return false;
54
55 //run cheap checks first
56 if ( mWkbType != otherPolygon->mWkbType )
57 return false;
58
59 if ( ( !mExteriorRing && otherPolygon->mExteriorRing ) || ( mExteriorRing && !otherPolygon->mExteriorRing ) )
60 return false;
61
62 if ( mInteriorRings.count() != otherPolygon->mInteriorRings.count() )
63 return false;
64
65 // compare rings
66 if ( mExteriorRing && otherPolygon->mExteriorRing )
67 {
68 if ( useDistance )
69 {
70 if ( !( *mExteriorRing ).fuzzyDistanceEqual( *otherPolygon->mExteriorRing, epsilon ) )
71 return false;
72 }
73 else
74 {
75 if ( !( *mExteriorRing ).fuzzyEqual( *otherPolygon->mExteriorRing, epsilon ) )
76 return false;
77 }
78 }
79
80 for ( int i = 0; i < mInteriorRings.count(); ++i )
81 {
82 if ( ( !mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) ) || ( mInteriorRings.at( i ) && !otherPolygon->mInteriorRings.at( i ) ) )
83 return false;
84
85 if ( useDistance )
86 {
87 if ( mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) && !( *mInteriorRings.at( i ) ).fuzzyDistanceEqual( *otherPolygon->mInteriorRings.at( i ), epsilon ) )
88 return false;
89 }
90 else
91 {
92 if ( mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) && !( *mInteriorRings.at( i ) ).fuzzyEqual( *otherPolygon->mInteriorRings.at( i ), epsilon ) )
93 return false;
94 }
95 }
96
97 return true;
98 }
99#endif
100 public:
101 // clang-format off
102 bool fuzzyEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
103 // clang-format on
104 {
105 return fuzzyHelper( other, epsilon, false );
106 }
107 bool fuzzyDistanceEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
108 {
109 return fuzzyHelper( other, epsilon, true );
110 }
111 bool operator==( const QgsAbstractGeometry &other ) const override
112 {
113 return fuzzyEqual( other, 1e-8 );
114 }
115
116 bool operator!=( const QgsAbstractGeometry &other ) const override
117 {
118 return !operator==( other );
119 }
120
121 ~QgsCurvePolygon() override;
122
123 QString geometryType() const override SIP_HOLDGIL;
124 int dimension() const override SIP_HOLDGIL;
125 QgsCurvePolygon *clone() const override SIP_FACTORY;
126 void clear() override;
127
128 bool fromWkb( QgsConstWkbPtr &wkb ) override;
129 bool fromWkt( const QString &wkt ) override;
130
131 int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
132 QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
133 QString asWkt( int precision = 17 ) const override;
134 QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
135 QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
136 json asJsonObject( int precision = 17 ) const override SIP_SKIP;
137 QString asKml( int precision = 17 ) const override;
138 void normalize() final SIP_HOLDGIL;
139
144 virtual QgsPolygon *surfaceToPolygon() const SIP_FACTORY;
145
146 //surface interface
147 double area() const override SIP_HOLDGIL;
148 double area3D() const override SIP_HOLDGIL;
149 double perimeter() const override SIP_HOLDGIL;
150 QgsAbstractGeometry *boundary() const override SIP_FACTORY;
151 QgsCurvePolygon *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0, bool removeRedundantPoints = false ) const override SIP_FACTORY;
152 QgsCurvePolygon *simplifyByDistance( double tolerance ) const override SIP_FACTORY;
153 bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
154
155 bool boundingBoxIntersects( const QgsBox3D &box3d ) const override SIP_HOLDGIL;
156 bool boundingBoxIntersects( const QgsRectangle &box ) const override SIP_HOLDGIL;
157
163 double roundness() const;
164
165 //curve polygon interface
166
173 {
174 return mInteriorRings.size();
175 }
176
183 {
184 return mExteriorRing.get();
185 }
186
196 {
197 return mExteriorRing.get();
198 }
199
200#ifndef SIP_RUN
201
208 const QgsCurve *interiorRing( int i ) const SIP_HOLDGIL
209 {
210 if ( i < 0 || i >= mInteriorRings.size() )
211 {
212 return nullptr;
213 }
214 return mInteriorRings.at( i );
215 }
216
226 {
227 if ( i < 0 || i >= mInteriorRings.size() )
228 {
229 return nullptr;
230 }
231 return mInteriorRings.at( i );
232 }
233#else
234// clang-format off
235
244 SIP_PYOBJECT interiorRing( int i ) SIP_HOLDGIL SIP_TYPEHINT( QgsCurve );
245 % MethodCode
246 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
247 {
248 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
249 sipIsErr = 1;
250 }
251 else
252 {
253 return sipConvertFromType( const_cast< QgsCurve * >( sipCpp->interiorRing( a0 ) ), sipType_QgsCurve, NULL );
254 }
255 % End
256// clang-format on
257#endif
258
265 virtual QgsPolygon *toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
266
275 virtual void setExteriorRing( QgsCurve *ring SIP_TRANSFER );
276
278 void setInteriorRings( const QVector<QgsCurve *> &rings SIP_TRANSFER );
280 virtual void addInteriorRing( QgsCurve *ring SIP_TRANSFER );
281
282#ifndef SIP_RUN
283
290 bool removeInteriorRing( int ringIndex );
291#else
292// clang-format off
293
303 bool removeInteriorRing( int i );
304 % MethodCode
305 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
306 {
307 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
308 sipIsErr = 1;
309 }
310 else
311 {
312 return PyBool_FromLong( sipCpp->removeInteriorRing( a0 ) );
313 }
314 % End
315// clang-format on
316#endif
317
324 void removeInteriorRings( double minimumAllowedArea = -1 );
325
332 void removeInvalidRings();
333
347 void forceRHR();
348
357 void forceClockwise();
358
367 void forceCounterClockwise();
368
369 QPainterPath asQPainterPath() const override;
370 void draw( QPainter &p ) const override;
371 void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward, bool transformZ = false ) override SIP_THROW( QgsCsException );
372 void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
373
374 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
375 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
376 bool deleteVertex( QgsVertexId position ) override;
377
378 QgsCoordinateSequence coordinateSequence() const override;
379 int nCoordinates() const override;
380 int vertexNumberFromVertexId( QgsVertexId id ) const override;
381 bool isEmpty() const override SIP_HOLDGIL;
382 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;
383
384 bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override;
385 void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
386 bool hasCurvedSegments() const override;
387
393 QgsAbstractGeometry *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
394
400 double vertexAngle( QgsVertexId vertex ) const override;
401
402 int vertexCount( int part = 0, int ring = 0 ) const override;
403 int ringCount( int part = 0 ) const override SIP_HOLDGIL;
404 int partCount() const override SIP_HOLDGIL;
405 QgsPoint vertexAt( QgsVertexId id ) const override;
406 double segmentLength( QgsVertexId startVertex ) const override;
407
408 bool addZValue( double zValue = 0 ) override;
409 bool addMValue( double mValue = 0 ) override;
410 bool dropZValue() override;
411 bool dropMValue() override;
412 void swapXy() override;
413
414 QgsCurvePolygon *toCurveType() const override SIP_FACTORY;
415
416 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
417
418#ifndef SIP_RUN
419 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
420 void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
421
430 inline static const QgsCurvePolygon *cast( const QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
431 {
432 if ( !geom )
433 return nullptr;
434
435 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
436 if ( flatType == Qgis::WkbType::CurvePolygon
437 || flatType == Qgis::WkbType::Polygon
438 || flatType == Qgis::WkbType::Triangle )
439 return static_cast<const QgsCurvePolygon *>( geom );
440 return nullptr;
441 }
442
451 inline static QgsCurvePolygon *cast( QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
452 {
453 if ( !geom )
454 return nullptr;
455
456 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
457 if ( flatType == Qgis::WkbType::CurvePolygon
458 || flatType == Qgis::WkbType::Polygon
459 || flatType == Qgis::WkbType::Triangle )
460 return static_cast<QgsCurvePolygon *>( geom );
461 return nullptr;
462 }
463#endif
464
466
467#ifdef SIP_RUN
468// clang-format off
469 SIP_PYOBJECT __repr__();
470 % MethodCode
471 QString wkt = sipCpp->asWkt();
472 if ( wkt.length() > 1000 )
473 wkt = wkt.left( 1000 ) + u"..."_s;
474 QString str = u"<QgsCurvePolygon: %1>"_s.arg( wkt );
475 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
476 % End
477// clang-format on
478#endif
479
480 protected:
481
482 int childCount() const override;
483 QgsAbstractGeometry *childGeometry( int index ) const override;
484 int compareToSameClass( const QgsAbstractGeometry *other ) const final;
485
486 protected:
487
488 std::unique_ptr< QgsCurve > mExteriorRing;
489 QVector<QgsCurve *> mInteriorRings;
490
491 QgsBox3D calculateBoundingBox3D() const override;
492};
493
494// clazy:excludeall=qstring-allocations
495
496#endif // QGSCURVEPOLYGON_H
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:294
@ Polygon
Polygon.
Definition qgis.h:298
@ Triangle
Triangle.
Definition qgis.h:299
@ CurvePolygon
CurvePolygon.
Definition qgis.h:306
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition qgis.h:2764
@ Forward
Forward transform (from source to destination).
Definition qgis.h:2765
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:211
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:37
A rectangle specified with double values.
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:239
#define SIP_SKIP
Definition qgis_sip.h:133
#define SIP_TRANSFER
Definition qgis_sip.h:35
#define SIP_OUT
Definition qgis_sip.h:57
#define SIP_HOLDGIL
Definition qgis_sip.h:178
#define SIP_FACTORY
Definition qgis_sip.h:83
#define SIP_THROW(name,...)
Definition qgis_sip.h:210
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QVector< QgsRingSequence > QgsCoordinateSequence
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition qgstracer.cpp:72