QGIS API Documentation  3.37.0-Master (a5b4d9743e8)
qgsgeometrycollection.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometrycollection.h
3  -------------------------------------------------------------------
4 Date : 28 Oct 2014
5 Copyright : (C) 2014 by Marco Hugentobler
6 email : marco.hugentobler at sourcepole dot com
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #ifndef QGSGEOMETRYCOLLECTION_H
17 #define QGSGEOMETRYCOLLECTION_H
18 
19 #include <QVector>
20 
21 
22 #include "qgis_core.h"
23 #include "qgis_sip.h"
24 #include "qgsabstractgeometry.h"
25 #include "qgsrectangle.h"
26 #include "qgsbox3d.h"
27 
28 class QgsPoint;
29 
30 
36 class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
37 {
38  public:
39 
40 
45 
48  ~QgsGeometryCollection() override;
49 
50  bool operator==( const QgsAbstractGeometry &other ) const override
51  {
52  return fuzzyEqual( other, 1e-8 );
53  }
54 
55  bool operator!=( const QgsAbstractGeometry &other ) const override
56  {
57  return !operator==( other );
58  }
59 
60 #ifndef SIP_RUN
61  private:
62  bool fuzzyHelper( const QgsAbstractGeometry &other, double epsilon, bool useDistance ) const
63  {
64  const QgsGeometryCollection *otherCollection = qgsgeometry_cast< const QgsGeometryCollection * >( &other );
65  if ( !otherCollection )
66  return false;
67 
68  if ( mWkbType != otherCollection->mWkbType )
69  return false;
70 
71  if ( mGeometries.count() != otherCollection->mGeometries.count() )
72  return false;
73 
74  for ( int i = 0; i < mGeometries.count(); ++i )
75  {
76  QgsAbstractGeometry *g1 = mGeometries.at( i );
77  QgsAbstractGeometry *g2 = otherCollection->mGeometries.at( i );
78 
79  // Quick check if the geometries are exactly the same
80  if ( g1 != g2 )
81  {
82  if ( !g1 || !g2 )
83  return false;
84 
85  // Slower check, compare the contents of the geometries
86  if ( useDistance )
87  {
88  if ( !( *g1 ).fuzzyDistanceEqual( *g2, epsilon ) )
89  {
90  return false;
91  }
92  }
93  else
94  {
95  if ( !( *g1 ).fuzzyEqual( *g2, epsilon ) )
96  {
97  return false;;
98  }
99  }
100  }
101  }
102  return true;
103  }
104 #endif
105  public:
106  bool fuzzyEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
107  {
108  return fuzzyHelper( other, epsilon, false );
109  }
110  bool fuzzyDistanceEqual( const QgsAbstractGeometry &other, double epsilon = 1e-8 ) const override SIP_HOLDGIL
111  {
112  return fuzzyHelper( other, epsilon, true );
113  }
114 
115  QgsGeometryCollection *clone() const override SIP_FACTORY;
116 
120  int numGeometries() const SIP_HOLDGIL
121  {
122  return mGeometries.size();
123  }
124 
125 #ifdef SIP_RUN
126 
130  int __len__() const;
131  % MethodCode
132  sipRes = sipCpp->numGeometries();
133  % End
134 
136  int __bool__() const;
137  % MethodCode
138  sipRes = true;
139  % End
140 #endif
141 
142 
148  const QgsAbstractGeometry *geometryN( int n ) const SIP_SKIP
149  {
150  return mGeometries.value( n );
151  }
152 
153 #ifndef SIP_RUN
154 
159  QgsAbstractGeometry *geometryN( int n ) SIP_HOLDGIL;
160 #else
161 
167  SIP_PYOBJECT geometryN( int n ) SIP_TYPEHINT( QgsAbstractGeometry );
168  % MethodCode
169  if ( a0 < 0 || a0 >= sipCpp->numGeometries() )
170  {
171  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
172  sipIsErr = 1;
173  }
174  else
175  {
176  return sipConvertFromType( sipCpp->geometryN( a0 ), sipType_QgsAbstractGeometry, NULL );
177  }
178  % End
179 #endif
180 
181 
182  //methods inherited from QgsAbstractGeometry
183  bool isEmpty() const override SIP_HOLDGIL;
184  int dimension() const override SIP_HOLDGIL;
185  QString geometryType() const override SIP_HOLDGIL;
186  void clear() override;
187  QgsGeometryCollection *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const override SIP_FACTORY;
188  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
189  QgsAbstractGeometry *boundary() const override SIP_FACTORY;
190  void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const override;
191  int vertexNumberFromVertexId( QgsVertexId id ) const override;
192  bool boundingBoxIntersects( const QgsBox3D &box3d ) const override SIP_HOLDGIL;
193 
202  void reserve( int size ) SIP_HOLDGIL;
203 
205  virtual bool addGeometry( QgsAbstractGeometry *g SIP_TRANSFER );
206 
212  virtual bool insertGeometry( QgsAbstractGeometry *g SIP_TRANSFER, int index );
213 
214 #ifndef SIP_RUN
215 
221  virtual bool removeGeometry( int nr );
222 #else
223 
230  virtual bool removeGeometry( int nr );
231  % MethodCode
232  const int count = sipCpp->numGeometries();
233  if ( a0 < 0 || a0 >= count )
234  {
235  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
236  sipIsErr = 1;
237  }
238  else
239  {
240  return PyBool_FromLong( sipCpp->removeGeometry( a0 ) );
241  }
242  % End
243 #endif
244 
245  void normalize() final SIP_HOLDGIL;
246  void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward, bool transformZ = false ) override SIP_THROW( QgsCsException );
247  void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 ) override;
248 
249  void draw( QPainter &p ) const override;
250  QPainterPath asQPainterPath() const override;
251 
252  bool fromWkb( QgsConstWkbPtr &wkb ) override;
253  bool fromWkt( const QString &wkt ) override;
254 
255  int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
256  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const override;
257  QString asWkt( int precision = 17 ) const override;
258  QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
259  QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
260  json asJsonObject( int precision = 17 ) const override SIP_SKIP;
261  QString asKml( int precision = 17 ) const override;
262 
263  QgsBox3D boundingBox3D() const override;
264 
265  QgsCoordinateSequence coordinateSequence() const override;
266  int nCoordinates() const override;
267 
268  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;
269  bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const override;
270 
271  //low-level editing
272  bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) override;
273  bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) override;
274  bool deleteVertex( QgsVertexId position ) override;
275 
276  double length() const override SIP_HOLDGIL;
277  double area() const override SIP_HOLDGIL;
278  double perimeter() const override SIP_HOLDGIL;
279 
280  bool hasCurvedSegments() const override SIP_HOLDGIL;
281 
287  QgsAbstractGeometry *segmentize( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const override SIP_FACTORY;
288 
289  double vertexAngle( QgsVertexId vertex ) const override;
290  double segmentLength( QgsVertexId startVertex ) const override;
291  int vertexCount( int part = 0, int ring = 0 ) const override;
292  int ringCount( int part = 0 ) const override;
293  int partCount() const override;
294  QgsPoint vertexAt( QgsVertexId id ) const override;
295  bool isValid( QString &error SIP_OUT, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const override;
296 
297  bool addZValue( double zValue = 0 ) override;
298  bool addMValue( double mValue = 0 ) override;
299  bool dropZValue() override;
300  bool dropMValue() override;
301  void swapXy() override;
302  QgsGeometryCollection *toCurveType() const override SIP_FACTORY;
303  const QgsAbstractGeometry *simplifiedTypeRef() const override SIP_HOLDGIL;
304 
305  bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) override;
306 
307 #ifndef SIP_RUN
308  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
309  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) override;
310 
317  inline static const QgsGeometryCollection *cast( const QgsAbstractGeometry *geom )
318  {
319  if ( geom && QgsWkbTypes::isMultiType( geom->wkbType() ) )
320  return static_cast<const QgsGeometryCollection *>( geom );
321  return nullptr;
322  }
323 #endif
324 
325 
326 #ifdef SIP_RUN
327 
338  SIP_PYOBJECT __getitem__( int index ) SIP_TYPEHINT( QgsAbstractGeometry );
339  % MethodCode
340  const int count = sipCpp->numGeometries();
341  if ( a0 < -count || a0 >= count )
342  {
343  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
344  sipIsErr = 1;
345  }
346  else if ( a0 >= 0 )
347  {
348  return sipConvertFromType( sipCpp->geometryN( a0 ), sipType_QgsAbstractGeometry, NULL );
349  }
350  else
351  {
352  return sipConvertFromType( sipCpp->geometryN( count + a0 ), sipType_QgsAbstractGeometry, NULL );
353  }
354  % End
355 
366  void __delitem__( int index );
367  % MethodCode
368  const int count = sipCpp->numGeometries();
369  if ( a0 >= 0 && a0 < count )
370  sipCpp->removeGeometry( a0 );
371  else if ( a0 < 0 && a0 >= -count )
372  sipCpp->removeGeometry( count + a0 );
373  else
374  {
375  PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
376  sipIsErr = 1;
377  }
378  % End
379 
385  SIP_PYOBJECT __iter__() SIP_TYPEHINT( QgsGeometryPartIterator );
386  % MethodCode
387  sipRes = sipConvertFromNewType( new QgsGeometryPartIterator( sipCpp ), sipType_QgsGeometryPartIterator, Py_None );
388  % End
389 #endif
390 
404  QgsGeometryCollection *extractPartsByType( Qgis::WkbType type, bool useFlatType = true ) const SIP_FACTORY;
405 
406  QgsGeometryCollection *createEmptyWithSameType() const override SIP_FACTORY;
407 
408  protected:
409  int childCount() const override;
410  QgsAbstractGeometry *childGeometry( int index ) const override;
411  int compareToSameClass( const QgsAbstractGeometry *other ) const final;
412 
413  protected:
414  QVector< QgsAbstractGeometry * > mGeometries;
415 
419  virtual bool wktOmitChildType() const;
420 
424  bool fromCollectionWkt( const QString &wkt, const QVector<QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType = QString() );
425 
426  QgsBox3D calculateBoundingBox3D() const override;
427  void clearCache() const override;
428 
429  private:
430 
431  mutable QgsBox3D mBoundingBox;
432  mutable bool mHasCachedValidity = false;
433  mutable QString mValidityFailureReason;
434 };
435 
436 // clazy:excludeall=qstring-allocations
437 
438 #endif // QGSGEOMETRYCOLLECTION_H
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:54
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
An abstract base class for classes which transform geometries by transforming input points to output ...
Abstract base class for all geometries.
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 QgsAbstractGeometry * clone() const =0
Clones the geometry by performing a deep copy.
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 bool isEmpty() const
Returns true if the geometry is empty.
virtual void normalize()=0
Reorganizes the geometry into a normalized form (or "canonical" form).
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 bool operator==(const QgsAbstractGeometry &other) const =0
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
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:44
Geometry collection.
bool fuzzyDistanceEqual(const QgsAbstractGeometry &other, double epsilon=1e-8) const override
Performs fuzzy distance comparison between this geometry and other using an epsilon.
QVector< QgsAbstractGeometry * > mGeometries
static const QgsGeometryCollection * cast(const QgsAbstractGeometry *geom)
Cast the geom to a QgsGeometryCollection.
bool operator==(const QgsAbstractGeometry &other) const override
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
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
Java-style iterator for traversal of parts of a geometry.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
static bool isMultiType(Qgis::WkbType type)
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:758
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
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#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