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