QGIS API Documentation 3.39.0-Master (47f7b3a4989)
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 "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, bool removeRedundantPoints = false ) const override SIP_FACTORY;
141 QgsCurvePolygon *simplifyByDistance( double tolerance ) const override SIP_FACTORY;
142 bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
143 bool boundingBoxIntersects( const QgsBox3D &box3d ) const override SIP_HOLDGIL;
144
150 double roundness() const;
151
152 //curve polygon interface
153
159 int numInteriorRings() const SIP_HOLDGIL
160 {
161 return mInteriorRings.size();
162 }
163
170 {
171 return mExteriorRing.get();
172 }
173
183 {
184 return mExteriorRing.get();
185 }
186
187#ifndef SIP_RUN
188
195 const QgsCurve *interiorRing( int i ) const SIP_HOLDGIL
196 {
197 if ( i < 0 || i >= mInteriorRings.size() )
198 {
199 return nullptr;
200 }
201 return mInteriorRings.at( i );
202 }
203
213 {
214 if ( i < 0 || i >= mInteriorRings.size() )
215 {
216 return nullptr;
217 }
218 return mInteriorRings.at( i );
219 }
220#else
221
230 SIP_PYOBJECT interiorRing( int i ) SIP_HOLDGIL SIP_TYPEHINT( QgsCurve );
231 % MethodCode
232 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
233 {
234 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
235 sipIsErr = 1;
236 }
237 else
238 {
239 return sipConvertFromType( const_cast< QgsCurve * >( sipCpp->interiorRing( a0 ) ), sipType_QgsCurve, NULL );
240 }
241 % End
242#endif
243
250 virtual QgsPolygon *toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
251
260 virtual void setExteriorRing( QgsCurve *ring SIP_TRANSFER );
261
263 void setInteriorRings( const QVector<QgsCurve *> &rings SIP_TRANSFER );
265 virtual void addInteriorRing( QgsCurve *ring SIP_TRANSFER );
266
267#ifndef SIP_RUN
268
275 bool removeInteriorRing( int ringIndex );
276#else
277
287 bool removeInteriorRing( int i );
288 % MethodCode
289 if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
290 {
291 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
292 sipIsErr = 1;
293 }
294 else
295 {
296 return PyBool_FromLong( sipCpp->removeInteriorRing( a0 ) );
297 }
298 % End
299#endif
300
307 void removeInteriorRings( double minimumAllowedArea = -1 );
308
315 void removeInvalidRings();
316
330 void forceRHR();
331
340 void forceClockwise();
341
350 void forceCounterClockwise();
351
352 QPainterPath asQPainterPath() const override;
353 void draw( QPainter &p ) const override;
355 void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
356
357 bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
358 bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
359 bool deleteVertex( QgsVertexId position ) override;
360
361 QgsCoordinateSequence coordinateSequence() const override;
362 int nCoordinates() const override;
363 int vertexNumberFromVertexId( QgsVertexId id ) const override;
364 bool isEmpty() const override SIP_HOLDGIL;
365 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;
366
367 bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override;
368 void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
369 bool hasCurvedSegments() const override;
370
376 QgsAbstractGeometry *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
377
383 double vertexAngle( QgsVertexId vertex ) const override;
384
385 int vertexCount( int part = 0, int ring = 0 ) const override;
386 int ringCount( int part = 0 ) const override SIP_HOLDGIL;
387 int partCount() const override SIP_HOLDGIL;
388 QgsPoint vertexAt( QgsVertexId id ) const override;
389 double segmentLength( QgsVertexId startVertex ) const override;
390
391 bool addZValue( double zValue = 0 ) override;
392 bool addMValue( double mValue = 0 ) override;
393 bool dropZValue() override;
394 bool dropMValue() override;
395 void swapXy() override;
396
397 QgsCurvePolygon *toCurveType() const override SIP_FACTORY;
398
399 bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
400
401#ifndef SIP_RUN
402 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
403 void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
404
411 inline static const QgsCurvePolygon *cast( const QgsAbstractGeometry *geom )
412 {
413 if ( !geom )
414 return nullptr;
415
416 const Qgis::WkbType flatType = QgsWkbTypes::flatType( geom->wkbType() );
417 if ( flatType == Qgis::WkbType::CurvePolygon
418 || flatType == Qgis::WkbType::Polygon
419 || flatType == Qgis::WkbType::Triangle )
420 return static_cast<const QgsCurvePolygon *>( geom );
421 return nullptr;
422 }
423#endif
424
426
427#ifdef SIP_RUN
428 SIP_PYOBJECT __repr__();
429 % MethodCode
430 QString wkt = sipCpp->asWkt();
431 if ( wkt.length() > 1000 )
432 wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
433 QString str = QStringLiteral( "<QgsCurvePolygon: %1>" ).arg( wkt );
434 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
435 % End
436#endif
437
438 protected:
439
440 int childCount() const override;
441 QgsAbstractGeometry *childGeometry( int index ) const override;
442 int compareToSameClass( const QgsAbstractGeometry *other ) const final;
443
444 protected:
445
446 std::unique_ptr< QgsCurve > mExteriorRing;
447 QVector<QgsCurve *> mInteriorRings;
448
449 QgsBox3D calculateBoundingBox3D() const override;
450};
451
452// clazy:excludeall=qstring-allocations
453
454#endif // QGSCURVEPOLYGON_H
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:201
@ Polygon
Polygon.
@ Triangle
Triangle.
@ CurvePolygon
CurvePolygon.
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition qgis.h:2289
@ 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.
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.
#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