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