1 /***************************************************************************
2                         qgsabstractgeometry.h
3   -------------------------------------------------------------------
4 Date                 : 04 Sept 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 QGSABSTRACTGEOMETRYV2
17 #define QGSABSTRACTGEOMETRYV2
18 
19 #include <array>
20 #include <functional>
21 #include <type_traits>
22 #include <QString>
23 
24 #include "qgis_core.h"
25 #include "qgis.h"
26 #include "qgswkbtypes.h"
27 #include "qgswkbptr.h"
28 
29 #ifndef SIP_RUN
30 #include "json_fwd.hpp"
31 using namespace nlohmann;
32 #endif
33 
34 class QgsMapToPixel;
35 class QgsCurve;
36 class QgsMultiCurve;
37 class QgsMultiPoint;
38 
39 struct QgsVertexId;
40 class QgsVertexIterator;
41 class QPainter;
42 class QDomDocument;
43 class QDomElement;
44 class QgsGeometryPartIterator;
45 class QgsGeometryConstPartIterator;
46 class QgsConstWkbPtr;
47 class QPainterPath;
48 class QgsAbstractGeometryTransformer;
49 class QgsFeedback;
50 class QgsCoordinateTransform;
51 class QgsPoint;
52 class QgsRectangle;
53 
54 typedef QVector< QgsPoint > QgsPointSequence;
55 #ifndef SIP_RUN
56 typedef QVector< QgsPointSequence > QgsRingSequence;
57 typedef QVector< QgsRingSequence > QgsCoordinateSequence;
58 #else
59 typedef QVector< QVector< QgsPoint > > QgsRingSequence;
60 typedef QVector< QVector< QVector< QgsPoint > > > QgsCoordinateSequence;
61 #endif
62 
63 
64 /**
65  * \ingroup core
66  * \class QgsAbstractGeometry
67  * \brief Abstract base class for all geometries
68  *
69  * \note QgsAbstractGeometry objects are inherently Cartesian/planar geometries. They have no concept of geodesy, and none
70  * of the methods or properties exposed from the QgsAbstractGeometry API (or QgsGeometry API) utilize
71  * geodesic calculations. Accordingly, properties like length() and area() and spatial operations like centroid()
72  * are always calculated using strictly Cartesian mathematics. In contrast, the QgsDistanceArea class exposes
73  * methods for working with geodesic calculations and spatial operations on geometries,
74  * and should be used whenever calculations which account for the curvature of the Earth (or any other celestial body)
75  * are required.
76  *
77  * \since QGIS 2.10
78  */
79 class CORE_EXPORT QgsAbstractGeometry
80 {
81 
82 #ifdef SIP_RUN
83     SIP_CONVERT_TO_SUBCLASS_CODE
84     if ( qgsgeometry_cast<QgsPoint *>( sipCpp ) != nullptr )
85       sipType = sipType_QgsPoint;
86     else if ( qgsgeometry_cast<QgsLineString *>( sipCpp ) != nullptr )
87       sipType = sipType_QgsLineString;
88     else if ( qgsgeometry_cast<QgsCircularString *>( sipCpp ) != nullptr )
89       sipType = sipType_QgsCircularString;
90     else if ( qgsgeometry_cast<QgsCompoundCurve *>( sipCpp ) != nullptr )
91       sipType = sipType_QgsCompoundCurve;
92     else if ( qgsgeometry_cast<QgsTriangle *>( sipCpp ) != nullptr )
93       sipType = sipType_QgsTriangle;
94     else if ( qgsgeometry_cast<QgsPolygon *>( sipCpp ) != nullptr )
95       sipType = sipType_QgsPolygon;
96     else if ( qgsgeometry_cast<QgsCurvePolygon *>( sipCpp ) != nullptr )
97       sipType = sipType_QgsCurvePolygon;
98     else if ( qgsgeometry_cast<QgsMultiPoint *>( sipCpp ) != nullptr )
99       sipType = sipType_QgsMultiPoint;
100     else if ( qgsgeometry_cast<QgsMultiLineString *>( sipCpp ) != nullptr )
101       sipType = sipType_QgsMultiLineString;
102     else if ( qgsgeometry_cast<QgsMultiPolygon *>( sipCpp ) != nullptr )
103       sipType = sipType_QgsMultiPolygon;
104     else if ( qgsgeometry_cast<QgsMultiSurface *>( sipCpp ) != nullptr )
105       sipType = sipType_QgsMultiSurface;
106     else if ( qgsgeometry_cast<QgsMultiCurve *>( sipCpp ) != nullptr )
107       sipType = sipType_QgsMultiCurve;
108     else if ( qgsgeometry_cast<QgsGeometryCollection *>( sipCpp ) != nullptr )
109       sipType = sipType_QgsGeometryCollection;
110     else
111       sipType = 0;
112     SIP_END
113 #endif
114 
115     Q_GADGET
116 
117   public:
118 
119     //! Segmentation tolerance as maximum angle or maximum difference between approximation and circle
120     enum SegmentationToleranceType
121     {
122 
123       /**
124        * Maximum angle between generating radii (lines from arc center
125        * to output vertices)
126       */
127       MaximumAngle = 0,
128 
129       /**
130        * Maximum distance between an arbitrary point on the original
131        * curve and closest point on its approximation.
132       */
133       MaximumDifference
134     };
135     Q_ENUM( SegmentationToleranceType )
136 
137     //! Axis order for GML generation
138     enum AxisOrder
139     {
140 
141       /**
142        * X comes before Y (or lon before lat)
143        */
144       XY = 0,
145 
146       /**
147        * Y comes before X (or lat before lon)
148        */
149       YX
150     };
151     Q_ENUM( QgsAbstractGeometry::AxisOrder )
152 
153     /**
154      * Constructor for QgsAbstractGeometry.
155      */
156     QgsAbstractGeometry() = default;
157     virtual ~QgsAbstractGeometry() = default;
158     QgsAbstractGeometry( const QgsAbstractGeometry &geom );
159     QgsAbstractGeometry &operator=( const QgsAbstractGeometry &geom );
160 
161     virtual bool operator==( const QgsAbstractGeometry &other ) const = 0;
162     virtual bool operator!=( const QgsAbstractGeometry &other ) const = 0;
163 
164     /**
165      * Clones the geometry by performing a deep copy
166      */
167     virtual QgsAbstractGeometry *clone() const = 0 SIP_FACTORY;
168 
169     /**
170      * Comparator for sorting of geometry.
171      *
172      * \since QGIS 3.20
173      */
174     virtual int compareTo( const QgsAbstractGeometry *other ) const;
175 
176     /**
177      * Clears the geometry, ie reset it to a null geometry
178      */
179     virtual void clear() = 0;
180 
181     /**
182      * Returns the minimal bounding box for the geometry
183      */
184     virtual QgsRectangle boundingBox() const = 0;
185 
186     //mm-sql interface
187 
188     /**
189      * Returns the inherent dimension of the geometry. For example, this is 0 for a point geometry,
190      * 1 for a linestring and 2 for a polygon.
191      */
192     virtual int dimension() const = 0;
193 
194     /**
195      * Returns a unique string representing the geometry type.
196      * \see wkbType
197      * \see wktTypeStr
198      */
199     virtual QString geometryType() const = 0;
200 
201     /**
202      * Returns the WKB type of the geometry.
203      * \see geometryType
204      * \see wktTypeStr
205      */
wkbType()206     inline QgsWkbTypes::Type wkbType() const SIP_HOLDGIL { return mWkbType; }
207 
208     /**
209      * Returns the WKT type string of the geometry.
210      * \see geometryType
211      * \see wkbType
212      */
213     QString wktTypeStr() const;
214 
215     /**
216      * Returns TRUE if the geometry is 3D and contains a z-value.
217      * \see isMeasure
218      */
is3D()219     bool is3D() const SIP_HOLDGIL
220     {
221       return QgsWkbTypes::hasZ( mWkbType );
222     }
223 
224     /**
225      * Returns TRUE if the geometry contains m values.
226      * \see is3D
227      */
isMeasure()228     bool isMeasure() const SIP_HOLDGIL
229     {
230       return QgsWkbTypes::hasM( mWkbType );
231     }
232 
233     /**
234      * Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the geometry).
235      * For instance, a polygon geometry will have a boundary consisting of the linestrings for each ring in the polygon.
236      * \returns boundary for geometry. May be NULLPTR for some geometry types.
237      * \since QGIS 3.0
238      */
239     virtual QgsAbstractGeometry *boundary() const = 0 SIP_FACTORY;
240 
241     /**
242      * Reorganizes the geometry into a normalized form (or "canonical" form).
243      *
244      * Polygon rings will be rearranged so that their starting vertex is the lower left and ring orientation follows the
245      * right hand rule, collections are ordered by geometry type, and other normalization techniques are applied. The
246      * resultant geometry will be geometrically equivalent to the original geometry.
247      *
248      * \since QGIS 3.20
249      */
250     virtual void normalize() = 0;
251 
252     //import
253 
254     /**
255      * Sets the geometry from a WKB string.
256      * After successful read the wkb argument will be at the position where the reading has stopped.
257      * \see fromWkt
258      */
259     virtual bool fromWkb( QgsConstWkbPtr &wkb ) = 0;
260 
261     /**
262      * Sets the geometry from a WKT string.
263      * \see fromWkb
264      */
265     virtual bool fromWkt( const QString &wkt ) = 0;
266 
267     //export
268 
269     /**
270      * WKB export flags.
271      * \since QGIS 3.14
272      */
273     enum WkbFlag
274     {
275       FlagExportTrianglesAsPolygons = 1 << 0, //!< Triangles should be exported as polygon geometries
276     };
277     Q_DECLARE_FLAGS( WkbFlags, WkbFlag )
278 
279     /**
280      * Returns the length of the QByteArray returned by asWkb()
281      *
282      * The optional \a flags argument specifies flags controlling WKB export behavior
283      *
284      * \since QGIS 3.16
285      */
286     virtual int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const = 0;
287 
288     /**
289      * Returns a WKB representation of the geometry.
290      *
291      * The optional \a flags argument specifies flags controlling WKB export behavior (since QGIS 3.14).
292      *
293      * \see asWkt
294      * \see asGml2
295      * \see asGml3
296      * \see asJson()
297      * \since QGIS 3.0
298      */
299     virtual QByteArray asWkb( WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const = 0;
300 
301     /**
302      * Returns a WKT representation of the geometry.
303      * \param precision number of decimal places for coordinates
304      * \see asWkb()
305      * \see asGml2()
306      * \see asGml3()
307      * \see asJson()
308      */
309     virtual QString asWkt( int precision = 17 ) const = 0;
310 
311     /**
312      * Returns a GML2 representation of the geometry.
313      * \param doc DOM document
314      * \param precision number of decimal places for coordinates
315      * \param ns XML namespace
316      * \param axisOrder Axis order for generated GML
317      * \see asWkb()
318      * \see asWkt()
319      * \see asGml3()
320      * \see asJson()
321      */
322     virtual QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const = 0;
323 
324     /**
325      * Returns a GML3 representation of the geometry.
326      * \param doc DOM document
327      * \param precision number of decimal places for coordinates
328      * \param ns XML namespace
329      * \param axisOrder Axis order for generated GML
330      * \see asWkb()
331      * \see asWkt()
332      * \see asGml2()
333      * \see asJson()
334      */
335     virtual QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const = 0;
336 
337     /**
338      * Returns a GeoJSON representation of the geometry as a QString.
339      * \param precision number of decimal places for coordinates
340      * \see asWkb()
341      * \see asWkt()
342      * \see asGml2()
343      * \see asGml3()
344      * \see asJsonObject()
345      */
346     QString asJson( int precision = 17 );
347 
348     /**
349      * Returns a json object representation of the geometry.
350      * \see asWkb()
351      * \see asWkt()
352      * \see asGml2()
353      * \see asGml3()
354      * \see asJson()
355      * \note not available in Python bindings
356      * \since QGIS 3.10
357      */
358     virtual json asJsonObject( int precision = 17 ) SIP_SKIP const;
359 
360     /**
361      * Returns a KML representation of the geometry.
362      * \since QGIS 3.12
363      */
364     virtual QString asKml( int precision = 17 ) const = 0;
365 
366 
367     //render pipeline
368 
369     /**
370      * Transforms the geometry using a coordinate transform
371      * \param ct coordinate transform
372      * \param d transformation direction
373      * \param transformZ set to TRUE to also transform z coordinates. This requires that
374      * the z coordinates in the geometry represent height relative to the vertical datum
375      * of the source CRS (generally ellipsoidal heights) and are expressed in its vertical
376      * units (generally meters). If FALSE, then z coordinates will not be changed by the
377      * transform.
378      */
379     virtual void transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection d = Qgis::TransformDirection::Forward, bool transformZ = false ) SIP_THROW( QgsCsException ) = 0;
380 
381     /**
382      * Transforms the x and y components of the geometry using a QTransform object \a t.
383      *
384      * Optionally, the geometry's z values can be scaled via \a zScale and translated via \a zTranslate.
385      * Similarly, m-values can be scaled via \a mScale and translated via \a mTranslate.
386      */
387     virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0,
388                             double mTranslate = 0.0, double mScale = 1.0 ) = 0;
389 
390     /**
391      * Draws the geometry using the specified QPainter.
392      * \param p destination QPainter
393      */
394     virtual void draw( QPainter &p ) const = 0;
395 
396     /**
397      * Returns the geometry represented as a QPainterPath.
398      *
399      * \warning not all geometry subclasses can be represented by a QPainterPath, e.g.
400      * points and multipoint geometries will return an empty path.
401      *
402      * \since QGIS 3.16
403      */
404     virtual QPainterPath asQPainterPath() const = 0;
405 
406     /**
407      * Returns the vertex number corresponding to a vertex \a id.
408      *
409      * The vertex numbers start at 0, so a return value of 0 corresponds
410      * to the first vertex.
411      *
412      * Returns -1 if a corresponding vertex could not be found.
413      *
414      * \since QGIS 3.0
415      */
416     virtual int vertexNumberFromVertexId( QgsVertexId id ) const = 0;
417 
418     /**
419      * Returns next vertex id and coordinates
420      * \param id initial value should be the starting vertex id. The next vertex id will be stored
421      * in this variable if found.
422      * \param vertex container for found node
423      * \returns FALSE if at end
424      */
425     virtual bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const = 0;
426 
427     /**
428      * Returns the vertices adjacent to a specified \a vertex within a geometry.
429      * \since QGIS 3.0
430      */
431     virtual void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const = 0;
432 
433     /**
434      * Retrieves the sequence of geometries, rings and nodes.
435      * \returns coordinate sequence
436      */
437     virtual QgsCoordinateSequence coordinateSequence() const = 0;
438 
439     /**
440      * Returns the number of nodes contained in the geometry
441      */
442     virtual int nCoordinates() const;
443 
444     /**
445      * Returns the point corresponding to a specified vertex id
446      */
447     virtual QgsPoint vertexAt( QgsVertexId id ) const = 0;
448 
449     /**
450      * Searches for the closest segment of the geometry to a given point.
451      * \param pt specifies the point to find closest segment to
452      * \param segmentPt storage for the closest point within the geometry
453      * \param vertexAfter storage for the ID of the vertex at the end of the closest segment
454      * \param leftOf indicates whether the point lies on the left side of the geometry (-1 if point is to the left
455      * of the geometry, +1 if the point is to the right of the geometry, or 0 for cases where left/right could not
456      * be determined, e.g. point exactly on a line)
457      * FALSE if point is to right of segment)
458      * \param epsilon epsilon for segment snapping
459      * \returns squared distance to closest segment or negative value on error
460      */
461     virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT,
462                                    QgsVertexId &vertexAfter SIP_OUT,
463                                    int *leftOf SIP_OUT = nullptr, double epsilon = 4 * std::numeric_limits<double>::epsilon() ) const = 0;
464 
465     //low-level editing
466 
467     /**
468      * Inserts a vertex into the geometry
469      * \param position vertex id for position of inserted vertex
470      * \param vertex vertex to insert
471      * \returns TRUE if insert was successful
472      * \see moveVertex
473      * \see deleteVertex
474      */
475     virtual bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) = 0;
476 
477     /**
478      * Moves a vertex within the geometry
479      * \param position vertex id for vertex to move
480      * \param newPos new position of vertex
481      * \returns TRUE if move was successful
482      * \see insertVertex
483      * \see deleteVertex
484      */
485     virtual bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) = 0;
486 
487     /**
488      * Deletes a vertex within the geometry
489      * \param position vertex id for vertex to delete
490      * \returns TRUE if delete was successful
491      * \see insertVertex
492      * \see moveVertex
493      */
494     virtual bool deleteVertex( QgsVertexId position ) = 0;
495 
496     /**
497      * Returns the planar, 2-dimensional length of the geometry.
498      *
499      * \warning QgsAbstractGeometry objects are inherently Cartesian/planar geometries, and the length
500      * returned by this method is calculated using strictly Cartesian mathematics. In contrast,
501      * the QgsDistanceArea class exposes methods for calculating the lengths of geometries using
502      * geodesic calculations which account for the curvature of the Earth (or any other
503      * celestial body).
504      *
505      * \see area()
506      * \see perimeter()
507      */
508     virtual double length() const;
509 
510     /**
511      * Returns the planar, 2-dimensional perimeter of the geometry.
512      *
513      * \warning QgsAbstractGeometry objects are inherently Cartesian/planar geometries, and the perimeter
514      * returned by this method is calculated using strictly Cartesian mathematics. In contrast,
515      * the QgsDistanceArea class exposes methods for calculating the perimeters of geometries using
516      * geodesic calculations which account for the curvature of the Earth (or any other
517      * celestial body).
518      *
519      * \see area()
520      * \see length()
521      */
522     virtual double perimeter() const;
523 
524     /**
525      * Returns the planar, 2-dimensional area of the geometry.
526      *
527      * \warning QgsAbstractGeometry objects are inherently Cartesian/planar geometries, and the area
528      * returned by this method is calculated using strictly Cartesian mathematics. In contrast,
529      * the QgsDistanceArea class exposes methods for calculating the areas of geometries using
530      * geodesic calculations which account for the curvature of the Earth (or any other
531      * celestial body).
532      *
533      * \see length()
534      * \see perimeter()
535      */
536     virtual double area() const;
537 
538     /**
539      * Returns the length of the segment of the geometry which begins at \a startVertex.
540      *
541      * \warning QgsAbstractGeometry objects are inherently Cartesian/planar geometries, and the lengths
542      * returned by this method are calculated using strictly Cartesian mathematics.
543      *
544      * \since QGIS 3.0
545      */
546     virtual double segmentLength( QgsVertexId startVertex ) const = 0;
547 
548     //! Returns the centroid of the geometry
549     virtual QgsPoint centroid() const;
550 
551     /**
552      * Returns TRUE if the geometry is empty
553      */
554     virtual bool isEmpty() const;
555 
556     /**
557      * Returns TRUE if the geometry contains curved segments
558      */
559     virtual bool hasCurvedSegments() const;
560 
561     /**
562      * Returns TRUE if the bounding box of this geometry intersects with a \a rectangle.
563      *
564      * Since this test only considers the bounding box of the geometry, is is very fast to
565      * calculate and handles invalid geometries.
566      *
567      * \since QGIS 3.20
568      */
569     virtual bool boundingBoxIntersects( const QgsRectangle &rectangle ) const SIP_HOLDGIL;
570 
571     /**
572      * Returns a version of the geometry without curves. Caller takes ownership of
573      * the returned geometry.
574      * \param tolerance segmentation tolerance
575      * \param toleranceType maximum segmentation angle or maximum difference between approximation and curve
576      */
577     virtual QgsAbstractGeometry *segmentize( double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
578 
579     /**
580      * Returns the geometry converted to the more generic curve type.
581      * E.g. QgsLineString -> QgsCompoundCurve, QgsPolygon -> QgsCurvePolygon,
582      * QgsMultiLineString -> QgsMultiCurve, QgsMultiPolygon -> QgsMultiSurface
583      * \returns the converted geometry. Caller takes ownership
584     */
585     virtual QgsAbstractGeometry *toCurveType() const = 0 SIP_FACTORY;
586 
587     /**
588      * Makes a new geometry with all the points or vertices snapped to the closest point of the grid.
589      * Ownership is transferred to the caller.
590      *
591      * If the gridified geometry could not be calculated NULLPTR will be returned.
592      * It may generate an invalid geometry (in some corner cases).
593      * It can also be thought as rounding the edges and it may be useful for removing errors.
594      *
595      * Example:
596      *
597      * \code{.py}
598      *   geometry.snappedToGrid(1, 1)
599      * \endcode
600      *
601      * In this case we use a 2D grid of 1x1 to gridify.
602      * In this case, it can be thought like rounding the x and y of all the points/vertices to full units (remove all decimals).
603      * \param hSpacing Horizontal spacing of the grid (x axis). 0 to disable.
604      * \param vSpacing Vertical spacing of the grid (y axis). 0 to disable.
605      * \param dSpacing Depth spacing of the grid (z axis). 0 (default) to disable.
606      * \param mSpacing Custom dimension spacing of the grid (m axis). 0 (default) to disable.
607      * \since 3.0
608      */
609     virtual QgsAbstractGeometry *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const = 0 SIP_FACTORY;
610 
611     /**
612      * Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a
613      * degenerate geometry.
614      *
615      * The \a epsilon parameter specifies the tolerance for coordinates when determining that
616      * vertices are identical.
617      *
618      * By default, z values are not considered when detecting duplicate nodes. E.g. two nodes
619      * with the same x and y coordinate but different z values will still be considered
620      * duplicate and one will be removed. If \a useZValues is TRUE, then the z values are
621      * also tested and nodes with the same x and y but different z will be maintained.
622      *
623      * Note that duplicate nodes are not tested between different parts of a multipart geometry. E.g.
624      * a multipoint geometry with overlapping points will not be changed by this method.
625      *
626      * The function will return TRUE if nodes were removed, or FALSE if no duplicate nodes
627      * were found.
628      *
629      * \since QGIS 3.0
630      */
631     virtual bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) = 0;
632 
633     /**
634      * Returns approximate angle at a vertex. This is usually the average angle between adjacent
635      * segments, and can be pictured as the orientation of a line following the curvature of the
636      * geometry at the specified vertex.
637      * \param vertex the vertex id
638      * \returns rotation in radians, clockwise from north
639      */
640     virtual double vertexAngle( QgsVertexId vertex ) const = 0;
641 
642     /**
643      * Returns the number of vertices of which this geometry is built.
644      */
645     virtual int vertexCount( int part = 0, int ring = 0 ) const = 0;
646 
647     /**
648      * Returns the number of rings of which this geometry is built.
649      */
650     virtual int ringCount( int part = 0 ) const = 0;
651 
652     /**
653      * Returns count of parts contained in the geometry.
654      * \see vertexCount
655      * \see ringCount
656      */
657     virtual int partCount() const = 0;
658 
659     /**
660      * Adds a z-dimension to the geometry, initialized to a preset value.
661      * \param zValue initial z-value for all nodes
662      * \returns TRUE on success
663      * \see dropZValue()
664      * \see addMValue()
665      * \since QGIS 2.12
666      */
667     virtual bool addZValue( double zValue = 0 ) = 0;
668 
669     /**
670      * Adds a measure to the geometry, initialized to a preset value.
671      * \param mValue initial m-value for all nodes
672      * \returns TRUE on success
673      * \see dropMValue()
674      * \see addZValue()
675      * \since QGIS 2.12
676      */
677     virtual bool addMValue( double mValue = 0 ) = 0;
678 
679     /**
680      * Drops any z-dimensions which exist in the geometry.
681      * \returns TRUE if Z values were present and have been removed
682      * \see addZValue()
683      * \see dropMValue()
684      * \since QGIS 2.14
685      */
686     virtual bool dropZValue() = 0;
687 
688     /**
689      * Drops any measure values which exist in the geometry.
690      * \returns TRUE if m-values were present and have been removed
691      * \see addMValue()
692      * \see dropZValue()
693      * \since QGIS 2.14
694      */
695     virtual bool dropMValue() = 0;
696 
697     /**
698      * Swaps the x and y coordinates from the geometry. This can be used
699      * to repair geometries which have accidentally had their latitude and longitude
700      * coordinates reversed.
701      * \since QGIS 3.2
702      */
703     virtual void swapXy() = 0;
704 
705     /**
706      * Converts the geometry to a specified type.
707      * \returns TRUE if conversion was successful
708      * \since QGIS 2.14
709      */
710     virtual bool convertTo( QgsWkbTypes::Type type );
711 
712     /**
713      * Returns a reference to the simplest lossless representation of this geometry,
714      * e.g. if the geometry is a multipart geometry type with a single member geometry,
715      * a reference to that part will be returned.
716      *
717      * This method employs the following logic:
718      *
719      * - For multipart geometries containing a single part only a direct reference to that part will be returned.
720      * - For compound curve geometries containing a single curve only a direct reference to that curve will be returned.
721      *
722      * This method returns a reference only, and does not involve any geometry cloning.
723      *
724      * \note Ownership of the returned geometry is NOT transferred, and remains with the original
725      * geometry object. Callers must take care to ensure that the original geometry object
726      * exists for the lifespan of the returned object.
727      *
728      * \since QGIS 3.20
729      */
730     virtual const QgsAbstractGeometry *simplifiedTypeRef() const SIP_HOLDGIL;
731 
732     /**
733      * Checks validity of the geometry, and returns TRUE if the geometry is valid.
734      *
735      * \param error will be set to the validity error message
736      * \param flags indicates optional flags which control the type of validity checking performed
737      * (corresponding to Qgis::GeometryValidityFlags).
738      *
739      * \returns TRUE if geometry is valid
740      *
741      * \since QGIS 3.8
742      */
743     virtual bool isValid( QString &error SIP_OUT, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const = 0;
744 
745     /**
746      * Transforms the vertices from the geometry in place, using the specified geometry \a transformer
747      * object.
748      *
749      * Depending on the \a transformer used, this may result in an invalid geometry.
750      *
751      * The optional \a feedback argument can be used to cancel the transformation before it completes.
752      * If this is done, the geometry will be left in a semi-transformed state.
753      *
754      * \returns TRUE if the geometry was successfully transformed.
755      *
756      * \since QGIS 3.18
757      */
758     virtual bool transform( QgsAbstractGeometryTransformer *transformer, QgsFeedback *feedback = nullptr ) = 0;
759 
760 #ifndef SIP_RUN
761 
762     /**
763      * Filters the vertices from the geometry in place, removing any which do not return TRUE for the \a filter function
764      * check. Has no meaning when called on a single point geometry.
765      *
766      * Depending on the \a filter used, this may result in an invalid geometry.
767      *
768      * \note Not available in Python bindings
769      * \since QGIS 3.2
770      */
771     virtual void filterVertices( const std::function< bool( const QgsPoint & ) > &filter );
772 
773     /**
774      * Transforms the vertices from the geometry in place, applying the \a transform function
775      * to every vertex.
776      *
777      * Depending on the \a transform used, this may result in an invalid geometry.
778      *
779      * Transform functions are not permitted to alter the dimensionality of vertices. If
780      * a transform which adds (or removes) z/m values is desired, first call the corresponding
781      * addZValue() or addMValue() function to change the geometry's dimensionality and then
782      * transform.
783      *
784      * \note Not available in Python bindings
785      * \since QGIS 3.4
786      */
787     virtual void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform );
788 
789     /**
790      * \ingroup core
791      * \brief The part_iterator class provides STL-style iterator for geometry parts.
792      * \since QGIS 3.6
793      */
794     class CORE_EXPORT part_iterator
795     {
796       private:
797 
798         int mIndex = 0; //!< Current part in the geometry
799         QgsAbstractGeometry *mGeometry = nullptr;
800 
801       public:
802         //! Create invalid iterator
803         part_iterator() = default;
804 
805         //! Create part iterator for a geometry
806         part_iterator( QgsAbstractGeometry *g, int index );
807 
808         /**
809          * The prefix ++ operator (++it) advances the iterator to the next part and returns an iterator to the new current part.
810          * Calling this function on iterator that is already past the last item leads to undefined results.
811          */
812         part_iterator &operator++();
813 
814         //! The postfix ++ operator (it++) advances the iterator to the next part and returns an iterator to the previously current part.
815         part_iterator operator++( int );
816 
817         //! Returns the current item.
818         QgsAbstractGeometry *operator*() const;
819 
820         //! Returns the part number of the current item.
821         int partNumber() const;
822 
823         bool operator==( part_iterator other ) const;
824         bool operator!=( part_iterator other ) const { return !( *this == other ); }
825     };
826 
827     /**
828      * Returns STL-style iterator pointing to the first part of the geometry.
829      *
830      * \see parts_end()
831      * \see parts()
832      *
833      * \since QGIS 3.6
834      */
parts_begin()835     part_iterator parts_begin()
836     {
837       return part_iterator( this, 0 );
838     }
839 
840     /**
841      * Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
842      *
843      * \see parts_begin()
844      * \see parts()
845      *
846      * \since QGIS 3.6
847      */
848     part_iterator parts_end();
849 
850     /**
851      * Returns Java-style iterator for traversal of parts of the geometry. This iterator
852      * returns read-only references to parts and cannot be used to modify the parts.
853      *
854      * \note Not available in Python bindings
855      * \since QGIS 3.6
856      */
857     QgsGeometryConstPartIterator parts() const;
858 
859     /**
860      * \ingroup core
861      * \brief The part_iterator class provides STL-style iterator for const references to geometry parts.
862      * \since QGIS 3.6
863      */
864     class CORE_EXPORT const_part_iterator
865     {
866       private:
867 
868         int mIndex = 0; //!< Current part in the geometry
869         const QgsAbstractGeometry *mGeometry = nullptr;
870 
871       public:
872         //! Create invalid iterator
873         const_part_iterator() = default;
874 
875         //! Create part iterator for a geometry
876         const_part_iterator( const QgsAbstractGeometry *g, int index );
877 
878         /**
879          * The prefix ++ operator (++it) advances the iterator to the next part and returns an iterator to the new current part.
880          * Calling this function on iterator that is already past the last item leads to undefined results.
881          */
882         const_part_iterator &operator++();
883 
884         //! The postfix ++ operator (it++) advances the iterator to the next part and returns an iterator to the previously current part.
885         const_part_iterator operator++( int );
886 
887         //! Returns the current item.
888         const QgsAbstractGeometry *operator*() const;
889 
890         //! Returns the part number of the current item.
891         int partNumber() const;
892 
893         bool operator==( const_part_iterator other ) const;
894         bool operator!=( const_part_iterator other ) const { return !( *this == other ); }
895     };
896 
897     /**
898      * Returns STL-style iterator pointing to the const first part of the geometry.
899      *
900      * \see const_parts_end()
901      *
902      * \since QGIS 3.6
903      */
const_parts_begin()904     const_part_iterator const_parts_begin() const
905     {
906       return const_part_iterator( this, 0 );
907     }
908 
909     /**
910      * Returns STL-style iterator pointing to the imaginary const part after the last part of the geometry.
911      *
912      * \see const_parts_begin()
913      *
914      * \since QGIS 3.6
915      */
916     const_part_iterator const_parts_end() const;
917 
918 
919     /**
920      * \ingroup core
921      * \brief The vertex_iterator class provides STL-style iterator for vertices.
922      * \since QGIS 3.0
923      */
924     class CORE_EXPORT vertex_iterator
925     {
926       private:
927 
928         /**
929          * A helper structure to keep track of vertex traversal within one level within a geometry.
930          * For example, linestring geometry will have just one level, while multi-polygon has three levels
931          * (part index, ring index, vertex index).
932          */
933         struct Level
934         {
935           const QgsAbstractGeometry *g = nullptr;  //!< Current geometry
936           int index = 0;               //!< Ptr in the current geometry
937 
938           bool operator==( const Level &other ) const;
939         };
940 
941         std::array<Level, 3> levels;  //!< Stack of levels - three levels should be sufficient (e.g. part index, ring index, vertex index)
942         int depth = -1;               //!< At what depth level are we right now
943 
944         void digDown();   //!< Prepare the stack of levels so that it points to a leaf child geometry
945 
946       public:
947         //! Create invalid iterator
948         vertex_iterator() = default;
949 
950         //! Create vertex iterator for a geometry
951         vertex_iterator( const QgsAbstractGeometry *g, int index );
952 
953         /**
954          * The prefix ++ operator (++it) advances the iterator to the next vertex and returns an iterator to the new current vertex.
955          * Calling this function on iterator that is already past the last item leads to undefined results.
956          */
957         vertex_iterator &operator++();
958 
959         //! The postfix ++ operator (it++) advances the iterator to the next vertex and returns an iterator to the previously current vertex.
960         vertex_iterator operator++( int );
961 
962         //! Returns the current item.
963         QgsPoint operator*() const;
964 
965         //! Returns vertex ID of the current item.
966         QgsVertexId vertexId() const;
967 
968         bool operator==( const vertex_iterator &other ) const;
969         bool operator!=( const vertex_iterator &other ) const { return !( *this == other ); }
970     };
971 
972     /**
973      * Returns STL-style iterator pointing to the first vertex of the geometry.
974      *
975      * \see vertices_end()
976      * \see vertices()
977      *
978      * \since QGIS 3.0
979      */
vertices_begin()980     vertex_iterator vertices_begin() const
981     {
982       return vertex_iterator( this, 0 );
983     }
984 
985     /**
986      * Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry.
987      *
988      * \see vertices_begin()
989      * \see vertices()
990      *
991      * \since QGIS 3.0
992      */
vertices_end()993     vertex_iterator vertices_end() const
994     {
995       return vertex_iterator( this, childCount() );
996     }
997 #endif
998 
999     /**
1000      * Returns Java-style iterator for traversal of parts of the geometry. This iterator
1001      * can safely be used to modify parts of the geometry.
1002      *
1003      * Example
1004      *
1005      * \code{.py}
1006      *   # print the WKT representation of each part in a multi-point geometry
1007      *   geometry = QgsMultiPoint.fromWkt( 'MultiPoint( 0 0, 1 1, 2 2)' )
1008      *   for part in geometry.parts():
1009      *       print(part.asWkt())
1010      *
1011      *   # single part geometries only have one part - this loop will iterate once only
1012      *   geometry = QgsLineString.fromWkt( 'LineString( 0 0, 10 10 )' )
1013      *   for part in geometry.parts():
1014      *       print(part.asWkt())
1015      *
1016      *   # parts can be modified during the iteration
1017      *   geometry = QgsMultiPoint.fromWkt( 'MultiPoint( 0 0, 1 1, 2 2)' )
1018      *   for part in geometry.parts():
1019      *       part.transform(ct)
1020      *
1021      *   # part iteration can also be combined with vertex iteration
1022      *   geometry = QgsMultiPolygon.fromWkt( 'MultiPolygon((( 0 0, 0 10, 10 10, 10 0, 0 0 ),( 5 5, 5 6, 6 6, 6 5, 5 5)),((20 2, 22 2, 22 4, 20 4, 20 2)))' )
1023      *   for part in geometry.parts():
1024      *       for v in part.vertices():
1025      *           print(v.x(), v.y())
1026      *
1027      * \endcode
1028      *
1029      * \see vertices()
1030      * \since QGIS 3.6
1031      */
1032     QgsGeometryPartIterator parts();
1033 
1034 
1035     /**
1036      * Returns a read-only, Java-style iterator for traversal of vertices of all the geometry, including all geometry parts and rings.
1037      *
1038      * \warning The iterator returns a copy of individual vertices, and accordingly geometries cannot be
1039      * modified using the iterator. See transformVertices() for a safe method to modify vertices "in-place".
1040      *
1041      * Example
1042      *
1043      * \code{.py}
1044      *   # print the x and y coordinate for each vertex in a LineString
1045      *   geometry = QgsLineString.fromWkt( 'LineString( 0 0, 1 1, 2 2)' )
1046      *   for v in geometry.vertices():
1047      *       print(v.x(), v.y())
1048      *
1049      *   # vertex iteration includes all parts and rings
1050      *   geometry = QgsMultiPolygon.fromWkt( 'MultiPolygon((( 0 0, 0 10, 10 10, 10 0, 0 0 ),( 5 5, 5 6, 6 6, 6 5, 5 5)),((20 2, 22 2, 22 4, 20 4, 20 2)))' )
1051      *   for v in geometry.vertices():
1052      *       print(v.x(), v.y())
1053      * \endcode
1054      *
1055      * \see parts()
1056      * \since QGIS 3.0
1057      */
1058     QgsVertexIterator vertices() const;
1059 
1060     /**
1061      * Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
1062      * To create it, the geometry is default constructed and then the WKB is changed.
1063      * \see clone()
1064      * \since 3.0
1065      */
1066     virtual QgsAbstractGeometry *createEmptyWithSameType() const = 0 SIP_FACTORY;
1067 
1068   protected:
1069 
1070     /**
1071      * Returns the sort index for the geometry, used in the compareTo() method to compare
1072      * geometries of different types.
1073      *
1074      * \since QGIS 3.20
1075      */
1076     int sortIndex() const;
1077 
1078     /**
1079      * Compares to an \a other geometry of the same class, and returns a integer
1080      * for sorting of the two geometries.
1081      *
1082      * \note The actual logic for the sorting is an internal detail only and is subject to change
1083      * between QGIS versions. The result should only be used for direct comparison of geometries
1084      * and not stored for later use.
1085      *
1086      * \since QGIS 3.20
1087      */
1088     virtual int compareToSameClass( const QgsAbstractGeometry *other ) const = 0;
1089 
1090     /**
1091      * Returns whether the geometry has any child geometries (FALSE for point / curve, TRUE otherwise)
1092      * \note used for vertex_iterator implementation
1093      * \since QGIS 3.0
1094      */
1095     virtual bool hasChildGeometries() const;
1096 
1097     /**
1098      * Returns number of child geometries (for geometries with child geometries) or child points (for geometries without child geometries - i.e. curve / point)
1099      * \note used for vertex_iterator implementation
1100      * \since QGIS 3.0
1101      */
childCount()1102     virtual int childCount() const { return 0; }
1103 
1104     /**
1105      * Returns pointer to child geometry (for geometries with child geometries - i.e. geom. collection / polygon)
1106      * \note used for vertex_iterator implementation
1107      * \since QGIS 3.0
1108      */
childGeometry(int index)1109     virtual QgsAbstractGeometry *childGeometry( int index ) const { Q_UNUSED( index ) return nullptr; }
1110 
1111     /**
1112      * Returns point at index (for geometries without child geometries - i.e. curve / point)
1113      * \note used for vertex_iterator implementation
1114      * \since QGIS 3.0
1115      */
1116     virtual QgsPoint childPoint( int index ) const;
1117 
1118   protected:
1119     QgsWkbTypes::Type mWkbType = QgsWkbTypes::Unknown;
1120 
1121     /**
1122      * Updates the geometry type based on whether sub geometries contain z or m values.
1123      */
1124     void setZMTypeFromSubGeometry( const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType );
1125 
1126     /**
1127      * Default calculator for the minimal bounding box for the geometry. Derived classes should override this method
1128      * if a more efficient bounding box calculation is available.
1129      */
1130     virtual QgsRectangle calculateBoundingBox() const;
1131 
1132     /**
1133      * Clears any cached parameters associated with the geometry, e.g., bounding boxes
1134      */
1135     virtual void clearCache() const;
1136 
1137     friend class TestQgsGeometry;
1138 };
1139 
1140 
1141 #ifndef SIP_RUN
1142 
1143 template <class T>
qgsgeometry_cast(const QgsAbstractGeometry * geom)1144 inline T qgsgeometry_cast( const QgsAbstractGeometry *geom )
1145 {
1146   return const_cast<T>( std::remove_pointer<T>::type::cast( geom ) );
1147 }
1148 
1149 #endif
1150 
1151 // clazy:excludeall=qstring-allocations
1152 
1153 /**
1154  * \ingroup core
1155  * \brief Java-style iterator for traversal of vertices of a geometry
1156  * \since QGIS 3.0
1157  */
1158 class CORE_EXPORT QgsVertexIterator
1159 {
1160   public:
1161     //! Constructor for QgsVertexIterator
1162     QgsVertexIterator() = default;
1163 
1164     //! Constructs iterator for the given geometry
QgsVertexIterator(const QgsAbstractGeometry * geometry)1165     QgsVertexIterator( const QgsAbstractGeometry *geometry )
1166       : g( geometry )
1167       , i( g->vertices_begin() )
1168       , n( g->vertices_end() )
1169     {
1170     }
1171 
1172     //! Find out whether there are more vertices
hasNext()1173     bool hasNext() const
1174     {
1175       return g && g->vertices_end() != i;
1176     }
1177 
1178     //! Returns next vertex of the geometry (undefined behavior if hasNext() returns FALSE before calling next())
1179     QgsPoint next();
1180 
1181 #ifdef SIP_RUN
1182     QgsVertexIterator *__iter__();
1183     % MethodCode
1184     sipRes = sipCpp;
1185     % End
1186 
1187     SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsPoint );
1188     % MethodCode
1189     if ( sipCpp->hasNext() )
1190       sipRes = sipConvertFromType( new QgsPoint( sipCpp->next() ), sipType_QgsPoint, Py_None );
1191     else
1192       PyErr_SetString( PyExc_StopIteration, "" );
1193     % End
1194 #endif
1195 
1196   private:
1197     const QgsAbstractGeometry *g = nullptr;
1198     QgsAbstractGeometry::vertex_iterator i, n;
1199 
1200 };
1201 
1202 /**
1203  * \ingroup core
1204  * \brief Java-style iterator for traversal of parts of a geometry
1205  * \since QGIS 3.6
1206  */
1207 class CORE_EXPORT QgsGeometryPartIterator
1208 {
1209   public:
1210     //! Constructor for QgsGeometryPartIterator
1211     QgsGeometryPartIterator() = default;
1212 
1213     //! Constructs iterator for the given geometry
QgsGeometryPartIterator(QgsAbstractGeometry * geometry)1214     QgsGeometryPartIterator( QgsAbstractGeometry *geometry )
1215       : g( geometry )
1216       , i( g->parts_begin() )
1217       , n( g->parts_end() )
1218     {
1219     }
1220 
1221     //! Find out whether there are more parts
hasNext()1222     bool hasNext() const SIP_HOLDGIL
1223     {
1224       return g && g->parts_end() != i;
1225     }
1226 
1227     //! Returns next part of the geometry (undefined behavior if hasNext() returns FALSE before calling next())
1228     QgsAbstractGeometry *next();
1229 
1230 #ifdef SIP_RUN
1231     QgsGeometryPartIterator *__iter__();
1232     % MethodCode
1233     sipRes = sipCpp;
1234     % End
1235 
1236     SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1237     % MethodCode
1238     if ( sipCpp->hasNext() )
1239       sipRes = sipConvertFromType( sipCpp->next(), sipType_QgsAbstractGeometry, NULL );
1240     else
1241       PyErr_SetString( PyExc_StopIteration, "" );
1242     % End
1243 #endif
1244 
1245   private:
1246     QgsAbstractGeometry *g = nullptr;
1247     QgsAbstractGeometry::part_iterator i, n;
1248 
1249 };
1250 
1251 
1252 /**
1253  * \ingroup core
1254  * \brief Java-style iterator for const traversal of parts of a geometry
1255  * \since QGIS 3.6
1256  */
1257 class CORE_EXPORT QgsGeometryConstPartIterator
1258 {
1259   public:
1260     //! Constructor for QgsGeometryConstPartIterator
1261     QgsGeometryConstPartIterator() = default;
1262 
1263     //! Constructs iterator for the given geometry
QgsGeometryConstPartIterator(const QgsAbstractGeometry * geometry)1264     QgsGeometryConstPartIterator( const QgsAbstractGeometry *geometry )
1265       : g( geometry )
1266       , i( g->const_parts_begin() )
1267       , n( g->const_parts_end() )
1268     {
1269     }
1270 
1271     //! Find out whether there are more parts
hasNext()1272     bool hasNext() const SIP_HOLDGIL
1273     {
1274       return g && g->const_parts_end() != i;
1275     }
1276 
1277     //! Returns next part of the geometry (undefined behavior if hasNext() returns FALSE before calling next())
1278     const QgsAbstractGeometry *next();
1279 
1280 #ifdef SIP_RUN
1281     QgsGeometryConstPartIterator *__iter__();
1282     % MethodCode
1283     sipRes = sipCpp;
1284     % End
1285 
1286     SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1287     % MethodCode
1288     if ( sipCpp->hasNext() )
1289       sipRes = sipConvertFromType( const_cast< QgsAbstractGeometry * >( sipCpp->next() ), sipType_QgsAbstractGeometry, NULL );
1290     else
1291       PyErr_SetString( PyExc_StopIteration, "" );
1292     % End
1293 #endif
1294 
1295   private:
1296     const QgsAbstractGeometry *g = nullptr;
1297     QgsAbstractGeometry::const_part_iterator i, n;
1298 
1299 };
1300 
1301 Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAbstractGeometry::WkbFlags )
1302 
1303 #endif //QGSABSTRACTGEOMETRYV2
1304