1 /***************************************************************************
2   qgsgeometry.h - Geometry (stored as Open Geospatial Consortium WKB)
3   -------------------------------------------------------------------
4 Date                 : 02 May 2005
5 Copyright            : (C) 2005 by Brendan Morley
6 email                : morb at ozemail dot com dot au
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 QGSGEOMETRY_H
17 #define QGSGEOMETRY_H
18 
19 #include <functional>
20 
21 #include <QDomDocument>
22 #include <QJsonObject>
23 #include <QSet>
24 #include <QString>
25 #include <QVector>
26 
27 #include <climits>
28 #include <limits>
29 #include <memory>
30 
31 #include "qgis_core.h"
32 #include "qgis_sip.h"
33 
34 #include "qgsabstractgeometry.h"
35 #include "qgspointxy.h"
36 #include "qgspoint.h"
37 #include "qgsfeatureid.h"
38 #include "qgsvertexid.h"
39 
40 #ifndef SIP_RUN
41 #include "json_fwd.hpp"
42 using namespace nlohmann;
43 #endif
44 
45 class QgsGeometryEngine;
46 class QgsVectorLayer;
47 class QgsMapToPixel;
48 class QPainter;
49 class QgsPolygon;
50 class QgsLineString;
51 class QgsCurve;
52 class QgsFeedback;
53 
54 /**
55  * Polyline as represented as a vector of two-dimensional points.
56  *
57  * This type has no support for Z/M dimensions and use of QgsPolyline is encouraged instead.
58  *
59  * \note In QGIS 2.x this type was available as QgsPolyline.
60  *
61  * \since QGIS 3.0
62  */
63 typedef QVector<QgsPointXY> QgsPolylineXY;
64 
65 /**
66  * Polyline as represented as a vector of points.
67  *
68  * This type has full support for Z/M dimensions.
69  *
70  * \since QGIS 3.0
71  */
72 typedef QgsPointSequence QgsPolyline;
73 
74 //! Polygon: first item of the list is outer ring, inner rings (if any) start from second item
75 #ifndef SIP_RUN
76 typedef QVector<QgsPolylineXY> QgsPolygonXY;
77 #else
78 typedef QVector<QVector<QgsPointXY>> QgsPolygonXY;
79 #endif
80 
81 //! A collection of QgsPoints that share a common collection of attributes
82 typedef QVector<QgsPointXY> QgsMultiPointXY;
83 
84 //! A collection of QgsPolylines that share a common collection of attributes
85 #ifndef SIP_RUN
86 typedef QVector<QgsPolylineXY> QgsMultiPolylineXY;
87 #else
88 typedef QVector<QVector<QgsPointXY>> QgsMultiPolylineXY;
89 #endif
90 
91 //! A collection of QgsPolygons that share a common collection of attributes
92 #ifndef SIP_RUN
93 typedef QVector<QgsPolygonXY> QgsMultiPolygonXY;
94 #else
95 typedef QVector<QVector<QVector<QgsPointXY>>> QgsMultiPolygonXY;
96 #endif
97 
98 class QgsRectangle;
99 
100 class QgsConstWkbPtr;
101 
102 struct QgsGeometryPrivate;
103 
104 /**
105  * \ingroup core
106  * \brief A geometry is the spatial representation of a feature.
107  *
108  * QgsGeometry acts as a generic container for geometry objects. QgsGeometry objects are implicitly shared,
109  * so making copies of geometries is inexpensive. The geometry container class can also be stored inside
110  * a QVariant object.
111  *
112  * The actual geometry representation is stored as a QgsAbstractGeometry within the container, and
113  * can be accessed via the get() method or set using the set() method. This gives access to the underlying
114  * raw geometry primitive, such as the point, line, polygon, curve or other geometry subclasses.
115  *
116  * \note QgsGeometry objects are inherently Cartesian/planar geometries. They have no concept of geodesy, and none
117  * of the methods or properties exposed from the QgsGeometry API (or QgsAbstractGeometry subclasses) utilize
118  * geodesic calculations. Accordingly, properties like length() and area() or spatial operations like buffer()
119  * are always calculated using strictly Cartesian mathematics. In contrast, the QgsDistanceArea class exposes
120  * methods for working with geodesic calculations and spatial operations on geometries,
121  * and should be used whenever calculations which account for the curvature of the Earth (or any other celestial body)
122  * are required.
123  */
124 class CORE_EXPORT QgsGeometry
125 {
126     Q_GADGET
127     Q_PROPERTY( bool isNull READ isNull )
128     Q_PROPERTY( QgsWkbTypes::GeometryType type READ type )
129 
130   public:
131 
132     //! Constructor
133     QgsGeometry() SIP_HOLDGIL;
134 
135     //! Copy constructor will prompt a deep copy of the object
136     QgsGeometry( const QgsGeometry & );
137 
138     /**
139      * Creates a deep copy of the object
140      * \note not available in Python bindings
141      */
142     QgsGeometry &operator=( QgsGeometry const &rhs ) SIP_SKIP;
143 
144     /**
145      * Creates a geometry from an abstract geometry object. Ownership of
146      * geom is transferred.
147      * \since QGIS 2.10
148      */
149     explicit QgsGeometry( QgsAbstractGeometry *geom SIP_TRANSFER );
150 
151     /**
152      * Creates a geometry from an abstract geometry object. Ownership of
153      * geom is transferred.
154      * \note Not available in Python bindings
155      */
156     explicit QgsGeometry( std::unique_ptr< QgsAbstractGeometry > geom ) SIP_SKIP;
157 
158     virtual ~QgsGeometry();
159 
160     /**
161      * Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
162      *
163      * This is much faster then calling the non-const get() method.
164      *
165      * \note In QGIS 2.x this method was named geometry().
166      *
167      * \see set()
168      * \see get()
169      * \since QGIS 3.0
170     */
171     const QgsAbstractGeometry *constGet() const SIP_HOLDGIL;
172 
173     /**
174      * Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
175      *
176      * This method can be slow to call, as it may trigger a detachment of the geometry
177      * and a deep copy. Where possible, use constGet() instead.
178      *
179      * \note In QGIS 2.x this method was named geometry().
180      *
181      * \see constGet()
182      * \see set()
183      * \since QGIS 3.0
184     */
185     QgsAbstractGeometry *get();
186 
187     /**
188      * Sets the underlying geometry store. Ownership of geometry is transferred.
189      *
190      * \note In QGIS 2.x this method was named setGeometry().
191      * \note This method is deprecated for usage in Python and will be removed from Python bindings with QGIS 4.
192      *       Using this method will confuse Python's memory management and type information system.
193      *       Better create a new QgsGeometry object instead.
194      *
195      * \see get()
196      * \see constGet()
197      * \since QGIS 3.0
198      */
199     void set( QgsAbstractGeometry *geometry SIP_TRANSFER ) SIP_DEPRECATED;
200 
201     /**
202      * Returns TRUE if the geometry is null (ie, contains no underlying geometry
203      * accessible via geometry() ).
204      * \see get
205      * \see isEmpty()
206      * \since QGIS 2.10
207      */
208     bool isNull() const SIP_HOLDGIL;
209 
210     //! Creates a new geometry from a WKT string
211     static QgsGeometry fromWkt( const QString &wkt );
212     //! Creates a new geometry from a QgsPointXY object
213     static QgsGeometry fromPointXY( const QgsPointXY &point ) SIP_HOLDGIL;
214     //! Creates a new geometry from a QgsMultiPointXY object
215     static QgsGeometry fromMultiPointXY( const QgsMultiPointXY &multipoint );
216 
217     /**
218      * Creates a new LineString geometry from a list of QgsPointXY points.
219      *
220      * Using fromPolyline() is preferred, as fromPolyline() is more efficient
221      * and will respect any Z or M dimensions present in the input points.
222      *
223      * \note In QGIS 2.x this method was available as fromPolyline().
224      *
225      * \see fromPolyline()
226      * \since QGIS 3.0
227      */
228     static QgsGeometry fromPolylineXY( const QgsPolylineXY &polyline );
229 
230     /**
231      * Creates a new LineString geometry from a list of QgsPoint points.
232      *
233      * This method will respect any Z or M dimensions present in the input points.
234      * E.g. if input points are PointZ type, the resultant linestring will be
235      * a LineStringZ type.
236      *
237      * \since QGIS 3.0
238      */
239     static QgsGeometry fromPolyline( const QgsPolyline &polyline );
240 
241     /**
242      * Creates a new geometry from a QgsMultiPolylineXY object.
243      */
244     static QgsGeometry fromMultiPolylineXY( const QgsMultiPolylineXY &multiline );
245 
246 #ifndef SIP_RUN
247 
248     /**
249      * Creates a new geometry from a QgsPolygonXY.
250      */
251 #else
252 
253     /**
254      * Creates a new polygon geometry from a list of lists of QgsPointXY.
255      *
256      * The first list of QgsPointXY objects specifies the exterior ring of the polygon, and the remaining
257      * lists specify any interior rings.
258      *
259      * ### Example
260      *
261      * \code{.py}
262      *   # Create a polygon geometry with a single exterior ring (a triangle)
263      *   polygon = QgsGeometry.fromPolygonXY([[QgsPointXY(1, 2), QgsPointXY(5, 2), QgsPointXY(5, 10), QgsPointXY(1, 2)]]))
264      *
265      *   # Create a donut shaped polygon geometry with an interior ring
266      *   polygon = QgsGeometry.fromPolygonXY([[QgsPointXY(1, 2), QgsPointXY(5, 2), QgsPointXY(5, 10), QgsPointXY(1, 10), QgsPointXY(1, 2)],
267      *                                        [QgsPointXY(3, 4), QgsPointXY(4, 4), QgsPointXY(4, 6), QgsPointXY(3, 6), QgsPointXY(3, 4)]])
268      * \endcode
269      */
270 #endif
271     static QgsGeometry fromPolygonXY( const QgsPolygonXY &polygon );
272 
273     /**
274      * Creates a new geometry from a QgsMultiPolygonXY.
275      */
276     static QgsGeometry fromMultiPolygonXY( const QgsMultiPolygonXY &multipoly );
277 
278     //! Creates a new geometry from a QgsRectangle
279     static QgsGeometry fromRect( const QgsRectangle &rect ) SIP_HOLDGIL;
280     //! Creates a new multipart geometry from a list of QgsGeometry objects
281     static QgsGeometry collectGeometry( const QVector<QgsGeometry> &geometries );
282 
283     /**
284      * Creates a wedge shaped buffer from a \a center point.
285      *
286      * The \a azimuth gives the angle (in degrees) for the middle of the wedge to point.
287      * The buffer width (in degrees) is specified by the \a angularWidth parameter. Note that the
288      * wedge will extend to half of the \a angularWidth either side of the \a azimuth direction.
289      *
290      * The outer radius of the buffer is specified via \a outerRadius, and optionally an
291      * \a innerRadius can also be specified.
292      *
293      * The returned geometry will be a CurvePolygon geometry containing circular strings. It may
294      * need to be segmentized to convert to a standard Polygon geometry.
295      *
296      * \since QGIS 3.2
297      */
298     static QgsGeometry createWedgeBuffer( const QgsPoint &center, double azimuth, double angularWidth,
299                                           double outerRadius, double innerRadius = 0 );
300 
301     /**
302      * Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
303      * This class will take ownership of the buffer.
304      * \note not available in Python bindings
305      */
306     void fromWkb( unsigned char *wkb, int length ) SIP_SKIP;
307 
308     /**
309      * Set the geometry, feeding in the buffer containing OGC Well-Known Binary
310      * \since QGIS 3.0
311      */
312     void fromWkb( const QByteArray &wkb );
313 
314     /**
315      * Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
316      * \see type
317      */
318     QgsWkbTypes::Type wkbType() const SIP_HOLDGIL;
319 
320     /**
321      * Returns type of the geometry as a QgsWkbTypes::GeometryType
322      * \see wkbType
323      */
324     QgsWkbTypes::GeometryType type() const SIP_HOLDGIL;
325 
326     /**
327      * Returns TRUE if the geometry is empty (eg a linestring with no vertices,
328      * or a collection with no geometries). A null geometry will always
329      * return TRUE for isEmpty().
330      * \see isNull()
331      */
332     bool isEmpty() const;
333 
334     //! Returns TRUE if WKB of the geometry is of WKBMulti* type
335     bool isMultipart() const SIP_HOLDGIL;
336 
337     /**
338      * Test if this geometry is exactly equal to another \a geometry.
339      *
340      * This is a strict equality check, where the underlying geometries must
341      * have exactly the same type, component vertices and vertex order.
342      *
343      * Calling this method is dramatically faster than the topological
344      * equality test performed by isGeosEqual().
345      *
346      * \note Comparing two null geometries will return FALSE.
347      *
348      * \see isGeosEqual()
349      * \since QGIS 1.5
350      */
351     bool equals( const QgsGeometry &geometry ) const;
352 
353     /**
354      * Compares the geometry with another geometry using GEOS.
355      *
356      * This method performs a slow, topological check, where geometries
357      * are considered equal if all of the their component edges overlap. E.g.
358      * lines with the same vertex locations but opposite direction will be
359      * considered equal by this method.
360      *
361      * Consider using the much faster, stricter equality test performed
362      * by equals() instead.
363      *
364      * \note Comparing two null geometries will return FALSE.
365      *
366      * \see equals()
367      * \since QGIS 1.5
368      */
369     bool isGeosEqual( const QgsGeometry & ) const;
370 
371     /**
372      * Checks validity of the geometry using GEOS.
373      *
374      * The \a flags parameter indicates optional flags which control the type of validity checking performed.
375      *
376      * \since QGIS 1.5
377      */
378     bool isGeosValid( Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
379 
380     /**
381      * Determines whether the geometry is simple (according to OGC definition),
382      * i.e. it has no anomalous geometric points, such as self-intersection or self-tangency.
383      * Uses GEOS library for the test.
384      * \note This is useful mainly for linestrings and linear rings. Polygons are simple by definition,
385      * for checking anomalies in polygon geometries one can use isGeosValid().
386      * \since QGIS 3.0
387      */
388     bool isSimple() const;
389 
390     /**
391      * Returns TRUE if the geometry is a polygon that is almost an axis-parallel rectangle.
392      *
393      * The \a maximumDeviation argument specifes the maximum angle (in degrees) that the polygon edges
394      * are allowed to deviate from axis parallel lines.
395      *
396      * By default the check will permit polygons with more than 4 edges, so long as the overall shape of
397      * the polygon is an axis-parallel rectangle (i.e. it is tolerant to rectangles with additional vertices
398      * added along the rectangle sides). If \a simpleRectanglesOnly is set to TRUE then the method will
399      * only return TRUE if the geometry is a simple rectangle consisting of 4 edges.
400      *
401      * \since QGIS 3.20
402      */
403     bool isAxisParallelRectangle( double maximumDeviation, bool simpleRectanglesOnly = false ) const;
404 
405     /**
406      * Returns the planar, 2-dimensional area of the geometry.
407      *
408      * \warning QgsGeometry objects are inherently Cartesian/planar geometries, and the area
409      * returned by this method is calculated using strictly Cartesian mathematics. In contrast,
410      * the QgsDistanceArea class exposes methods for calculating the areas of geometries using
411      * geodesic calculations which account for the curvature of the Earth (or any other
412      * celestial body).
413      *
414      * \see length()
415      * \since QGIS 1.5
416      */
417     double area() const;
418 
419     /**
420      * Returns the planar, 2-dimensional length of geometry.
421      *
422      * \warning QgsGeometry objects are inherently Cartesian/planar geometries, and the length
423      * returned by this method is calculated using strictly Cartesian mathematics. In contrast,
424      * the QgsDistanceArea class exposes methods for calculating the lengths of geometries using
425      * geodesic calculations which account for the curvature of the Earth (or any other
426      * celestial body).
427      *
428      * \see area()
429      * \since QGIS 1.5
430      */
431     double length() const;
432 
433     /**
434      * Returns the minimum distance between this geometry and another geometry.
435      * Will return a negative value if either geometry is empty or null.
436      *
437      * \warning QgsGeometry objects are inherently Cartesian/planar geometries, and the distance
438      * returned by this method is calculated using strictly Cartesian mathematics.
439      */
440     double distance( const QgsGeometry &geom ) const;
441 
442 #ifndef SIP_RUN
443 
444     // TODO QGIS 4: consider renaming vertices_begin, vertices_end, parts_begin, parts_end, etc
445     // to camelCase
446 
447     /**
448      * Returns STL-style iterator pointing to the first vertex of the geometry
449      * \since QGIS 3.0
450      */
451     QgsAbstractGeometry::vertex_iterator vertices_begin() const;
452 
453     /**
454      * Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry
455      * \since QGIS 3.0
456      */
457     QgsAbstractGeometry::vertex_iterator vertices_end() const;
458 #endif
459 
460     /**
461      * Returns a read-only, Java-style iterator for traversal of vertices of all the geometry, including all geometry parts and rings.
462      *
463      * \warning The iterator returns a copy of individual vertices, and accordingly geometries cannot be
464      * modified using the iterator. See transformVertices() for a safe method to modify vertices "in-place".
465      *
466      * ### Example
467      *
468      * \code{.py}
469      *   # print the x and y coordinate for each vertex in a LineString
470      *   geometry = QgsGeometry.fromWkt( 'LineString( 0 0, 1 1, 2 2)' )
471      *   for v in geometry.vertices():
472      *       print(v.x(), v.y())
473      *
474      *   # vertex iteration includes all parts and rings
475      *   geometry = QgsGeometry.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)))' )
476      *   for v in geometry.vertices():
477      *       print(v.x(), v.y())
478      * \endcode
479      *
480      * \see parts()
481      * \since QGIS 3.0
482      */
483     QgsVertexIterator vertices() const;
484 
485 #ifndef SIP_RUN
486 
487     /**
488      * Returns STL-style iterator pointing to the first part of the geometry.
489      *
490      * This method forces a detach. Use const_parts_begin() to avoid the detach
491      * if the parts are not going to be modified.
492      *
493      * \since QGIS 3.6
494      */
495     QgsAbstractGeometry::part_iterator parts_begin();
496 
497     /**
498      * Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
499      *
500      * This method forces a detach. Use const_parts_begin() to avoid the detach
501      * if the parts are not going to be modified.
502      *
503      * \since QGIS 3.6
504      */
505     QgsAbstractGeometry::part_iterator parts_end();
506 
507     /**
508      * Returns STL-style const iterator pointing to the first part of the geometry.
509      *
510      * This method avoids a detach and is more efficient then parts_begin() for read
511      * only iteration.
512      *
513      * \since QGIS 3.6
514      */
515     QgsAbstractGeometry::const_part_iterator const_parts_begin() const;
516 
517     /**
518      * Returns STL-style iterator pointing to the imaginary part after the last part of the geometry.
519      *
520      * This method avoids a detach and is more efficient then parts_end() for read
521      * only iteration.
522      *
523      * \since QGIS 3.6
524      */
525     QgsAbstractGeometry::const_part_iterator const_parts_end() const;
526 #endif
527 
528     /**
529      * Returns Java-style iterator for traversal of parts of the geometry. This iterator
530      * can safely be used to modify parts of the geometry.
531      *
532      * This method forces a detach. Use constParts() to avoid the detach
533      * if the parts are not going to be modified.
534      *
535      * ### Example
536      *
537      * \code{.py}
538      *   # print the WKT representation of each part in a multi-point geometry
539      *   geometry = QgsGeometry.fromWkt( 'MultiPoint( 0 0, 1 1, 2 2)' )
540      *   for part in geometry.parts():
541      *       print(part.asWkt())
542      *
543      *   # single part geometries only have one part - this loop will iterate once only
544      *   geometry = QgsGeometry.fromWkt( 'LineString( 0 0, 10 10 )' )
545      *   for part in geometry.parts():
546      *       print(part.asWkt())
547      *
548      *   # parts can be modified during the iteration
549      *   geometry = QgsGeometry.fromWkt( 'MultiPoint( 0 0, 1 1, 2 2)' )
550      *   for part in geometry.parts():
551      *       part.transform(ct)
552      *
553      *   # part iteration can also be combined with vertex iteration
554      *   geometry = QgsGeometry.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)))' )
555      *   for part in geometry.parts():
556      *       for v in part.vertices():
557      *           print(v.x(), v.y())
558      *
559      * \endcode
560      *
561      * \see constParts()
562      * \see vertices()
563      * \since QGIS 3.6
564      */
565     QgsGeometryPartIterator parts();
566 
567     /**
568      * Returns Java-style iterator for traversal of parts of the geometry. This iterator
569      * returns read-only references to parts and cannot be used to modify the parts.
570      *
571      * Unlike parts(), this method does not force a detach and is more efficient if read-only
572      * iteration only is required.
573      *
574      * ### Example
575      *
576      * \code{.py}
577      *   # print the WKT representation of each part in a multi-point geometry
578      *   geometry = QgsGeometry.fromWkt( 'MultiPoint( 0 0, 1 1, 2 2)' )
579      *   for part in geometry.constParts():
580      *       print(part.asWkt())
581      *
582      *   # single part geometries only have one part - this loop will iterate once only
583      *   geometry = QgsGeometry.fromWkt( 'LineString( 0 0, 10 10 )' )
584      *   for part in geometry.constParts():
585      *       print(part.asWkt())
586      *
587      *   # part iteration can also be combined with vertex iteration
588      *   geometry = QgsGeometry.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)))' )
589      *   for part in geometry.constParts():
590      *       for v in part.vertices():
591      *           print(v.x(), v.y())
592      *
593      * \endcode
594      *
595      * \see parts()
596      * \see vertices()
597      * \since QGIS 3.6
598      */
599     QgsGeometryConstPartIterator constParts() const;
600 
601     /**
602      * Returns the Hausdorff distance between this geometry and \a geom. This is basically a measure of how similar or dissimilar 2 geometries are.
603      *
604      * This algorithm is an approximation to the standard Hausdorff distance. This approximation is exact or close enough for a large
605      * subset of useful cases. Examples of these are:
606      *
607      * - computing distance between Linestrings that are roughly parallel to each other,
608      *   and roughly equal in length. This occurs in matching linear networks.
609      * - Testing similarity of geometries.
610      *
611      * If the default approximate provided by this method is insufficient, use hausdorffDistanceDensify() instead.
612      *
613      * In case of error -1 will be returned.
614      *
615      * \see hausdorffDistanceDensify()
616      * \since QGIS 3.0
617      */
618     double hausdorffDistance( const QgsGeometry &geom ) const;
619 
620     /**
621      * Returns the Hausdorff distance between this geometry and \a geom. This is basically a measure of how similar or dissimilar 2 geometries are.
622      *
623      * This function accepts a \a densifyFraction argument. The function performs a segment
624      * densification before computing the discrete Hausdorff distance. The \a densifyFraction parameter
625      * sets the fraction by which to densify each segment. Each segment will be split into a
626      * number of equal-length subsegments, whose fraction of the total length is
627      * closest to the given fraction.
628      *
629      * This method can be used when the default approximation provided by hausdorffDistance()
630      * is not sufficient. Decreasing the \a densifyFraction parameter will make the
631      * distance returned approach the true Hausdorff distance for the geometries.
632      *
633      * In case of error -1 will be returned.
634      *
635      * \see hausdorffDistance()
636      * \since QGIS 3.0
637      */
638     double hausdorffDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const;
639 
640     /**
641      * Returns the Fréchet distance between this geometry and \a geom, restricted to discrete points for both geometries.
642      *
643      * The Fréchet distance is a measure of similarity between curves that takes into account the location and ordering of the points along the curves.
644      * Therefore it is often better than the Hausdorff distance.
645      *
646      * In case of error -1 will be returned.
647      *
648      * This method requires a QGIS build based on GEOS 3.7 or later.
649      *
650      * \throws QgsNotSupportedException on QGIS builds based on GEOS 3.6 or earlier.
651      * \see frechetDistanceDensify()
652      * \since QGIS 3.20
653      */
654     double frechetDistance( const QgsGeometry &geom ) const SIP_THROW( QgsNotSupportedException );
655 
656     /**
657      * Returns the Fréchet distance between this geometry and \a geom, restricted to discrete points for both geometries.
658      *
659      * The Fréchet distance is a measure of similarity between curves that takes into account the location and ordering of the points along the curves.
660      * Therefore it is often better than the Hausdorff distance.
661      *
662      * This function accepts a \a densifyFraction argument. The function performs a segment
663      * densification before computing the discrete Fréchet distance. The \a densifyFraction parameter
664      * sets the fraction by which to densify each segment. Each segment will be split into a
665      * number of equal-length subsegments, whose fraction of the total length is
666      * closest to the given fraction.
667      *
668      * This method can be used when the default approximation provided by frechetDistance()
669      * is not sufficient. Decreasing the \a densifyFraction parameter will make the
670      * distance returned approach the true Fréchet distance for the geometries.
671      *
672      * This method requires a QGIS build based on GEOS 3.7 or later.
673      *
674      * \throws QgsNotSupportedException on QGIS builds based on GEOS 3.6 or earlier.
675      * \see frechetDistance()
676      * \since QGIS 3.20
677      */
678     double frechetDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const SIP_THROW( QgsNotSupportedException );
679 
680     /**
681      * Returns the vertex closest to the given point, the corresponding vertex index, squared distance snap point / target point
682      * and the indices of the vertices before and after the closest vertex.
683      * \param point point to search for
684      * \param closestVertexIndex will be set to the vertex index of the closest found vertex
685      * \param previousVertexIndex will be set to the vertex index of the previous vertex from the closest one. Will be set to -1 if
686      * not present.
687      * \param nextVertexIndex will be set to the vertex index of the next vertex after the closest one. Will be set to -1 if
688      * not present.
689      * \param sqrDist will be set to the square distance between the closest vertex and the specified point
690      * \returns closest point in geometry. If not found (empty geometry), returns null point and sqrDist is negative.
691      */
692     QgsPointXY closestVertex( const QgsPointXY &point, int &closestVertexIndex SIP_OUT, int &previousVertexIndex SIP_OUT, int &nextVertexIndex SIP_OUT, double &sqrDist SIP_OUT ) const;
693 
694     /**
695      * Returns the distance along this geometry from its first vertex to the specified vertex.
696      * \param vertex vertex index to calculate distance to
697      * \returns distance to vertex (following geometry), or -1 for invalid vertex numbers
698      * \warning QgsGeometry objects are inherently Cartesian/planar geometries, and the distance
699      * returned by this method is calculated using strictly Cartesian mathematics.
700      * \since QGIS 2.16
701      */
702     double distanceToVertex( int vertex ) const;
703 
704     /**
705      * Returns the bisector angle for this geometry at the specified vertex.
706      * \param vertex vertex index to calculate bisector angle at
707      * \returns bisector angle, in radians clockwise from north
708      * \see interpolateAngle()
709      * \since QGIS 3.0
710      */
711     double angleAtVertex( int vertex ) const;
712 
713     /**
714      * Returns the indexes of the vertices before and after the given vertex index.
715      *
716      * This function takes into account the following factors:
717      *
718      * # If the given vertex index is at the end of a linestring,
719      *    the adjacent index will be -1 (for "no adjacent vertex")
720      * # If the given vertex index is at the end of a linear ring
721      *    (such as in a polygon), the adjacent index will take into
722      *    account the first vertex is equal to the last vertex (and will
723      *    skip equal vertex positions).
724      */
725     void adjacentVertices( int atVertex, int &beforeVertex SIP_OUT, int &afterVertex SIP_OUT ) const;
726 
727     /**
728      * Insert a new vertex before the given vertex index,
729      *  ring and item (first number is index 0)
730      *  If the requested vertex number (beforeVertex.back()) is greater
731      *  than the last actual vertex on the requested ring and item,
732      *  it is assumed that the vertex is to be appended instead of inserted.
733      *  Returns FALSE if atVertex does not correspond to a valid vertex
734      *  on this geometry (including if this geometry is a Point).
735      *  It is up to the caller to distinguish between
736      *  these error conditions.  (Or maybe we add another method to this
737      *  object to help make the distinction?)
738      */
739     bool insertVertex( double x, double y, int beforeVertex );
740 
741     /**
742      * Insert a new vertex before the given vertex index,
743      *  ring and item (first number is index 0)
744      *  If the requested vertex number (beforeVertex.back()) is greater
745      *  than the last actual vertex on the requested ring and item,
746      *  it is assumed that the vertex is to be appended instead of inserted.
747      *  Returns FALSE if atVertex does not correspond to a valid vertex
748      *  on this geometry (including if this geometry is a Point).
749      *  It is up to the caller to distinguish between
750      *  these error conditions.  (Or maybe we add another method to this
751      *  object to help make the distinction?)
752      */
753     bool insertVertex( const QgsPoint &point, int beforeVertex );
754 
755     /**
756      * Moves the vertex at the given position number
757      * and item (first number is index 0)
758      * to the given coordinates.
759      * Returns FALSE if atVertex does not correspond to a valid vertex
760      * on this geometry
761      */
762     bool moveVertex( double x, double y, int atVertex );
763 
764     /**
765      * Moves the vertex at the given position number
766      * and item (first number is index 0)
767      * to the given coordinates.
768      * Returns FALSE if atVertex does not correspond to a valid vertex
769      * on this geometry
770      */
771     bool moveVertex( const QgsPoint &p, int atVertex );
772 
773     /**
774      * Deletes the vertex at the given position number and item
775      * (first number is index 0)
776      * \returns FALSE if atVertex does not correspond to a valid vertex
777      * on this geometry (including if this geometry is a Point),
778      * or if the number of remaining vertices in the linestring
779      * would be less than two.
780      * It is up to the caller to distinguish between
781      * these error conditions.  (Or maybe we add another method to this
782      * object to help make the distinction?)
783      */
784     bool deleteVertex( int atVertex );
785 
786     /**
787      * Converts the vertex at the given position from/to circular
788      * \returns FALSE if atVertex does not correspond to a valid vertex
789      * on this geometry (including if this geometry is a Point),
790      * or if the specified vertex can't be converted (e.g. start/end points).
791      * \since QGIS 3.20
792      */
793     bool toggleCircularAtVertex( int atVertex );
794 
795     /**
796      * Returns coordinates of a vertex.
797      * \param atVertex index of the vertex
798      * \returns Coordinates of the vertex or empty QgsPoint on error
799      */
800     QgsPoint vertexAt( int atVertex ) const;
801 
802     /**
803      * Returns the squared Cartesian distance between the given point
804      * to the given vertex index (vertex at the given position number,
805      * ring and item (first number is index 0))
806      */
807     double sqrDistToVertexAt( QgsPointXY &point SIP_IN, int atVertex ) const;
808 
809     /**
810      * Returns the nearest (closest) point on this geometry to another geometry.
811      * \see shortestLine()
812      * \since QGIS 2.14
813      */
814     QgsGeometry nearestPoint( const QgsGeometry &other ) const;
815 
816     /**
817      * Returns the shortest line joining this geometry to another geometry.
818      * \see nearestPoint()
819      *
820      * \warning QgsGeometry objects are inherently Cartesian/planar geometries, and the line
821      * returned by this method is calculated using strictly Cartesian mathematics. See QgsDistanceArea
822      * for similar methods which account for the curvature of an ellipsoidal body such as the Earth.
823      *
824      * \since QGIS 2.14
825      */
826     QgsGeometry shortestLine( const QgsGeometry &other ) const;
827 
828     /**
829      * Searches for the closest vertex in this geometry to the given point.
830      * \param point Specifiest the point for search
831      * \param atVertex Receives index of the closest vertex
832      * \returns The squared Cartesian distance is also returned in sqrDist, negative number on error
833      */
834     double closestVertexWithContext( const QgsPointXY &point, int &atVertex SIP_OUT ) const;
835 
836     /**
837      * Searches for the closest segment of geometry to the given point
838      * \param point Specifies the point for search
839      * \param minDistPoint Receives the nearest point on the segment
840      * \param nextVertexIndex Receives index of the next vertex after the closest segment. The vertex
841      * before the closest segment is always nextVertexIndex - 1
842      * \param leftOrRightOfSegment Out: Returns if the point is located on the left or right side of the geometry ( < 0 means left, > 0 means right, 0 indicates
843      * that the test was unsuccessful, e.g. for a point exactly on the line)
844      * \param epsilon epsilon for segment snapping
845      * \returns The squared Cartesian distance is also returned in sqrDist, negative number on error
846      */
847     double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &nextVertexIndex SIP_OUT, int *leftOrRightOfSegment SIP_OUT = nullptr, double epsilon = DEFAULT_SEGMENT_EPSILON ) const;
848 
849     /**
850      * Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
851      * \param ring The ring to be added
852      * \returns OperationResult a result code: success or reason of failure
853      */
854     Qgis::GeometryOperationResult addRing( const QVector<QgsPointXY> &ring );
855 
856     /**
857      * Adds a new ring to this geometry. This makes only sense for polygon and multipolygons.
858      * \param ring The ring to be added
859      * \returns OperationResult a result code: success or reason of failure
860      */
861     Qgis::GeometryOperationResult addRing( QgsCurve *ring SIP_TRANSFER );
862 
863     /**
864      * Adds a new part to a the geometry.
865      * \param points points describing part to add
866      * \param geomType default geometry type to create if no existing geometry
867      * \returns OperationResult a result code: success or reason of failure
868      */
869     Qgis::GeometryOperationResult addPart( const QVector<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsXY );
870 
871     /**
872      * Adds a new part to a the geometry.
873      * \param points points describing part to add
874      * \param geomType default geometry type to create if no existing geometry
875      * \returns OperationResult a result code: success or reason of failure
876      */
877     Qgis::GeometryOperationResult addPart( const QgsPointSequence &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPoints );
878 
879     /**
880      * Adds a new part to this geometry.
881      * \param part part to add (ownership is transferred)
882      * \param geomType default geometry type to create if no existing geometry
883      * \returns OperationResult a result code: success or reason of failure
884      */
885     Qgis::GeometryOperationResult addPart( QgsAbstractGeometry *part SIP_TRANSFER, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry );
886 
887     /**
888      * Adds a new island polygon to a multipolygon feature
889      * \returns OperationResult a result code: success or reason of failure
890      * \note available in python bindings as addPartGeometry
891      */
892     Qgis::GeometryOperationResult addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
893 
894     /**
895      * Removes the interior rings from a (multi)polygon geometry. If the minimumAllowedArea
896      * parameter is specified then only rings smaller than this minimum
897      * area will be removed.
898      * \since QGIS 3.0
899      */
900     QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
901 
902     /**
903      * Translates this geometry by dx, dy, dz and dm.
904      * \returns OperationResult a result code: success or reason of failure
905      */
906     Qgis::GeometryOperationResult translate( double dx, double dy, double dz = 0.0, double dm = 0.0 );
907 
908     /**
909      * Transforms this geometry as described by the coordinate transform \a ct.
910      *
911      * The transformation defaults to a forward transform, but the direction can be swapped
912      * by setting the \a direction argument.
913      *
914      * By default, z-coordinates are not transformed, even if the coordinate transform
915      * includes a vertical datum transformation. To transform z-coordinates, set
916      * \a transformZ to TRUE. This requires that the z coordinates in the geometry represent
917      * height relative to the vertical datum of the source CRS (generally ellipsoidal heights)
918      * and are expressed in its vertical units (generally meters).
919      *
920      * \returns OperationResult a result code: success or reason of failure
921      */
922     Qgis::GeometryOperationResult transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward, bool transformZ = false ) SIP_THROW( QgsCsException );
923 
924     /**
925      * Transforms the x and y components of the geometry using a QTransform object \a t.
926      *
927      * Optionally, the geometry's z values can be scaled via \a zScale and translated via \a zTranslate.
928      * Similarly, m-values can be scaled via \a mScale and translated via \a mTranslate.
929      *
930      * \returns OperationResult a result code: success or reason of failure
931      */
932     Qgis::GeometryOperationResult transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
933 
934     /**
935      * Rotate this geometry around the Z axis
936      * \param rotation clockwise rotation in degrees
937      * \param center rotation center
938      * \returns OperationResult a result code: success or reason of failure
939      */
940     Qgis::GeometryOperationResult rotate( double rotation, const QgsPointXY &center );
941 
942     /**
943      * Splits this geometry according to a given line.
944      * \param splitLine the line that splits the geometry
945      * \param[out] newGeometries list of new geometries that have been created with the split
946      * \param topological TRUE if topological editing is enabled
947      * \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
948      * \param splitFeature Set to TRUE if you want to split a feature, otherwise set to FALSE to split parts
949      * \returns OperationResult a result code: success or reason of failure
950      * \deprecated since QGIS 3.12 - will be removed in QGIS 4.0. Use the variant which accepts QgsPoint objects instead of QgsPointXY.
951      */
952     Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitGeometry( const QVector<QgsPointXY> &splitLine, QVector<QgsGeometry> &newGeometries SIP_OUT, bool topological, QVector<QgsPointXY> &topologyTestPoints SIP_OUT, bool splitFeature = true ) SIP_DEPRECATED;
953 
954     /**
955      * Splits this geometry according to a given line.
956      * \param splitLine the line that splits the geometry
957      * \param[out] newGeometries list of new geometries that have been created with the ``splitLine``. If the geometry is 3D, a linear interpolation of the z value is performed on the geometry at split points, see example.
958      * \param topological TRUE if topological editing is enabled
959      * \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
960      * \param splitFeature Set to TRUE if you want to split a feature, otherwise set to FALSE to split parts
961      * fix this bug?
962      * \param skipIntersectionTest set to TRUE to skip the potentially expensive initial intersection check. Only set this flag if an intersection
963      * test has already been performed by the caller! Not available in Python bindings.
964      * \returns OperationResult a result code: success or reason of failure
965      *
966      * Example:
967      *
968      * \code{.py}
969      *  geometry = QgsGeometry.fromWkt('CompoundCurveZ ((2749546.2003820720128715 1262904.45356595050543547 100, 2749557.82053794478997588 1262920.05570670193992555 200))')
970      *  split_line = [QgsPoint(2749544.19, 1262914.79), QgsPoint(2749557.64, 1262897.30)]
971      *  result, new_geometries, point_xy = geometry.splitGeometry(split_line, False)
972      *  print(geometry.asWkt(2))
973      *  > LineStringZ (2749549.12 1262908.38 125.14, 2749557.82 1262920.06 200)
974      * \endcode
975      */
976     Qgis::GeometryOperationResult splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries SIP_OUT, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true, bool skipIntersectionTest SIP_PYARGREMOVE = false );
977 
978     /**
979      * Splits this geometry according to a given curve.
980      * \param curve the curve that splits the geometry
981      * \param[out] newGeometries list of new geometries that have been created with the ``splitLine``. If the geometry is 3D, a linear interpolation of the z value is performed on the geometry at split points, see example.
982      * \param preserveCircular whether if circular strings are preserved after splitting
983      * \param topological TRUE if topological editing is enabled
984      * \param[out] topologyTestPoints points that need to be tested for topological completeness in the dataset
985      * \param splitFeature Set to TRUE if you want to split a feature, otherwise set to FALSE to split parts
986      * \returns OperationResult a result code: success or reason of failure
987      * \since QGIS 3.16
988      */
989     Qgis::GeometryOperationResult splitGeometry( const QgsCurve *curve,  QVector<QgsGeometry> &newGeometries SIP_OUT, bool preserveCircular, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true );
990 
991     /**
992      * Replaces a part of this geometry with another line
993      * \returns OperationResult a result code: success or reason of failure
994      */
995     Qgis::GeometryOperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
996 
997     /**
998      * Changes this geometry such that it does not intersect the other geometry
999      * \param other geometry that should not be intersect
1000      * \note Not available in Python
1001      */
1002     int makeDifferenceInPlace( const QgsGeometry &other ) SIP_SKIP;
1003 
1004     /**
1005      * Returns the geometry formed by modifying this geometry such that it does not
1006      * intersect the other geometry.
1007      * \param other geometry that should not be intersect
1008      * \returns difference geometry, or empty geometry if difference could not be calculated
1009      * \since QGIS 3.0
1010      */
1011     QgsGeometry makeDifference( const QgsGeometry &other ) const;
1012 
1013     /**
1014      * Returns the bounding box of the geometry.
1015      * \see orientedMinimumBoundingBox()
1016      */
1017     QgsRectangle boundingBox() const;
1018 
1019     /**
1020      * Returns the oriented minimum bounding box for the geometry, which is the smallest (by area)
1021      * rotated rectangle which fully encompasses the geometry. The area, angle (clockwise in degrees from North),
1022      * width and height of the rotated bounding box will also be returned.
1023      *
1024      * If an error was encountered while creating the result, more information can be retrieved
1025      * by calling lastError() on the returned geometry.
1026      *
1027      * \see boundingBox()
1028      * \since QGIS 3.0
1029      */
1030     QgsGeometry orientedMinimumBoundingBox( double &area SIP_OUT, double &angle SIP_OUT, double &width SIP_OUT, double &height SIP_OUT ) const;
1031 
1032     /**
1033      * Returns the oriented minimum bounding box for the geometry, which is the smallest (by area)
1034      * rotated rectangle which fully encompasses the geometry.
1035      *
1036      * If an error was encountered while creating the result, more information can be retrieved
1037      * by calling lastError() on the returned geometry.
1038      *
1039      * \since QGIS 3.0
1040      */
1041     QgsGeometry orientedMinimumBoundingBox() const SIP_SKIP;
1042 
1043     /**
1044      * Returns the minimal enclosing circle for the geometry.
1045      * \param center Center of the minimal enclosing circle returneds
1046      * \param radius Radius of the minimal enclosing circle returned
1047      * \param segments Number of segments used to segment geometry. \see QgsEllipse::toPolygon()
1048      * \returns the minimal enclosing circle as a QGIS geometry
1049      * \since QGIS 3.0
1050      */
1051     QgsGeometry minimalEnclosingCircle( QgsPointXY &center SIP_OUT, double &radius SIP_OUT, unsigned int segments = 36 ) const;
1052 
1053     /**
1054      * Returns the minimal enclosing circle for the geometry.
1055      * \param segments Number of segments used to segment geometry. \see QgsEllipse::toPolygon()
1056      * \since QGIS 3.0
1057      */
1058     QgsGeometry minimalEnclosingCircle( unsigned int segments = 36 ) const SIP_SKIP;
1059 
1060     /**
1061      * Attempts to orthogonalize a line or polygon geometry by shifting vertices to make the geometries
1062      * angles either right angles or flat lines. This is an iterative algorithm which will loop until
1063      * either the vertices are within a specified tolerance of right angles or a set number of maximum
1064      * iterations is reached. The angle threshold parameter specifies how close to a right angle or
1065      * straight line an angle must be before it is attempted to be straightened.
1066      * \since QGIS 3.0
1067      */
1068     QgsGeometry orthogonalize( double tolerance = 1.0E-8, int maxIterations = 1000, double angleThreshold = 15.0 ) const;
1069 
1070     /**
1071      * Returns a new geometry with all points or vertices snapped to the closest point of the grid.
1072      *
1073      * If the gridified geometry could not be calculated (or was totally collapsed) an empty geometry will be returned.
1074      * Note that snapping to grid may generate an invalid geometry in some corner cases.
1075      * It can also be thought as rounding the edges and it may be useful for removing errors.
1076      * \param hSpacing Horizontal spacing of the grid (x axis). 0 to disable.
1077      * \param vSpacing Vertical spacing of the grid (y axis). 0 to disable.
1078      * \param dSpacing Depth spacing of the grid (z axis). 0 (default) to disable.
1079      * \param mSpacing Custom dimension spacing of the grid (m axis). 0 (default) to disable.
1080      * \since 3.0
1081      */
1082     QgsGeometry snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const;
1083 
1084     /**
1085      * Removes duplicate nodes from the geometry, wherever removing the nodes does not result in a
1086      * degenerate geometry.
1087      *
1088      * The \a epsilon parameter specifies the tolerance for coordinates when determining that
1089      * vertices are identical.
1090      *
1091      * By default, z values are not considered when detecting duplicate nodes. E.g. two nodes
1092      * with the same x and y coordinate but different z values will still be considered
1093      * duplicate and one will be removed. If \a useZValues is TRUE, then the z values are
1094      * also tested and nodes with the same x and y but different z will be maintained.
1095      *
1096      * Note that duplicate nodes are not tested between different parts of a multipart geometry. E.g.
1097      * a multipoint geometry with overlapping points will not be changed by this method.
1098      *
1099      * The function will return TRUE if nodes were removed, or FALSE if no duplicate nodes
1100      * were found.
1101      *
1102      * \since QGIS 3.0
1103      */
1104     bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false );
1105 
1106     /**
1107      * Returns TRUE if this geometry exactly intersects with a \a rectangle. This test is exact
1108      * and can be slow for complex geometries.
1109      *
1110      * The GEOS library is used to perform the intersection test. Geometries which are not
1111      * valid may return incorrect results.
1112      *
1113      * \see boundingBoxIntersects()
1114      */
1115     bool intersects( const QgsRectangle &rectangle ) const;
1116 
1117     /**
1118      * Returns TRUE if this geometry exactly intersects with another \a geometry. This test is exact
1119      * and can be slow for complex geometries.
1120      *
1121      * The GEOS library is used to perform the intersection test. Geometries which are not
1122      * valid may return incorrect results.
1123      *
1124      * \note For performance critical code, or when testing for intersection against many different
1125      * geometries, consider using QgsGeometryEngine instead. This approach can be many orders of magnitude
1126      * faster than calling intersects() directly. See createGeometryEngine() for details on how to use the
1127      * QgsGeometryEngine class.
1128      *
1129      * \see boundingBoxIntersects()
1130      */
1131     bool intersects( const QgsGeometry &geometry ) const;
1132 
1133     /**
1134      * Returns TRUE if the bounding box of this geometry intersects with a \a rectangle. Since this
1135      * test only considers the bounding box of the geometry, is is very fast to calculate and handles invalid
1136      * geometries.
1137      *
1138      * \see intersects()
1139      *
1140      * \since QGIS 3.0
1141      */
1142     bool boundingBoxIntersects( const QgsRectangle &rectangle ) const;
1143 
1144     /**
1145      * Returns TRUE if the bounding box of this geometry intersects with the bounding box of another \a geometry. Since this
1146      * test only considers the bounding box of the geometries, is is very fast to calculate and handles invalid
1147      * geometries.
1148      *
1149      * \see intersects()
1150      *
1151      * \since QGIS 3.0
1152      */
1153     bool boundingBoxIntersects( const QgsGeometry &geometry ) const;
1154 
1155     /**
1156      * Returns TRUE if the geometry contains the point \a p.
1157      */
1158     bool contains( const QgsPointXY *p ) const;
1159 
1160     /**
1161      * Returns TRUE if the geometry completely contains another \a geometry.
1162      *
1163      * \note For performance critical code, or when testing for contains against many different
1164      * geometries, consider using QgsGeometryEngine instead. This approach can be many orders of magnitude
1165      * faster than calling contains() directly. See createGeometryEngine() for details on how to use the
1166      * QgsGeometryEngine class.
1167      *
1168      * \since QGIS 1.5
1169      */
1170     bool contains( const QgsGeometry &geometry ) const;
1171 
1172     /**
1173      * Returns TRUE if the geometry is disjoint of another \a geometry.
1174      *
1175      * \note For performance critical code, or when testing for disjoint against many different
1176      * geometries, consider using QgsGeometryEngine instead. This approach can be many orders of magnitude
1177      * faster than calling disjoint() directly. See createGeometryEngine() for details on how to use the
1178      * QgsGeometryEngine class.
1179      *
1180      * \since QGIS 1.5
1181      */
1182     bool disjoint( const QgsGeometry &geometry ) const;
1183 
1184     /**
1185      * Returns TRUE if the geometry touches another \a geometry.
1186      *
1187      * \note For performance critical code, or when testing for touches against many different
1188      * geometries, consider using QgsGeometryEngine instead. This approach can be many orders of magnitude
1189      * faster than calling touches() directly. See createGeometryEngine() for details on how to use the
1190      * QgsGeometryEngine class.
1191      *
1192      * \since QGIS 1.5
1193      */
1194     bool touches( const QgsGeometry &geometry ) const;
1195 
1196     /**
1197      * Returns TRUE if the geometry overlaps another \a geometry.
1198      *
1199      * \note For performance critical code, or when testing for overlaps against many different
1200      * geometries, consider using QgsGeometryEngine instead. This approach can be many orders of magnitude
1201      * faster than calling overlaps() directly. See createGeometryEngine() for details on how to use the
1202      * QgsGeometryEngine class.
1203      *
1204      * \since QGIS 1.5
1205      */
1206     bool overlaps( const QgsGeometry &geometry ) const;
1207 
1208     /**
1209      * Returns TRUE if the geometry is completely within another \a geometry.
1210      *
1211      * \note For performance critical code, or when testing for within against many different
1212      * geometries, consider using QgsGeometryEngine instead. This approach can be many orders of magnitude
1213      * faster than calling within() directly. See createGeometryEngine() for details on how to use the
1214      * QgsGeometryEngine class.
1215      *
1216      * \since QGIS 1.5
1217      */
1218     bool within( const QgsGeometry &geometry ) const;
1219 
1220     /**
1221      * Returns TRUE if the geometry crosses another \a geometry.
1222      *
1223      * \note For performance critical code, or when testing for crosses against many different
1224      * geometries, consider using QgsGeometryEngine instead. This approach can be many orders of magnitude
1225      * faster than calling crosses() directly. See createGeometryEngine() for details on how to use the
1226      * QgsGeometryEngine class.
1227      *
1228      * \since QGIS 1.5
1229      */
1230     bool crosses( const QgsGeometry &geometry ) const;
1231 
1232     /**
1233      * Returns a buffer region around this geometry having the given width and with a specified number
1234      * of segments used to approximate curves
1235      *
1236      * \see singleSidedBuffer()
1237      * \see taperedBuffer()
1238      */
1239     QgsGeometry buffer( double distance, int segments ) const;
1240 
1241     /**
1242      * Returns a buffer region around the geometry, with additional style options.
1243      * \param distance    buffer distance
1244      * \param segments    for round joins, number of segments to approximate quarter-circle
1245      * \param endCapStyle end cap style
1246      * \param joinStyle   join style for corners in geometry
1247      * \param miterLimit  limit on the miter ratio used for very sharp corners (JoinStyleMiter only)
1248      *
1249      * \see singleSidedBuffer()
1250      * \see taperedBuffer()
1251      * \since QGIS 2.4
1252      */
1253     QgsGeometry buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1254 
1255     /**
1256      * Returns an offset line at a given distance and side from an input line.
1257      * \param distance    buffer distance
1258      * \param segments    for round joins, number of segments to approximate quarter-circle
1259      * \param joinStyle   join style for corners in geometry
1260      * \param miterLimit  limit on the miter ratio used for very sharp corners (JoinStyleMiter only)
1261      * \since QGIS 2.4
1262      */
1263     QgsGeometry offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1264 
1265     /**
1266      * Returns a single sided buffer for a (multi)line geometry. The buffer is only
1267      * applied to one side of the line.
1268      * \param distance buffer distance
1269      * \param segments for round joins, number of segments to approximate quarter-circle
1270      * \param side side of geometry to buffer
1271      * \param joinStyle join style for corners
1272      * \param miterLimit limit on the miter ratio used for very sharp corners
1273      * \returns buffered geometry, or an empty geometry if buffer could not be
1274      * calculated
1275      *
1276      * \see buffer()
1277      * \see taperedBuffer()
1278      * \since QGIS 3.0
1279      */
1280     QgsGeometry singleSidedBuffer( double distance, int segments, Qgis::BufferSide side,
1281                                    Qgis::JoinStyle joinStyle = Qgis::JoinStyle::Round,
1282                                    double miterLimit = 2.0 ) const;
1283 
1284     /**
1285      * Calculates a variable width buffer ("tapered buffer") for a (multi)curve geometry.
1286      *
1287      * The buffer begins at a width of \a startWidth at the start of each curve, and
1288      * ends at a width of \a endWidth. Note that unlike buffer() methods, \a startWidth
1289      * and \a endWidth are the diameter of the buffer at these points, not the radius.
1290      *
1291      * The \a segments argument specifies the number of segments to approximate quarter-circle
1292      * curves in the buffer.
1293      *
1294      * Non (multi)curve input geometries will return a null output geometry.
1295      *
1296      * \see buffer()
1297      * \see singleSidedBuffer()
1298      * \see variableWidthBufferByM()
1299      * \since QGIS 3.2
1300      */
1301     QgsGeometry taperedBuffer( double startWidth, double endWidth, int segments ) const;
1302 
1303     /**
1304      * Calculates a variable width buffer for a (multi)linestring geometry, where
1305      * the width at each node is taken from the linestring m values.
1306      *
1307      * The \a segments argument specifies the number of segments to approximate quarter-circle
1308      * curves in the buffer.
1309      *
1310      * Non (multi)linestring input geometries will return a null output geometry.
1311      *
1312      * \see buffer()
1313      * \see singleSidedBuffer()
1314      * \see taperedBuffer()
1315      * \since QGIS 3.2
1316      */
1317     QgsGeometry variableWidthBufferByM( int segments ) const;
1318 
1319     /**
1320      * Extends a (multi)line geometry by extrapolating out the start or end of the line
1321      * by a specified distance. Lines are extended using the bearing of the first or last
1322      * segment in the line.
1323      * \since QGIS 3.0
1324      */
1325     QgsGeometry extendLine( double startDistance, double endDistance ) const;
1326 
1327     //! Returns a simplified version of this geometry using a specified tolerance value
1328     QgsGeometry simplify( double tolerance ) const;
1329 
1330     /**
1331      * Returns a copy of the geometry which has been densified by adding the specified
1332      * number of extra nodes within each segment of the geometry.
1333      * If the geometry has z or m values present then these will be linearly interpolated
1334      * at the added nodes.
1335      * Curved geometry types are automatically segmentized by this routine.
1336      * \see densifyByDistance()
1337      * \since QGIS 3.0
1338      */
1339     QgsGeometry densifyByCount( int extraNodesPerSegment ) const;
1340 
1341     /**
1342      * Densifies the geometry by adding regularly placed extra nodes inside each segment
1343      * so that the maximum distance between any two nodes does not exceed the
1344      * specified \a distance.
1345      * E.g. specifying a distance 3 would cause the segment [0 0] -> [10 0]
1346      * to be converted to [0 0] -> [2.5 0] -> [5 0] -> [7.5 0] -> [10 0], since
1347      * 3 extra nodes are required on the segment and spacing these at 2.5 increments
1348      * allows them to be evenly spaced over the segment.
1349      * If the geometry has z or m values present then these will be linearly interpolated
1350      * at the added nodes.
1351      * Curved geometry types are automatically segmentized by this routine.
1352      * \see densifyByCount()
1353      * \since QGIS 3.0
1354      */
1355     QgsGeometry densifyByDistance( double distance ) const;
1356 
1357     /**
1358      * Attempts to convert a non-curved geometry into a curved geometry type (e.g.
1359      * LineString to CompoundCurve, Polygon to CurvePolygon).
1360      *
1361      * The \a distanceTolerance specifies the maximum deviation allowed between the original location
1362      * of vertices and where they would fall on the candidate curved geometry.
1363      *
1364      * This method only consider a segments as suitable for replacing with an arc if the points are all
1365      * regularly spaced on the candidate arc. The \a pointSpacingAngleTolerance parameter specifies the maximum
1366      * angular deviation (in radians) allowed when testing for regular point spacing.
1367      *
1368      * \note The API is considered EXPERIMENTAL and can be changed without a notice
1369      *
1370      * \since QGIS 3.14
1371      */
1372     QgsGeometry convertToCurves( double distanceTolerance = 1e-8, double angleTolerance = 1e-8 ) const;
1373 
1374     /**
1375      * Returns the center of mass of a geometry.
1376      *
1377      * If the input is a NULL geometry, the output will also be a NULL geometry.
1378      *
1379      * If an error was encountered while creating the result, more information can be retrieved
1380      * by calling lastError() on the returned geometry.
1381      *
1382      * \note for line based geometries, the center point of the line is returned,
1383      * and for point based geometries, the point itself is returned
1384      * \see pointOnSurface()
1385      * \see poleOfInaccessibility()
1386      */
1387     QgsGeometry centroid() const;
1388 
1389     /**
1390      * Returns a point guaranteed to lie on the surface of a geometry. While the centroid()
1391      * of a geometry may be located outside of the geometry itself (e.g., for concave shapes),
1392      * the point on surface will always be inside the geometry.
1393      *
1394      * If the input is a NULL geometry, the output will also be a NULL geometry.
1395      *
1396      * If an error was encountered while creating the result, more information can be retrieved
1397      * by calling lastError() on the returned geometry.
1398      *
1399      * \see centroid()
1400      * \see poleOfInaccessibility()
1401      */
1402     QgsGeometry pointOnSurface() const;
1403 
1404     /**
1405      * Calculates the approximate pole of inaccessibility for a surface, which is the
1406      * most distant internal point from the boundary of the surface. This function
1407      * uses the 'polylabel' algorithm (Vladimir Agafonkin, 2016), which is an iterative
1408      * approach guaranteed to find the true pole of inaccessibility within a specified
1409      * tolerance. More precise tolerances require more iterations and will take longer
1410      * to calculate.
1411      * Optionally, the distance to the polygon boundary from the pole can be stored.
1412      * \see centroid()
1413      * \see pointOnSurface()
1414      * \since QGIS 3.0
1415      */
1416     QgsGeometry poleOfInaccessibility( double precision, double *distanceToBoundary SIP_OUT = nullptr ) const;
1417 
1418     /**
1419      * Constructs the Largest Empty Circle for a set of obstacle geometries, up to a
1420      * specified tolerance.
1421      *
1422      * The Largest Empty Circle is the largest circle which has its center in the convex hull of the
1423      * obstacles (the boundary), and whose interior does not intersect with any obstacle.
1424      * The circle center is the point in the interior of the boundary which has the farthest distance from
1425      * the obstacles (up to tolerance). The circle is determined by the center point and a point lying on an
1426      * obstacle indicating the circle radius.
1427      * The implementation uses a successive-approximation technique over a grid of square cells covering the obstacles and boundary.
1428      * The grid is refined using a branch-and-bound algorithm.  Point containment and distance are computed in a performant
1429      * way by using spatial indexes.
1430      * Returns a two-point linestring, with one point at the center of the inscribed circle and the other
1431      * on the boundary of the inscribed circle.
1432      *
1433      * This method requires QGIS builds based on GEOS 3.9 or later.
1434      *
1435      * \warning the \a tolerance value must be a value greater than 0, or the algorithm may never converge on a solution
1436      *
1437      * \throws QgsNotSupportedException on QGIS builds based on GEOS 3.8 or earlier.
1438      *
1439      * \since QGIS 3.20
1440      */
1441     QgsGeometry largestEmptyCircle( double tolerance, const QgsGeometry &boundary = QgsGeometry() ) const SIP_THROW( QgsNotSupportedException );
1442 
1443     /**
1444      * Returns a linestring geometry which represents the minimum diameter of the geometry.
1445      *
1446      * The minimum diameter is defined to be the width of the smallest band that
1447      * contains the geometry, where a band is a strip of the plane defined
1448      * by two parallel lines. This can be thought of as the smallest hole that the geometry
1449      * can be moved through, with a single rotation.
1450      *
1451      * This method requires a QGIS build based on GEOS 3.6 or later.
1452      *
1453      * \throws QgsNotSupportedException on QGIS builds based on GEOS 3.5 or earlier.
1454      *
1455      * \since QGIS 3.20
1456      */
1457     QgsGeometry minimumWidth() const SIP_THROW( QgsNotSupportedException );
1458 
1459     /**
1460      * Computes the minimum clearance of a geometry.
1461      *
1462      * The minimum clearance is the smallest amount by which
1463      * a vertex could be moved to produce an invalid polygon, a non-simple linestring, or a multipoint with
1464      * repeated points.  If a geometry has a minimum clearance of 'eps', it can be said that:
1465      *
1466      * - No two distinct vertices in the geometry are separated by less than 'eps'
1467      * - No vertex is closer than 'eps' to a line segment of which it is not an endpoint.
1468      *
1469      * If the minimum clearance cannot be defined for a geometry (such as with a single point, or a multipoint
1470      * whose points are identical) a value of infinity will be returned.
1471      *
1472      * If an error occurs while calculating the clearance NaN will be returned.
1473      *
1474      * This method requires a QGIS build based on GEOS 3.6 or later.
1475      *
1476      * \throws QgsNotSupportedException on QGIS builds based on GEOS 3.5 or earlier.
1477      *
1478      * \since QGIS 3.20
1479      */
1480     double minimumClearance() const SIP_THROW( QgsNotSupportedException );
1481 
1482     /**
1483      * Returns a LineString whose endpoints define the minimum clearance of a geometry.
1484      *
1485      * If the geometry has no minimum clearance, an empty LineString will be returned.
1486      *
1487      * This method requires a QGIS build based on GEOS 3.6 or later.
1488      *
1489      * \throws QgsNotSupportedException on QGIS builds based on GEOS 3.5 or earlier.
1490      *
1491      * \since QGIS 3.20
1492      */
1493     QgsGeometry minimumClearanceLine() const SIP_THROW( QgsNotSupportedException );
1494 
1495     /**
1496      * Returns the smallest convex polygon that contains all the points in the geometry.
1497      *
1498      * If the input is a NULL geometry, the output will also be a NULL geometry.
1499      *
1500      * If an error was encountered while creating the result, more information can be retrieved
1501      * by calling lastError() on the returned geometry.
1502      */
1503     QgsGeometry convexHull() const;
1504 
1505     /**
1506      * Creates a Voronoi diagram for the nodes contained within the geometry.
1507      *
1508      * Returns the Voronoi polygons for the nodes contained within the geometry.
1509      * If \a extent is specified then it will be used as a clipping envelope for the diagram.
1510      * If no extent is set then the clipping envelope will be automatically calculated.
1511      * In either case the diagram will be clipped to the larger of the provided envelope
1512      * OR the envelope surrounding all input nodes.
1513      * The \a tolerance parameter specifies an optional snapping tolerance which can
1514      * be used to improve the robustness of the diagram calculation.
1515      * If \a edgesOnly is TRUE than line string boundary geometries will be returned
1516      * instead of polygons.
1517      * An empty geometry will be returned if the diagram could not be calculated.
1518      * \since QGIS 3.0
1519      */
1520     QgsGeometry voronoiDiagram( const QgsGeometry &extent = QgsGeometry(), double tolerance = 0.0, bool edgesOnly = false ) const;
1521 
1522     /**
1523      * Returns the Delaunay triangulation for the vertices of the geometry.
1524      * The \a tolerance parameter specifies an optional snapping tolerance which can
1525      * be used to improve the robustness of the triangulation.
1526      * If \a edgesOnly is TRUE than line string boundary geometries will be returned
1527      * instead of polygons.
1528      * An empty geometry will be returned if the diagram could not be calculated.
1529      * \since QGIS 3.0
1530      */
1531     QgsGeometry delaunayTriangulation( double tolerance = 0.0, bool edgesOnly = false ) const;
1532 
1533     /**
1534      * Returns a (Multi)LineString representing the fully noded version of a collection of linestrings.
1535      *
1536      * The noding preserves all of the input nodes, and introduces the least possible number of new nodes.
1537      * The resulting linework is dissolved (duplicate lines are removed).
1538      *
1539      * The input geometry type should be a (Multi)LineString.
1540      *
1541      * \since QGIS 3.20
1542      */
1543     QgsGeometry node() const;
1544 
1545     /**
1546      * Find paths shared between the two given lineal geometries (this and \a other).
1547      *
1548      * Returns a GeometryCollection having two elements:
1549      *
1550      * - first element is a MultiLineString containing shared paths
1551      *   having the same direction on both inputs
1552      * - second element is a MultiLineString containing shared paths
1553      *   having the opposite direction on the two inputs
1554      *
1555      * Returns a null geometry on exception.
1556      *
1557      * \since QGIS 3.20
1558      */
1559     QgsGeometry sharedPaths( const QgsGeometry &other ) const;
1560 
1561     /**
1562      * Subdivides the geometry. The returned geometry will be a collection containing subdivided parts
1563      * from the original geometry, where no part has more then the specified maximum number of nodes (\a maxNodes).
1564      *
1565      * This is useful for dividing a complex geometry into less complex parts, which are better able to be spatially
1566      * indexed and faster to perform further operations such as intersects on. The returned geometry parts may
1567      * not be valid and may contain self-intersections.
1568      *
1569      * The minimum allowed value for \a maxNodes is 8.
1570      *
1571      * Curved geometries will be segmentized before subdivision.
1572      *
1573      * If the input is a NULL geometry, the output will also be a NULL geometry.
1574      *
1575      * If an error was encountered while creating the result, more information can be retrieved
1576      * by calling lastError() on the returned geometry.
1577      *
1578      * \since QGIS 3.0
1579      */
1580     QgsGeometry subdivide( int maxNodes = 256 ) const;
1581 
1582     /**
1583      * Returns an interpolated point on the geometry at the specified \a distance.
1584      *
1585      * If the original geometry is a polygon type, the boundary of the polygon
1586      * will be used during interpolation. If the original geometry is a point
1587      * type, a null geometry will be returned.
1588      *
1589      * If z or m values are present, the output z and m will be interpolated using
1590      * the existing vertices' z or m values.
1591      *
1592      * If the input is a NULL geometry, the output will also be a NULL geometry.
1593      *
1594      * \see lineLocatePoint()
1595      * \since QGIS 2.0
1596      */
1597     QgsGeometry interpolate( double distance ) const;
1598 
1599     /**
1600      * Returns a distance representing the location along this linestring of the closest point
1601      * on this linestring geometry to the specified point. Ie, the returned value indicates
1602      * how far along this linestring you need to traverse to get to the closest location
1603      * where this linestring comes to the specified point.
1604      * \param point point to seek proximity to
1605      * \returns distance along line, or -1 on error
1606      * \note only valid for linestring geometries
1607      * \see interpolate()
1608      * \since QGIS 3.0
1609      */
1610     double lineLocatePoint( const QgsGeometry &point ) const;
1611 
1612     /**
1613      * Returns the angle parallel to the linestring or polygon boundary at the specified distance
1614      * along the geometry. Angles are in radians, clockwise from north.
1615      * If the distance coincides precisely at a node then the average angle from the segment either side
1616      * of the node is returned.
1617      * \param distance distance along geometry
1618      * \see angleAtVertex()
1619      * \since QGIS 3.0
1620      */
1621     double interpolateAngle( double distance ) const;
1622 
1623     /**
1624      * Returns a geometry representing the points shared by this geometry and other.
1625      *
1626      * If the input is a NULL geometry, the output will also be a NULL geometry.
1627      *
1628      * If an error was encountered while creating the result, more information can be retrieved
1629      * by calling lastError() on the returned geometry.
1630      */
1631     QgsGeometry intersection( const QgsGeometry &geometry ) const;
1632 
1633     /**
1634      * Clips the geometry using the specified \a rectangle.
1635      *
1636      * Performs a fast, non-robust intersection between the geometry and
1637      * a \a rectangle. The returned geometry may be invalid.
1638      * \since QGIS 3.0
1639      */
1640     QgsGeometry clipped( const QgsRectangle &rectangle );
1641 
1642     /**
1643      * Returns a geometry representing all the points in this geometry and other (a
1644      * union geometry operation).
1645      *
1646      * If the input is a NULL geometry, the output will also be a NULL geometry.
1647      *
1648      * If an error was encountered while creating the result, more information can be retrieved
1649      * by calling lastError() on the returned geometry.
1650      *
1651      * \note this operation is not called union since its a reserved word in C++.
1652      */
1653     QgsGeometry combine( const QgsGeometry &geometry ) const;
1654 
1655     /**
1656      * Merges any connected lines in a LineString/MultiLineString geometry and
1657      * converts them to single line strings.
1658      * \returns a LineString or MultiLineString geometry, with any connected lines
1659      * joined. An empty geometry will be returned if the input geometry was not a
1660      * MultiLineString geometry.
1661      * \since QGIS 3.0
1662      */
1663     QgsGeometry mergeLines() const;
1664 
1665     /**
1666      * Returns a geometry representing the points making up this geometry that do not make up other.
1667      *
1668      * If the input is a NULL geometry, the output will also be a NULL geometry.
1669      *
1670      * If an error was encountered while creating the result, more information can be retrieved
1671      * by calling lastError() on the returned geometry.
1672      */
1673     QgsGeometry difference( const QgsGeometry &geometry ) const;
1674 
1675     /**
1676      * Returns a geometry representing the points making up this geometry that do not make up other.
1677      *
1678      * If the input is a NULL geometry, the output will also be a NULL geometry.
1679      *
1680      * If an error was encountered while creating the result, more information can be retrieved
1681      * by calling lastError() on the returned geometry.
1682      */
1683     QgsGeometry symDifference( const QgsGeometry &geometry ) const;
1684 
1685     //! Returns an extruded version of this geometry.
1686     QgsGeometry extrude( double x, double y );
1687 
1688 #ifndef SIP_RUN
1689 
1690     /**
1691      * Returns a list of \a count random points generated inside a (multi)polygon geometry
1692      * (if \a acceptPoint is specified, and restrictive, the number of points returned may
1693      * be less than \a count).
1694      *
1695      * Optionally, a specific random \a seed can be used when generating points. If \a seed
1696      * is 0, then a completely random sequence of points will be generated.
1697      *
1698      * If the source geometry is not a (multi)polygon, an empty list will be returned.
1699      *
1700      * The optional \a feedback argument can be used to provide cancellation support during
1701      * the point generation.
1702      *
1703      * The \a acceptPoint function is used to filter result candidates. If the function returns
1704      * FALSE, then the point will not be accepted and another candidate generated.
1705      *
1706      * When \a acceptPoint is specified, \a maxTriesPerPoint defines how many attempts to make
1707      * before giving up generating a point.
1708      *
1709      * \since QGIS 3.10
1710      */
1711     QVector< QgsPointXY > randomPointsInPolygon( int count, const std::function< bool( const QgsPointXY & ) > &acceptPoint, unsigned long seed = 0, QgsFeedback *feedback = nullptr, int maxTriesPerPoint = 0 ) const;
1712 
1713     /**
1714      * Returns a list of \a count random points generated inside a (multi)polygon geometry.
1715      *
1716      * Optionally, a specific random \a seed can be used when generating points. If \a seed
1717      * is 0, then a completely random sequence of points will be generated.
1718      *
1719      * If the source geometry is not a (multi)polygon, an empty list will be returned.
1720      *
1721      * The optional \a feedback argument can be used to provide cancellation support during
1722      * the point generation.
1723      *
1724      * \since QGIS 3.10
1725      */
1726     QVector< QgsPointXY > randomPointsInPolygon( int count, unsigned long seed = 0, QgsFeedback *feedback = nullptr ) const;
1727     ///@cond PRIVATE
1728 #else
1729 
1730     /**
1731      * Returns a list of \a count random points generated inside a (multi)polygon geometry.
1732      *
1733      * Optionally, a specific random \a seed can be used when generating points. If \a seed
1734      * is 0, then a completely random sequence of points will be generated.
1735      *
1736      * This method works only with (multi)polygon geometry types.
1737      *
1738      * \throws TypeError if the geometry is not a polygon type
1739      * \throws ValueError if the geometry is null
1740      *
1741      * \since QGIS 3.10
1742      */
1743     SIP_PYOBJECT randomPointsInPolygon( int count, unsigned long seed = 0 ) const SIP_TYPEHINT( QgsPolylineXY );
1744     % MethodCode
1745     const QgsWkbTypes::GeometryType type = sipCpp->type();
1746     if ( sipCpp->isNull() )
1747     {
1748       PyErr_SetString( PyExc_ValueError, QStringLiteral( "Cannot generate points inside a null geometry." ).toUtf8().constData() );
1749       sipIsErr = 1;
1750     }
1751     else if ( type != QgsWkbTypes::PolygonGeometry )
1752     {
1753       PyErr_SetString( PyExc_TypeError, QStringLiteral( "Cannot generate points inside a %1 geometry. Only Polygon types are permitted." ).arg( QgsWkbTypes::displayString( sipCpp->wkbType() ) ).toUtf8().constData() );
1754       sipIsErr = 1;
1755     }
1756     else
1757     {
1758       const sipTypeDef *qvector_type = sipFindType( "QVector<QgsPointXY>" );
1759       sipRes = sipConvertFromNewType( new QVector< QgsPointXY >( sipCpp->randomPointsInPolygon( a0, a1 ) ), qvector_type, Py_None );
1760     }
1761     % End
1762 
1763 
1764 #endif
1765 ///@endcond
1766 
1767     /**
1768      * Returns the length of the QByteArray returned by asWkb()
1769      *
1770      * The optional \a flags argument specifies flags controlling WKB export behavior
1771      *
1772      * \since QGIS 3.16
1773      */
1774     int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1775 
1776     /**
1777      * Export the geometry to WKB
1778      *
1779      * The optional \a flags argument specifies flags controlling WKB export behavior (since QGIS 3.14).
1780      *
1781      * \since QGIS 3.0
1782      */
1783     QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1784 
1785     /**
1786      * Exports the geometry to WKT
1787      * \returns TRUE in case of success and FALSE else
1788      * \note precision parameter added in QGIS 2.4
1789      */
1790     QString asWkt( int precision = 17 ) const;
1791 
1792 #ifdef SIP_RUN
1793     SIP_PYOBJECT __repr__();
1794     % MethodCode
1795     QString str;
1796     if ( sipCpp->isNull() )
1797       str = QStringLiteral( "<QgsGeometry: null>" );
1798     else
1799     {
1800       QString wkt = sipCpp->asWkt();
1801       if ( wkt.length() > 1000 )
1802         wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
1803       str = QStringLiteral( "<QgsGeometry: %1>" ).arg( wkt );
1804     }
1805     sipRes = PyUnicode_FromString( str.toUtf8().constData() );
1806     % End
1807 #endif
1808 
1809     /**
1810      * Exports the geometry to a GeoJSON string.
1811      */
1812     QString asJson( int precision = 17 ) const;
1813 
1814     /**
1815      * Exports the geometry to a json object.
1816      * \note not available in Python bindings
1817      * \since QGIS 3.8
1818      */
1819     virtual json asJsonObject( int precision = 17 ) const SIP_SKIP;
1820 
1821     /**
1822      * Attempts to coerce this geometry into the specified destination \a type.
1823      *
1824      * This method will do anything possible to force the current geometry into the specified type. E.g.
1825      *
1826      * - lines or polygons will be converted to points by return either a single multipoint geometry or multiple
1827      *   single point geometries.
1828      * - polygons will be converted to lines by extracting their exterior and interior rings, returning
1829      *   either a multilinestring or multiple single line strings as dictated by \a type.
1830      * - lines will be converted to polygon rings if \a type is a polygon type
1831      * - curved geometries will be segmented if \a type is non-curved.
1832      * - multi geometries will be converted to a list of single geometries
1833      * - single geometries will be upgraded to multi geometries
1834      * - z or m values will be added or dropped as required.
1835      *
1836      * \note This method is much stricter than convertToType(), as it considers the exact WKB type
1837      * of geometries instead of the geometry family (point/line/polygon), and tries more exhaustively
1838      * to coerce geometries to the desired \a type. It also correctly maintains curves and z/m values
1839      * wherever appropriate.
1840      *
1841      * \since QGIS 3.14
1842      */
1843     QVector< QgsGeometry > coerceToType( QgsWkbTypes::Type type ) const;
1844 
1845     /**
1846      * Try to convert the geometry to the requested type
1847      * \param destType the geometry type to be converted to
1848      * \param destMultipart determines if the output geometry will be multipart or not
1849      * \returns the converted geometry or NULLPTR if the conversion fails.
1850      *
1851      * \note The coerceToType() method applies much stricter and more exhaustive attempts to convert
1852      * between geometry types, and is recommended instead of this method. This method force drops
1853      * curves and any z or m values present in the geometry.
1854      *
1855      * \since QGIS 2.2
1856      */
1857     QgsGeometry convertToType( QgsWkbTypes::GeometryType destType, bool destMultipart = false ) const;
1858 
1859     /* Accessor functions for getting geometry data */
1860 
1861 #ifndef SIP_RUN
1862 
1863     /**
1864      * Returns the contents of the geometry as a 2-dimensional point.
1865      *
1866      * Any z or m values present in the geometry will be discarded.
1867      *
1868      * \warning If the geometry is not a single-point type, an empty QgsPointXY() will be returned.
1869      */
1870     QgsPointXY asPoint() const;
1871 #else
1872 
1873     /**
1874      * Returns the contents of the geometry as a 2-dimensional point.
1875      *
1876      * Any z or m values present in the geometry will be discarded.
1877      *
1878      * This method works only with single-point geometry types.
1879      *
1880      * \throws TypeError if the geometry is not a single-point type
1881      * \throws ValueError if the geometry is null
1882      */
1883     SIP_PYOBJECT asPoint() const SIP_TYPEHINT( QgsPointXY );
1884     % MethodCode
1885     const QgsWkbTypes::Type type = sipCpp->wkbType();
1886     if ( sipCpp->isNull() )
1887     {
1888       PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a point." ).toUtf8().constData() );
1889       sipIsErr = 1;
1890     }
1891     else if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::Point )
1892     {
1893       PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a point. Only Point types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1894       sipIsErr = 1;
1895     }
1896     else
1897     {
1898       sipRes = sipConvertFromNewType( new QgsPointXY( sipCpp->asPoint() ), sipType_QgsPointXY, Py_None );
1899     }
1900     % End
1901 #endif
1902 
1903 #ifndef SIP_RUN
1904 
1905     /**
1906      * Returns the contents of the geometry as a polyline.
1907      *
1908      * Any z or m values present in the geometry will be discarded. If the geometry is a curved line type
1909      * (such as a CircularString), it will be automatically segmentized.
1910      *
1911      * \warning If the geometry is not a single-line (or single-curve) type, an empty list will be returned.
1912      */
1913     QgsPolylineXY asPolyline() const;
1914 #else
1915 
1916     /**
1917      * Returns the contents of the geometry as a polyline.
1918      *
1919      * Any z or m values present in the geometry will be discarded. If the geometry is a curved line type
1920      * (such as a CircularString), it will be automatically segmentized.
1921      *
1922      * This method works only with single-line (or single-curve).
1923      *
1924      * \throws TypeError if the geometry is not a single-line type
1925      * \throws ValueError if the geometry is null
1926      */
1927     SIP_PYOBJECT asPolyline() const SIP_TYPEHINT( QgsPolylineXY );
1928     % MethodCode
1929     const QgsWkbTypes::Type type = sipCpp->wkbType();
1930     if ( sipCpp->isNull() )
1931     {
1932       PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polyline." ).toUtf8().constData() );
1933       sipIsErr = 1;
1934     }
1935     else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::LineGeometry || QgsWkbTypes::isMultiType( type ) )
1936     {
1937       PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a polyline. Only single line or curve types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1938       sipIsErr = 1;
1939     }
1940     else
1941     {
1942       const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
1943       sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asPolyline() ), qvector_type, Py_None );
1944     }
1945     % End
1946 #endif
1947 
1948 #ifndef SIP_RUN
1949 
1950     /**
1951      * Returns the contents of the geometry as a polygon.
1952      *
1953      * Any z or m values present in the geometry will be discarded. If the geometry is a curved polygon type
1954      * (such as a CurvePolygon), it will be automatically segmentized.
1955      *
1956      * \warning If the geometry is not a single-polygon (or single-curve polygon) type, an empty list will be returned.
1957      */
1958     QgsPolygonXY asPolygon() const;
1959 #else
1960 
1961     /**
1962      * Returns the contents of the geometry as a polygon.
1963      *
1964      * Any z or m values present in the geometry will be discarded. If the geometry is a curved polygon type
1965      * (such as a CurvePolygon), it will be automatically segmentized.
1966      *
1967      * This method works only with single-polygon (or single-curve polygon) geometry types.
1968      *
1969      * \throws TypeError if the geometry is not a single-polygon type
1970      * \throws ValueError if the geometry is null
1971      */
1972     SIP_PYOBJECT asPolygon() const SIP_TYPEHINT( QgsPolygonXY );
1973     % MethodCode
1974     const QgsWkbTypes::Type type = sipCpp->wkbType();
1975     if ( sipCpp->isNull() )
1976     {
1977       PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polygon." ).toUtf8().constData() );
1978       sipIsErr = 1;
1979     }
1980     else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::PolygonGeometry || QgsWkbTypes::isMultiType( type ) )
1981     {
1982       PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a polygon. Only single polygon or curve polygon types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1983       sipIsErr = 1;
1984     }
1985     else
1986     {
1987       const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
1988       sipRes = sipConvertFromNewType( new QgsPolygonXY( sipCpp->asPolygon() ), qvector_type, Py_None );
1989     }
1990     % End
1991 #endif
1992 
1993 #ifndef SIP_RUN
1994 
1995     /**
1996      * Returns the contents of the geometry as a multi-point.
1997      *
1998      * Any z or m values present in the geometry will be discarded.
1999      *
2000      * \warning If the geometry is not a multi-point type, an empty list will be returned.
2001      */
2002     QgsMultiPointXY asMultiPoint() const;
2003 #else
2004 
2005     /**
2006      * Returns the contents of the geometry as a multi-point.
2007      *
2008      * Any z or m values present in the geometry will be discarded.
2009      *
2010      * This method works only with multi-point geometry types.
2011      *
2012      * \throws TypeError if the geometry is not a multi-point type
2013      * \throws ValueError if the geometry is null
2014      */
2015     SIP_PYOBJECT asMultiPoint() const SIP_TYPEHINT( QgsMultiPointXY );
2016     % MethodCode
2017     const QgsWkbTypes::Type type = sipCpp->wkbType();
2018     if ( sipCpp->isNull() )
2019     {
2020       PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipoint." ).toUtf8().constData() );
2021       sipIsErr = 1;
2022     }
2023     else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::PointGeometry || !QgsWkbTypes::isMultiType( type ) )
2024     {
2025       PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipoint. Only multipoint types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2026       sipIsErr = 1;
2027     }
2028     else
2029     {
2030       const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
2031       sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asMultiPoint() ), qvector_type, Py_None );
2032     }
2033     % End
2034 #endif
2035 
2036 #ifndef SIP_RUN
2037 
2038     /**
2039      * Returns the contents of the geometry as a multi-linestring.
2040      *
2041      * Any z or m values present in the geometry will be discarded. If the geometry is a curved line type
2042      * (such as a MultiCurve), it will be automatically segmentized.
2043      *
2044      * \warning If the geometry is not a multi-linestring (or multi-curve linestring) type, an empty list will be returned.
2045      */
2046     QgsMultiPolylineXY asMultiPolyline() const;
2047 #else
2048 
2049     /**
2050      * Returns the contents of the geometry as a multi-linestring.
2051      *
2052      * Any z or m values present in the geometry will be discarded. If the geometry is a curved line type
2053      * (such as a MultiCurve), it will be automatically segmentized.
2054      *
2055      * This method works only with multi-linestring (or multi-curve) geometry types.
2056      *
2057      * \throws TypeError if the geometry is not a multi-linestring type
2058      * \throws ValueError if the geometry is null
2059      */
2060     SIP_PYOBJECT asMultiPolyline() const SIP_TYPEHINT( QgsMultiPolylineXY );
2061     % MethodCode
2062     const QgsWkbTypes::Type type = sipCpp->wkbType();
2063     if ( sipCpp->isNull() )
2064     {
2065       PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multilinestring." ).toUtf8().constData() );
2066       sipIsErr = 1;
2067     }
2068     else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::LineGeometry || !QgsWkbTypes::isMultiType( type ) )
2069     {
2070       PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multilinestring. Only multi linestring or curves are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2071       sipIsErr = 1;
2072     }
2073     else
2074     {
2075       const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
2076       sipRes = sipConvertFromNewType( new QgsMultiPolylineXY( sipCpp->asMultiPolyline() ), qvector_type, Py_None );
2077     }
2078     % End
2079 #endif
2080 
2081 #ifndef SIP_RUN
2082 
2083     /**
2084      * Returns the contents of the geometry as a multi-polygon.
2085      *
2086      * Any z or m values present in the geometry will be discarded. If the geometry is a curved polygon type
2087      * (such as a MultiSurface), it will be automatically segmentized.
2088      *
2089      * \warning If the geometry is not a multi-polygon (or multi-curve polygon) type, an empty list will be returned.
2090      */
2091     QgsMultiPolygonXY asMultiPolygon() const;
2092 #else
2093 
2094     /**
2095      * Returns the contents of the geometry as a multi-polygon.
2096      *
2097      * Any z or m values present in the geometry will be discarded. If the geometry is a curved polygon type
2098      * (such as a MultiSurface), it will be automatically segmentized.
2099      *
2100      * This method works only with multi-polygon (or multi-curve polygon) geometry types.
2101      *
2102      * \throws TypeError if the geometry is not a multi-polygon type
2103      * \throws ValueError if the geometry is null
2104      */
2105     SIP_PYOBJECT asMultiPolygon() const SIP_TYPEHINT( QgsMultiPolygonXY );
2106     % MethodCode
2107     const QgsWkbTypes::Type type = sipCpp->wkbType();
2108     if ( sipCpp->isNull() )
2109     {
2110       PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipolygon." ).toUtf8().constData() );
2111       sipIsErr = 1;
2112     }
2113     else if ( QgsWkbTypes::geometryType( type ) != QgsWkbTypes::PolygonGeometry || !QgsWkbTypes::isMultiType( type ) )
2114     {
2115       PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipolygon. Only multi polygon or curves are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2116       sipIsErr = 1;
2117     }
2118     else
2119     {
2120       const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QVector<QgsPointXY>>>" );
2121       sipRes = sipConvertFromNewType( new QgsMultiPolygonXY( sipCpp->asMultiPolygon() ), qvector_type, Py_None );
2122     }
2123     % End
2124 #endif
2125 
2126     /**
2127      * Returns contents of the geometry as a list of geometries
2128      * \since QGIS 1.1
2129      */
2130     QVector<QgsGeometry> asGeometryCollection() const;
2131 
2132     /**
2133      * Returns contents of the geometry as a QPointF if wkbType is WKBPoint,
2134      * otherwise returns a null QPointF.
2135      * \since QGIS 2.7
2136      */
2137     QPointF asQPointF() const SIP_HOLDGIL;
2138 
2139     /**
2140      * Returns contents of the geometry as a QPolygonF.
2141      *
2142      * If geometry is a linestring, then the result will be an open QPolygonF.
2143      * If the geometry is a polygon, then the result will be a closed QPolygonF
2144      * of the geometry's exterior ring.
2145      *
2146      * If the geometry is a multi-part geometry, then only the first part will
2147      * be considered when converting to a QPolygonF.
2148      *
2149      * \since QGIS 2.7
2150      */
2151     QPolygonF asQPolygonF() const SIP_HOLDGIL;
2152 
2153     /**
2154      * Deletes a ring in polygon or multipolygon.
2155      * Ring 0 is outer ring and can't be deleted.
2156      * \returns TRUE on success
2157      * \since QGIS 1.2
2158      */
2159     bool deleteRing( int ringNum, int partNum = 0 );
2160 
2161     /**
2162      * Deletes part identified by the part number
2163      * \returns TRUE on success
2164      * \since QGIS 1.2
2165      */
2166     bool deletePart( int partNum );
2167 
2168     /**
2169      * Converts single type geometry into multitype geometry
2170      * e.g. a polygon into a multipolygon geometry with one polygon
2171      * If it is already a multipart geometry, it will return TRUE and
2172      * not change the geometry.
2173      *
2174      * \returns TRUE in case of success and FALSE else
2175      */
2176     bool convertToMultiType();
2177 
2178     /**
2179      * Converts multi type geometry into single type geometry
2180      * e.g. a multipolygon into a polygon geometry. Only the first part of the
2181      * multi geometry will be retained.
2182      * If it is already a single part geometry, it will return TRUE and
2183      * not change the geometry.
2184      *
2185      * \returns TRUE in case of success and FALSE else
2186      */
2187     bool convertToSingleType();
2188 
2189     /**
2190      * Converts geometry collection to a the desired geometry type subclass (multi-point,
2191      * multi-linestring or multi-polygon). Child geometries of different type are filtered out.
2192      * Does nothing the geometry is not a geometry collection. May leave the geometry
2193      * empty if none of the child geometries match the desired type.
2194      *
2195      * \returns TRUE in case of success and FALSE else
2196      * \since QGIS 3.2
2197      */
2198     bool convertGeometryCollectionToSubclass( QgsWkbTypes::GeometryType geomType );
2199 
2200     /**
2201      * Modifies geometry to avoid intersections with the layers specified in project properties
2202      * \param avoidIntersectionsLayers list of layers to check for intersections
2203      * \param ignoreFeatures possibility to give a list of features where intersections should be ignored (not available in Python bindings)
2204      * \returns 0 in case of success,
2205      *          1 if geometry is not of polygon type,
2206      *          2 if avoid intersection would change the geometry type,
2207      *          3 at least one geometry intersected is invalid. The algorithm may not work and return the same geometry as the input. You must fix your intersecting geometries.
2208      * \since QGIS 1.5
2209      */
2210     int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
2211                             const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) );
2212 
2213     /**
2214      * Attempts to make an invalid geometry valid without losing vertices.
2215      *
2216      * Already-valid geometries are returned without further intervention.
2217      * In case of full or partial dimensional collapses, the output geometry may be a collection
2218      * of lower-to-equal dimension geometries or a geometry of lower dimension.
2219      * Single polygons may become multi-geometries in case of self-intersections.
2220      * It preserves Z values, but M values will be dropped.
2221      *
2222      * If an error was encountered during the process, more information can be retrieved
2223      * by calling lastError() on the returned geometry.
2224      *
2225      * \returns new valid QgsGeometry or null geometry on error
2226      *
2227      * \note For QGIS builds using GEOS library versions older than 3.8 this method calls
2228      * an internal fork of PostGIS' ST_MakeValid() function. For builds based on GEOS 3.8 or
2229      * later this method calls the GEOS MakeValid method directly.
2230      *
2231      * \since QGIS 3.0
2232      */
2233     QgsGeometry makeValid() const;
2234 
2235     /**
2236      * Forces geometries to respect the Right-Hand-Rule, in which the area that is bounded by a polygon
2237      * is to the right of the boundary. In particular, the exterior ring is oriented in a clockwise direction
2238      * and the interior rings in a counter-clockwise direction.
2239      *
2240      * \since QGIS 3.6
2241      */
2242     QgsGeometry forceRHR() const;
2243 
2244     /**
2245      * \ingroup core
2246      * \brief A geometry error.
2247      */
2248     class CORE_EXPORT Error
2249     {
2250       public:
Error()2251         Error()
2252           : mMessage( QStringLiteral( "none" ) )
2253         {}
2254 
Error(const QString & m)2255         explicit Error( const QString &m )
2256           : mMessage( m )
2257         {}
2258 
Error(const QString & m,const QgsPointXY & p)2259         Error( const QString &m, const QgsPointXY &p )
2260           : mMessage( m )
2261           , mLocation( p )
2262           , mHasLocation( true ) {}
2263 
2264         /**
2265          * A human readable error message containing details about the error.
2266          */
2267         QString what() const;
2268 
2269         /**
2270          * The coordinates at which the error is located and should be visualized.
2271          */
2272         QgsPointXY where() const;
2273 
2274         /**
2275          * TRUE if the location available from \see where is valid.
2276          */
2277         bool hasWhere() const;
2278 
2279 #ifdef SIP_RUN
2280         SIP_PYOBJECT __repr__();
2281         % MethodCode
2282         QString str = QStringLiteral( "<QgsGeometry.Error: %1>" ).arg( sipCpp->what() );
2283         sipRes = PyUnicode_FromString( str.toUtf8().data() );
2284         % End
2285 #endif
2286 
2287         // TODO c++20 - replace with = default
2288         bool operator==( const QgsGeometry::Error &other ) const
2289         {
2290           return other.mMessage == mMessage && other.mHasLocation == mHasLocation && other.mLocation == mLocation;
2291         }
2292 
2293       private:
2294         QString mMessage;
2295         QgsPointXY mLocation;
2296         bool mHasLocation = false;
2297     };
2298 
2299     /**
2300      * Validates geometry and produces a list of geometry errors.
2301      * The \a method argument dictates which validator to utilize.
2302      *
2303      * The \a flags parameter indicates optional flags which control the type of validity checking performed.
2304      *
2305      * \since QGIS 1.5
2306      */
2307     void validateGeometry( QVector<QgsGeometry::Error> &errors SIP_OUT, Qgis::GeometryValidationEngine method = Qgis::GeometryValidationEngine::QgisInternal, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
2308 
2309     /**
2310      * Reorganizes the geometry into a normalized form (or "canonical" form).
2311      *
2312      * Polygon rings will be rearranged so that their starting vertex is the lower left and ring orientation follows the
2313      * right hand rule, collections are ordered by geometry type, and other normalization techniques are applied. The
2314      * resultant geometry will be geometrically equivalent to the original geometry.
2315      *
2316      * \since QGIS 3.20
2317      */
2318     void normalize();
2319 
2320     /**
2321      * Compute the unary union on a list of \a geometries. May be faster than an iterative union on a set of geometries.
2322      * The returned geometry will be fully noded, i.e. a node will be created at every common intersection of the
2323      * input geometries. An empty geometry will be returned in the case of errors.
2324      */
2325     static QgsGeometry unaryUnion( const QVector<QgsGeometry> &geometries );
2326 
2327     /**
2328      * Creates a GeometryCollection geometry containing possible polygons formed from the constituent
2329      * linework of a set of \a geometries. The input geometries must be fully noded (i.e. nodes exist
2330      * at every common intersection of the geometries). The easiest way to ensure this is to first
2331      * call unaryUnion() on the set of input geometries and then pass the result to polygonize().
2332      * An empty geometry will be returned in the case of errors.
2333      * \since QGIS 3.0
2334      */
2335     static QgsGeometry polygonize( const QVector<QgsGeometry> &geometries );
2336 
2337     /**
2338      * Converts the geometry to straight line segments, if it is a curved geometry type.
2339      * \param tolerance segmentation tolerance
2340      * \param toleranceType maximum segmentation angle or maximum difference between approximation and curve
2341      * \see requiresConversionToStraightSegments
2342      * \since QGIS 2.10
2343      */
2344     void convertToStraightSegment( double tolerance = M_PI / 180., QgsAbstractGeometry::SegmentationToleranceType toleranceType = QgsAbstractGeometry::MaximumAngle );
2345 
2346     /**
2347      * Returns TRUE if the geometry is a curved geometry type which requires conversion to
2348      * display as straight line segments.
2349      * \see convertToStraightSegment
2350      * \since QGIS 2.10
2351      */
2352     bool requiresConversionToStraightSegments() const;
2353 
2354     /**
2355      * Transforms the geometry from map units to pixels in place.
2356      * \param mtp map to pixel transform
2357      * \since QGIS 2.10
2358      */
2359     void mapToPixel( const QgsMapToPixel &mtp );
2360 
2361     /**
2362      * Draws the geometry onto a QPainter
2363      * \param p destination QPainter
2364      * \since QGIS 2.10
2365      */
2366     void draw( QPainter &p ) const;
2367 
2368     /**
2369      * Calculates the vertex ID from a vertex \a number.
2370      *
2371      * If a matching vertex was found, it will be stored in \a id.
2372      *
2373      * Returns TRUE if vertex was found.
2374      *
2375      * \see vertexNrFromVertexId()
2376      * \since QGIS 2.10
2377      */
2378     bool vertexIdFromVertexNr( int number, QgsVertexId &id SIP_OUT ) const;
2379 
2380     /**
2381      * Returns the vertex number corresponding to a vertex \a id.
2382      *
2383      * The vertex numbers start at 0, so a return value of 0 corresponds
2384      * to the first vertex.
2385      *
2386      * Returns -1 if a corresponding vertex could not be found.
2387      *
2388      * \see vertexIdFromVertexNr()
2389      * \since QGIS 2.10
2390      */
2391     int vertexNrFromVertexId( QgsVertexId id ) const;
2392 
2393     /**
2394      * Returns an error string referring to the last error encountered
2395      * either when this geometry was created or when an operation
2396      * was performed on the geometry.
2397      *
2398      * \since QGIS 3.0
2399      */
2400     QString lastError() const SIP_HOLDGIL;
2401 
2402     /**
2403      * Filters the vertices from the geometry in place, removing any which do not return TRUE for the \a filter function
2404      * check. Has no effect when called on a single point geometry.
2405      *
2406      * Depending on the \a filter used, this may result in an invalid geometry.
2407      *
2408      * \note Not available in Python bindings
2409      * \since QGIS 3.2
2410      */
2411     void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) SIP_SKIP;
2412 
2413     /**
2414      * Transforms the vertices from the geometry in place, applying the \a transform function
2415      * to every vertex.
2416      *
2417      * Depending on the \a transform used, this may result in an invalid geometry.
2418      *
2419      * Transform functions are not permitted to alter the dimensionality of vertices. If
2420      * a transform which adds (or removes) z/m values is desired, first call the corresponding
2421      * addZValue() or addMValue() function to change the geometry's dimensionality and then
2422      * transform.
2423      *
2424      * \note Not available in Python bindings
2425      * \since QGIS 3.4
2426      */
2427     void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) SIP_SKIP;
2428 
2429     /**
2430      * Construct geometry from a QPointF
2431      * \param point source QPointF
2432      * \since QGIS 2.7
2433      */
2434     static QgsGeometry fromQPointF( QPointF point ) SIP_HOLDGIL;
2435 
2436     /**
2437      * Construct geometry from a QPolygonF. If the polygon is closed than
2438      * the resultant geometry will be a polygon, if it is open than the
2439      * geometry will be a polyline.
2440      * \param polygon source QPolygonF
2441      * \since QGIS 2.7
2442      */
2443     static QgsGeometry fromQPolygonF( const QPolygonF &polygon );
2444 
2445     /**
2446      * Creates a QgsPolylineXY from a QPolygonF.
2447      * \param polygon source polygon
2448      * \returns QgsPolylineXY
2449      * \see createPolygonFromQPolygonF
2450      * \deprecated use QgsGeometry::fromQPolygonF() or QgsLineString::fromQPolygonF() instead.
2451      */
2452     Q_DECL_DEPRECATED static QgsPolylineXY createPolylineFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2453 
2454     /**
2455      * Creates a QgsPolygonXYfrom a QPolygonF.
2456      * \param polygon source polygon
2457      * \returns QgsPolygon
2458      * \see createPolylineFromQPolygonF
2459      * \deprecated use QgsGeometry::fromQPolygonF() or QgsLineString::fromQPolygonF() instead.
2460      */
2461     Q_DECL_DEPRECATED static QgsPolygonXY createPolygonFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2462 
2463 #ifndef SIP_RUN
2464 
2465     /**
2466      * Compares two polylines for equality within a specified tolerance.
2467      * \param p1 first polyline
2468      * \param p2 second polyline
2469      * \param epsilon maximum difference for coordinates between the polylines
2470      * \returns TRUE if polylines have the same number of points and all
2471      * points are equal within the specified tolerance
2472      * \since QGIS 2.9
2473      */
2474     static bool compare( const QgsPolylineXY &p1, const QgsPolylineXY &p2,
2475                          double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2476 
2477     /**
2478      * Compares two polygons for equality within a specified tolerance.
2479      * \param p1 first polygon
2480      * \param p2 second polygon
2481      * \param epsilon maximum difference for coordinates between the polygons
2482      * \returns TRUE if polygons have the same number of rings, and each ring has the same
2483      * number of points and all points are equal within the specified tolerance
2484      * \since QGIS 2.9
2485      */
2486     static bool compare( const QgsPolygonXY &p1, const QgsPolygonXY &p2,
2487                          double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2488 
2489     /**
2490      * Compares two multipolygons for equality within a specified tolerance.
2491      * \param p1 first multipolygon
2492      * \param p2 second multipolygon
2493      * \param epsilon maximum difference for coordinates between the multipolygons
2494      * \returns TRUE if multipolygons have the same number of polygons, the polygons have the same number
2495      * of rings, and each ring has the same number of points and all points are equal within the specified
2496      * tolerance
2497      * \since QGIS 2.9
2498      */
2499     static bool compare( const QgsMultiPolygonXY &p1, const QgsMultiPolygonXY &p2,
2500                          double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2501 #else
2502 
2503     /**
2504      * Compares two geometry objects for equality within a specified tolerance.
2505      * The objects can be of type QgsPolylineXY, QgsPolygonXYor QgsMultiPolygon.
2506      * The 2 types should match.
2507      * \param p1 first geometry object
2508      * \param p2 second geometry object
2509      * \param epsilon maximum difference for coordinates between the objects
2510      * \returns TRUE if objects are
2511      *
2512      * - polylines and have the same number of points and all
2513      *   points are equal within the specified tolerance
2514      * - polygons and have the same number of points and all
2515      *   points are equal within the specified tolerance
2516      * - multipolygons and  have the same number of polygons, the polygons have the same number
2517      *   of rings, and each ring has the same number of points and all points are equal
2518      *   within the specified tolerance
2519      *
2520      * \since QGIS 2.9
2521      */
2522     static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2523     % MethodCode
2524     {
2525       sipRes = false;
2526       int state0;
2527       int state1;
2528       int sipIsErr = 0;
2529 
2530       if ( PyList_Check( a0 ) && PyList_Check( a1 ) &&
2531            PyList_GET_SIZE( a0 ) && PyList_GET_SIZE( a1 ) )
2532       {
2533         PyObject *o0 = PyList_GetItem( a0, 0 );
2534         PyObject *o1 = PyList_GetItem( a1, 0 );
2535         if ( o0 && o1 )
2536         {
2537           // compare polyline - polyline
2538           if ( sipCanConvertToType( o0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2539                sipCanConvertToType( o1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2540                sipCanConvertToType( a0, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2541                sipCanConvertToType( a1, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2542           {
2543             QgsPolylineXY *p0;
2544             QgsPolylineXY *p1;
2545             p0 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a0, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2546             p1 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a1, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2547             if ( sipIsErr )
2548             {
2549               sipReleaseType( p0, sipType_QVector_0100QgsPointXY, state0 );
2550               sipReleaseType( p1, sipType_QVector_0100QgsPointXY, state1 );
2551             }
2552             else
2553             {
2554               sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2555             }
2556           }
2557           else if ( PyList_Check( o0 ) && PyList_Check( o1 ) &&
2558                     PyList_GET_SIZE( o0 ) && PyList_GET_SIZE( o1 ) )
2559           {
2560             PyObject *oo0 = PyList_GetItem( o0, 0 );
2561             PyObject *oo1 = PyList_GetItem( o1, 0 );
2562             if ( oo0 && oo1 )
2563             {
2564               // compare polygon - polygon
2565               if ( sipCanConvertToType( oo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2566                    sipCanConvertToType( oo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2567                    sipCanConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2568                    sipCanConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2569               {
2570                 QgsPolygonXY *p0;
2571                 QgsPolygonXY *p1;
2572                 p0 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2573                 p1 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2574                 if ( sipIsErr )
2575                 {
2576                   sipReleaseType( p0, sipType_QVector_0600QVector_0100QgsPointXY, state0 );
2577                   sipReleaseType( p1, sipType_QVector_0600QVector_0100QgsPointXY, state1 );
2578                 }
2579                 else
2580                 {
2581                   sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2582                 }
2583               }
2584               else if ( PyList_Check( oo0 ) && PyList_Check( oo1 ) &&
2585                         PyList_GET_SIZE( oo0 ) && PyList_GET_SIZE( oo1 ) )
2586               {
2587                 PyObject *ooo0 = PyList_GetItem( oo0, 0 );
2588                 PyObject *ooo1 = PyList_GetItem( oo1, 0 );
2589                 if ( ooo0 && ooo1 )
2590                 {
2591                   // compare multipolygon - multipolygon
2592                   if ( sipCanConvertToType( ooo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2593                        sipCanConvertToType( ooo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2594                        sipCanConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2595                        sipCanConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2596                   {
2597                     QgsMultiPolygonXY *p0;
2598                     QgsMultiPolygonXY *p1;
2599                     p0 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2600                     p1 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2601                     if ( sipIsErr )
2602                     {
2603                       sipReleaseType( p0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state0 );
2604                       sipReleaseType( p1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state1 );
2605                     }
2606                     else
2607                     {
2608                       sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2609                     }
2610                   }
2611                 }
2612               }
2613             }
2614           }
2615         }
2616       }
2617     }
2618     % End
2619 #endif
2620 
2621     /**
2622      * Smooths a geometry by rounding off corners using the Chaikin algorithm. This operation
2623      * roughly doubles the number of vertices in a geometry.
2624      *
2625      * If input geometries contain Z or M values, these will also be smoothed and the output
2626      * geometry will retain the same dimensionality as the input geometry.
2627      *
2628      * \param iterations number of smoothing iterations to run. More iterations results
2629      * in a smoother geometry
2630      * \param offset fraction of line to create new vertices along, between 0 and 1.0,
2631      * e.g., the default value of 0.25 will create new vertices 25% and 75% along each line segment
2632      * of the geometry for each iteration. Smaller values result in "tighter" smoothing.
2633      * \param minimumDistance minimum segment length to apply smoothing to
2634      * \param maxAngle maximum angle at node (0-180) at which smoothing will be applied
2635      * \since QGIS 2.9
2636      */
2637     QgsGeometry smooth( unsigned int iterations = 1, double offset = 0.25,
2638                         double minimumDistance = -1.0, double maxAngle = 180.0 ) const;
2639 
2640     /**
2641      * Creates and returns a new geometry engine representing the specified \a geometry.
2642      *
2643      * A geometry engine is a low-level representation of a QgsAbstractGeometry object, optimised for use with external
2644      * geometry libraries such as GEOS.
2645      *
2646      * QgsGeometryEngine objects provide a mechanism for optimized evaluation of geometric algorithms, including spatial relationships
2647      * between geometries and operations such as buffers or clipping. QgsGeometryEngine is recommended for use in any
2648      * performance critical code instead of directly using the equivalent QgsGeometry methods such as QgsGeometry::intersects().
2649      *
2650      * Many methods available in the QgsGeometryEngine class can benefit from pre-preparing geometries. For instance, whenever
2651      * a large number of spatial relationships will be tested (such as calling intersects(), within(), etc) then the
2652      * geometry should first be prepared by calling prepareGeometry() before performing the tests.
2653      *
2654      * ### Example
2655      *
2656      * \code{.py}
2657      *   # polygon_geometry contains a complex polygon, with many vertices
2658      *   polygon_geometry = QgsGeometry.fromWkt('Polygon((...))')
2659      *
2660      *   # create a QgsGeometryEngine representation of the polygon
2661      *   polygon_geometry_engine = QgsGeometry.createGeometryEngine(polygon_geometry.constGet())
2662      *
2663      *   # since we'll be performing many intersects tests, we can speed up these tests considerably
2664      *   # by first "preparing" the geometry engine
2665      *   polygon_geometry_engine.prepareGeometry()
2666      *
2667      *   # now we are ready to quickly test intersection against many other objects
2668      *   for feature in my_layer.getFeatures():
2669      *       feature_geometry = feature.geometry()
2670      *       # test whether the feature's geometry intersects our original complex polygon
2671      *       if polygon_geometry_engine.intersects(feature_geometry.constGet()):
2672      *           print('feature intersects the polygon!')
2673      * \endcode
2674      *
2675      * QgsGeometryEngine operations are backed by the GEOS library (https://trac.osgeo.org/geos/).
2676      */
2677     static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry ) SIP_FACTORY;
2678 
2679     /**
2680      * Upgrades a point list from QgsPointXY to QgsPoint
2681      * \param input list of QgsPointXY objects to be upgraded
2682      * \param output destination for list of points converted to QgsPoint
2683      */
2684     static void convertPointList( const QVector<QgsPointXY> &input, QgsPointSequence &output );
2685 
2686     /**
2687      * Downgrades a point list from QgsPoint to QgsPointXY
2688      * \param input list of QgsPoint objects to be downgraded
2689      * \param output destination for list of points converted to QgsPointXY
2690      */
2691     static void convertPointList( const QgsPointSequence &input, QVector<QgsPointXY> &output );
2692 
2693     //! Allows direct construction of QVariants from geometry.
QVariant()2694     operator QVariant() const
2695     {
2696       return QVariant::fromValue( *this );
2697     }
2698 
2699   private:
2700 
2701     QgsGeometryPrivate *d; //implicitly shared data pointer
2702 
2703     //! Last error encountered
2704     mutable QString mLastError;
2705 
2706     /**
2707      * Detaches the private geometry container from this instance, and clones
2708      * the existing geometry ready for modification.
2709      */
2710     void detach();
2711 
2712     /**
2713      * Detaches the private geometry container from this instance, and resets it
2714      * to a new abstract geometry pointer.
2715      */
2716     void reset( std::unique_ptr< QgsAbstractGeometry > newGeometry );
2717 
2718     static void convertPolygon( const QgsPolygon &input, QgsPolygonXY &output );
2719 
2720     //! Try to convert the geometry to a point
2721     QgsGeometry convertToPoint( bool destMultipart ) const;
2722     //! Try to convert the geometry to a line
2723     QgsGeometry convertToLine( bool destMultipart ) const;
2724     //! Try to convert the geometry to a polygon
2725     QgsGeometry convertToPolygon( bool destMultipart ) const;
2726 
2727     /**
2728      * Smooths a polyline using the Chaikin algorithm
2729      * \param line line to smooth
2730      * \param iterations number of smoothing iterations to run. More iterations results
2731      * in a smoother geometry
2732      * \param offset fraction of line to create new vertices along, between 0 and 1.0,
2733      * e.g., the default value of 0.25 will create new vertices 25% and 75% along each line segment
2734      * of the geometry for each iteration. Smaller values result in "tighter" smoothing.
2735      * \param minimumDistance minimum segment length to apply smoothing to
2736      * \param maxAngle maximum angle at node (0-180) at which smoothing will be applied
2737     */
2738     std::unique_ptr< QgsLineString > smoothLine( const QgsLineString &line, unsigned int iterations = 1, double offset = 0.25,
2739         double minimumDistance = -1, double maxAngle = 180.0 ) const;
2740 
2741     /**
2742      * Smooths a polygon using the Chaikin algorithm
2743      * \param polygon polygon to smooth
2744      * \param iterations number of smoothing iterations to run. More iterations results
2745      * in a smoother geometry
2746      * \param offset fraction of segment to create new vertices along, between 0 and 1.0,
2747      * e.g., the default value of 0.25 will create new vertices 25% and 75% along each line segment
2748      * of the geometry for each iteration. Smaller values result in "tighter" smoothing.
2749      * \param minimumDistance minimum segment length to apply smoothing to
2750      * \param maxAngle maximum angle at node (0-180) at which smoothing will be applied
2751     */
2752     std::unique_ptr< QgsPolygon > smoothPolygon( const QgsPolygon &polygon, unsigned int iterations = 1, double offset = 0.25,
2753         double minimumDistance = -1, double maxAngle = 180.0 ) const;
2754 
2755 
2756     friend class QgsInternalGeometryEngine;
2757 
2758 }; // class QgsGeometry
2759 
2760 Q_DECLARE_METATYPE( QgsGeometry )
2761 
2762 //! Writes the geometry to stream out. QGIS version compatibility is not guaranteed.
2763 CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry );
2764 //! Reads a geometry from stream in into geometry. QGIS version compatibility is not guaranteed.
2765 CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry );
2766 
2767 #endif
2768