QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 "qgis_core.h"
22#include "qgis_sip.h"
23#include "qgssurface.h"
24#include "qgscurve.h"
25#include <memory>
26
27class QgsPolygon;
28
34class CORE_EXPORT QgsCurvePolygon: public QgsSurface
35{
36 public:
40
41#ifndef SIP_RUN
42 private:
43 bool fuzzyHelper( const QgsAbstractGeometry &other, double epsilon, bool useDistance ) const
44 {
45 const QgsCurvePolygon *otherPolygon = qgsgeometry_cast< const QgsCurvePolygon * >( &other );
46 if ( !otherPolygon )
47 return false;
48
49 //run cheap checks first
50 if ( mWkbType != otherPolygon->mWkbType )
51 return false;
52
53 if ( ( !mExteriorRing && otherPolygon->mExteriorRing ) || ( mExteriorRing && !otherPolygon->mExteriorRing ) )
54 return false;
55
56 if ( mInteriorRings.count() != otherPolygon->mInteriorRings.count() )
57 return false;
58
59 // compare rings
60 if ( mExteriorRing && otherPolygon->mExteriorRing )
61 {
62 if ( useDistance )
63 {
64 if ( !( *mExteriorRing ).fuzzyDistanceEqual( *otherPolygon->mExteriorRing, epsilon ) )
65 return false;
66 }
67 else
68 {
69 if ( !( *mExteriorRing ).fuzzyEqual( *otherPolygon->mExteriorRing, epsilon ) )
70 return false;
71 }
72 }
73
74 for ( int i = 0; i < mInteriorRings.count(); ++i )
75 {
76 if ( ( !mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) ) ||
77 ( mInteriorRings.at( i ) && !otherPolygon->mInteriorRings.at( i ) ) )
78 return false;
79
80 if ( useDistance )
81 {
82 if ( mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) &&
83 !( *mInteriorRings.at( i ) ).fuzzyDistanceEqual( *otherPolygon->mInteriorRings.at( i ), epsilon ) )
84 return false;
85 }
86 else
87 {
88 if ( mInteriorRings.at( i ) && otherPolygon->mInteriorRings.at( i ) &&
89 !( *mInteriorRings.at( i ) ).fuzzyEqual( *otherPolygon->mInteriorRings.at( i ), epsilon ) )
90 return false;
91 }
92 }
93
94 return true;
95 }
96#endif
97 public:
98 bool fuzzyEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
99 {
100 return fuzzyHelper( other, epsilon, false );
101 }
102 bool fuzzyDistanceEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
103 {
104 return fuzzyHelper( other, epsilon, true );
105 }
106 bool operator==( const QgsAbstractGeometry &other ) const override
107 {
108 return fuzzyEqual( other, 1e-8 );
109 }
110
111 bool operator!=( const QgsAbstractGeometry &other ) const override
112 {
113 return !operator==( other );
114 }
115
116 ~QgsCurvePolygon() override;
117
118 QString geometryType() const override SIP_HOLDGIL;
119 int dimension() const override SIP_HOLDGIL;
120 QgsCurvePolygon *clone() const override SIP_FACTORY;
121 void clear() override;
122
123 bool fromWkb( QgsConstWkbPtr &wkb ) override;
124 bool fromWkt( const QString &wkt ) override;
125
126 int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
127 QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
128 QString asWkt( int precision = 17 ) const override;
129 QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
130 QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
131 json asJsonObject( int precision = 17 ) const override SIP_SKIP;
132 QString asKml( int precision = 17 ) const override;
133 void normalize() final SIP_HOLDGIL;
134
135 //surface interface
136 double area() const override SIP_HOLDGIL;
137 double perimeter() const override SIP_HOLDGIL;
138 QgsPolygon *surfaceToPolygon() const override SIP_FACTORY;
139 QgsAbstractGeometry *boundary() const override SIP_FACTORY;
140 QgsCurvePolygon *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY;
141 bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
142 bool boundingBoxIntersects( const QgsBox3D &box3d ) const override SIP_HOLDGIL;
143
149 double roundness() const;
150
151 //curve polygon interface
152
158 int numInteriorRings() const SIP_HOLDGIL
159 {
160 return mInteriorRings.size();
161 }
162
169 {
170 return mExteriorRing.get();
171 }
172
182 {
183 return mExteriorRing.get();
184 }
185
186#ifndef SIP_RUN
187
194 const QgsCurve *interiorRing( int i ) const SIP_HOLDGIL
195 {
196 if ( i < 0 || i >= mInteriorRings.size() )
197 {
198 return nullptr;
199 }
200 return mInteriorRings.at( i );
201 }
202
212 {
213 if ( i < 0 || i >= mInteriorRings.size() )
214 {
215 return nullptr;
216 }
217 return mInteriorRings.at( i );
218 }
219#else
220
229 SIP_PYOBJECT interiorRing( int i ) SIP_HOLDGIL SIP_TYPEHINT( QgsCurve );
230 % MethodCode
231 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
232 {
233 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
234 sipIsErr = 1;
235 }
236 else
237 {
238 return sipConvertFromType( const_cast< QgsCurve * >( sipCpp->interiorRing( a0 ) ), sipType_QgsCurve, NULL );
239 }
240 % End
241#endif
242
249 virtual QgsPolygon *toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
250
259 virtual void setExteriorRing( QgsCurve *ring SIP_TRANSFER );
260
262 void setInteriorRings( const QVector<QgsCurve *> &rings SIP_TRANSFER );
264 virtual void addInteriorRing( QgsCurve *ring SIP_TRANSFER );
265
266#ifndef SIP_RUN
267
274 bool removeInteriorRing( int ringIndex );
275#else
276
286 bool removeInteriorRing( int i );
287 % MethodCode
288 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
289 {
290 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
291 sipIsErr = 1;
292 }
293 else
294 {
295 return PyBool_FromLong( sipCpp->removeInteriorRing( a0 ) );
296 }
297 % End
298#endif
299
306 void removeInteriorRings( double minimumAllowedArea = -1 );
307
314 void removeInvalidRings();
315
329 void forceRHR();
330
339 void forceClockwise();
340
349 void forceCounterClockwise();
350
351 QPainterPath asQPainterPath() const override;
352 void draw( QPainter &p ) const override;
354 void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
355
356 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
357 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
358 bool deleteVertex( QgsVertexId position ) override;
359
360 QgsCoordinateSequence coordinateSequence() const override;
361 int nCoordinates() const override;
362 int vertexNumberFromVertexId( QgsVertexId id ) const override;
363 bool isEmpty() const override SIP_HOLDGIL;
364 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;
365
366 bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override;
367 void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
368 bool hasCurvedSegments() const override;
369
375 QgsAbstractGeometry *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
376
382 double vertexAngle( QgsVertexId vertex ) const override;
383
384 int vertexCount( int part = 0, int ring = 0 ) const override;
385 int ringCount( int part = 0 ) const override SIP_HOLDGIL;
386 int partCount() const override SIP_HOLDGIL;
387 QgsPoint vertexAt( QgsVertexId id ) const override;
388 double segmentLength( QgsVertexId startVertex ) const override;
389
390 bool addZValue( double zValue = 0 ) override;
391 bool addMValue( double mValue = 0 ) override;
392 bool dropZValue() override;
393 bool dropMValue() override;
394 void swapXy() override;
395
396 QgsCurvePolygon *toCurveType() const override SIP_FACTORY;
397
398 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
399
400#ifndef SIP_RUN
401 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
402 void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
403
410 inline static const QgsCurvePolygon *cast( const QgsAbstractGeometry *geom )
411 {
412 if ( !geom )
413 return nullptr;
414
415 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
416 if ( flatType == Qgis::WkbType::CurvePolygon
417 || flatType == Qgis::WkbType::Polygon
418 || flatType == Qgis::WkbType::Triangle )
419 return static_cast<const QgsCurvePolygon *>( geom );
420 return nullptr;
421 }
422#endif
423
425
426#ifdef SIP_RUN
427 SIP_PYOBJECT __repr__();
428 % MethodCode
429 QString wkt = sipCpp->asWkt();
430 if ( wkt.length() > 1000 )
431 wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
432 QString str = QStringLiteral( "<QgsCurvePolygon: %1>" ).arg( wkt );
433 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
434 % End
435#endif
436
437 protected:
438
439 int childCount() const override;
440 QgsAbstractGeometry *childGeometry( int index ) const override;
441 int compareToSameClass( const QgsAbstractGeometry *other ) const final;
442
443 protected:
444
445 std::unique_ptr< QgsCurve > mExteriorRing;
446 QVector<QgsCurve *> mInteriorRings;
447
448 QgsBox3D calculateBoundingBox3D() const override;
449};
450
451// clazy:excludeall=qstring-allocations
452
453#endif // QGSCURVEPOLYGON_H
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
@ Polygon
Polygon.
@ Triangle
Triangle.
@ CurvePolygon
CurvePolygon.
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition: qgis.h:2191
@ Forward
Forward transform (from source to destination)
An abstract base class for classes which transform geometries by transforming input points to output ...
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
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:43
A const WKB pointer.
Definition: qgswkbptr.h:138
Class for doing transforms between two map coordinate systems.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:67
Curve polygon geometry type.
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.
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:35
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
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.
Definition: qgswkbtypes.h:628
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'. Negative values mean left ...
Definition: MathUtils.cpp:222
CORE_EXPORT std::unique_ptr< QgsPolygon > toPolygon(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns face as polygon geometry, caller is responsible for delete.
#define str(x)
Definition: qgis.cpp:38
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:232
#define SIP_SKIP
Definition: qgis_sip.h:126
#define SIP_TRANSFER
Definition: qgis_sip.h:36
#define SIP_OUT
Definition: qgis_sip.h:58
#define SIP_HOLDGIL
Definition: qgis_sip.h:171
#define SIP_FACTORY
Definition: qgis_sip.h:76
#define SIP_THROW(name,...)
Definition: qgis_sip.h:203
QVector< QgsRingSequence > QgsCoordinateSequence
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition: qgstracer.cpp:69
int precision
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30