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