QGIS API Documentation  3.21.0-Master (909859188c)
qgsgeometry.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometry.h - Geometry (stored as Open Geospatial Consortium WKB)
3  -------------------------------------------------------------------
4 Date : 02 May 2005
5 Copyright : (C) 2005 by Brendan Morley
6 email : morb at ozemail dot com dot au
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #ifndef QGSGEOMETRY_H
17 #define QGSGEOMETRY_H
18 
19 #include <functional>
20 
21 #include <QDomDocument>
22 #include <QJsonObject>
23 #include <QSet>
24 #include <QString>
25 #include <QVector>
26 
27 #include <climits>
28 #include <limits>
29 #include <memory>
30 
31 #include "qgis_core.h"
32 #include "qgis_sip.h"
33 
34 #include "qgsabstractgeometry.h"
35 #include "qgspointxy.h"
36 #include "qgspoint.h"
37 #include "qgsfeatureid.h"
38 
39 #ifndef SIP_RUN
40 #include "json_fwd.hpp"
41 using namespace nlohmann;
42 #endif
43 
44 class QgsGeometryEngine;
45 class QgsVectorLayer;
46 class QgsMapToPixel;
47 class QPainter;
48 class QgsPolygon;
49 class QgsLineString;
50 class QgsCurve;
51 class QgsFeedback;
52 
62 typedef QVector<QgsPointXY> QgsPolylineXY;
63 
72 
74 #ifndef SIP_RUN
75 typedef QVector<QgsPolylineXY> QgsPolygonXY;
76 #else
77 typedef QVector<QVector<QgsPointXY>> QgsPolygonXY;
78 #endif
79 
81 typedef QVector<QgsPointXY> QgsMultiPointXY;
82 
84 #ifndef SIP_RUN
85 typedef QVector<QgsPolylineXY> QgsMultiPolylineXY;
86 #else
87 typedef QVector<QVector<QgsPointXY>> QgsMultiPolylineXY;
88 #endif
89 
91 #ifndef SIP_RUN
92 typedef QVector<QgsPolygonXY> QgsMultiPolygonXY;
93 #else
94 typedef QVector<QVector<QVector<QgsPointXY>>> QgsMultiPolygonXY;
95 #endif
96 
97 class QgsRectangle;
98 
99 class QgsConstWkbPtr;
100 
101 struct QgsGeometryPrivate;
102 
123 class CORE_EXPORT QgsGeometry
124 {
125  Q_GADGET
126  Q_PROPERTY( bool isNull READ isNull )
127  Q_PROPERTY( QgsWkbTypes::GeometryType type READ type )
128 
129  public:
130 
133 
135  QgsGeometry( const QgsGeometry & );
136 
141  QgsGeometry &operator=( QgsGeometry const &rhs ) SIP_SKIP;
142 
148  explicit QgsGeometry( QgsAbstractGeometry *geom SIP_TRANSFER );
149 
155  explicit QgsGeometry( std::unique_ptr< QgsAbstractGeometry > geom ) SIP_SKIP;
156 
157  virtual ~QgsGeometry();
158 
170  const QgsAbstractGeometry *constGet() const SIP_HOLDGIL;
171 
184  QgsAbstractGeometry *get();
185 
198  void set( QgsAbstractGeometry *geometry SIP_TRANSFER ) SIP_DEPRECATED;
199 
207  bool isNull() const SIP_HOLDGIL;
208 
210  static QgsGeometry fromWkt( const QString &wkt );
212  static QgsGeometry fromPointXY( const QgsPointXY &point ) SIP_HOLDGIL;
214  static QgsGeometry fromMultiPointXY( const QgsMultiPointXY &multipoint );
215 
227  static QgsGeometry fromPolylineXY( const QgsPolylineXY &polyline );
228 
238  static QgsGeometry fromPolyline( const QgsPolyline &polyline );
239 
241  static QgsGeometry fromMultiPolylineXY( const QgsMultiPolylineXY &multiline );
243  static QgsGeometry fromPolygonXY( const QgsPolygonXY &polygon );
245  static QgsGeometry fromMultiPolygonXY( const QgsMultiPolygonXY &multipoly );
247  static QgsGeometry fromRect( const QgsRectangle &rect ) SIP_HOLDGIL;
249  static QgsGeometry collectGeometry( const QVector<QgsGeometry> &geometries );
250 
266  static QgsGeometry createWedgeBuffer( const QgsPoint &center, double azimuth, double angularWidth,
267  double outerRadius, double innerRadius = 0 );
268 
274  void fromWkb( unsigned char *wkb, int length ) SIP_SKIP;
275 
280  void fromWkb( const QByteArray &wkb );
281 
286  QgsWkbTypes::Type wkbType() const SIP_HOLDGIL;
287 
292  QgsWkbTypes::GeometryType type() const SIP_HOLDGIL;
293 
300  bool isEmpty() const;
301 
303  bool isMultipart() const SIP_HOLDGIL;
304 
319  bool equals( const QgsGeometry &geometry ) const;
320 
337  bool isGeosEqual( const QgsGeometry & ) const;
338 
346  bool isGeosValid( Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
347 
356  bool isSimple() const;
357 
371  bool isAxisParallelRectangle( double maximumDeviation, bool simpleRectanglesOnly = false ) const;
372 
385  double area() const;
386 
399  double length() const;
400 
408  double distance( const QgsGeometry &geom ) const;
409 
410 #ifndef SIP_RUN
411 
412  // TODO QGIS 4: consider renaming vertices_begin, vertices_end, parts_begin, parts_end, etc
413  // to camelCase
414 
419  QgsAbstractGeometry::vertex_iterator vertices_begin() const;
420 
425  QgsAbstractGeometry::vertex_iterator vertices_end() const;
426 #endif
427 
451  QgsVertexIterator vertices() const;
452 
453 #ifndef SIP_RUN
454 
464 
474 
483  QgsAbstractGeometry::const_part_iterator const_parts_begin() const;
484 
493  QgsAbstractGeometry::const_part_iterator const_parts_end() const;
494 #endif
495 
533  QgsGeometryPartIterator parts();
534 
567  QgsGeometryConstPartIterator constParts() const;
568 
586  double hausdorffDistance( const QgsGeometry &geom ) const;
587 
606  double hausdorffDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const;
607 
622  double frechetDistance( const QgsGeometry &geom ) const SIP_THROW( QgsNotSupportedException );
623 
646  double frechetDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const SIP_THROW( QgsNotSupportedException );
647 
660  QgsPointXY closestVertex( const QgsPointXY &point, int &closestVertexIndex SIP_OUT, int &previousVertexIndex SIP_OUT, int &nextVertexIndex SIP_OUT, double &sqrDist SIP_OUT ) const;
661 
670  double distanceToVertex( int vertex ) const;
671 
679  double angleAtVertex( int vertex ) const;
680 
693  void adjacentVertices( int atVertex, int &beforeVertex SIP_OUT, int &afterVertex SIP_OUT ) const;
694 
707  bool insertVertex( double x, double y, int beforeVertex );
708 
721  bool insertVertex( const QgsPoint &point, int beforeVertex );
722 
730  bool moveVertex( double x, double y, int atVertex );
731 
739  bool moveVertex( const QgsPoint &p, int atVertex );
740 
752  bool deleteVertex( int atVertex );
753 
761  bool toggleCircularAtVertex( int atVertex );
762 
768  QgsPoint vertexAt( int atVertex ) const;
769 
775  double sqrDistToVertexAt( QgsPointXY &point SIP_IN, int atVertex ) const;
776 
782  QgsGeometry nearestPoint( const QgsGeometry &other ) const;
783 
794  QgsGeometry shortestLine( const QgsGeometry &other ) const;
795 
802  double closestVertexWithContext( const QgsPointXY &point, int &atVertex SIP_OUT ) const;
803 
815  double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &nextVertexIndex SIP_OUT, int *leftOrRightOfSegment SIP_OUT = nullptr, double epsilon = DEFAULT_SEGMENT_EPSILON ) const;
816 
822  Qgis::GeometryOperationResult addRing( const QVector<QgsPointXY> &ring );
823 
830 
837  Qgis::GeometryOperationResult addPart( const QVector<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsXY );
838 
846 
854 
860  Qgis::GeometryOperationResult addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
861 
868  QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
869 
874  Qgis::GeometryOperationResult translate( double dx, double dy, double dz = 0.0, double dm = 0.0 );
875 
891 
900  Qgis::GeometryOperationResult transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
901 
908  Qgis::GeometryOperationResult rotate( double rotation, const QgsPointXY &center );
909 
920  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;
921 
944  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 );
945 
957  Qgis::GeometryOperationResult splitGeometry( const QgsCurve *curve, QVector<QgsGeometry> &newGeometries SIP_OUT, bool preserveCircular, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true );
958 
963  Qgis::GeometryOperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
964 
970  int makeDifferenceInPlace( const QgsGeometry &other ) SIP_SKIP;
971 
979  QgsGeometry makeDifference( const QgsGeometry &other ) const;
980 
985  QgsRectangle boundingBox() const;
986 
998  QgsGeometry orientedMinimumBoundingBox( double &area SIP_OUT, double &angle SIP_OUT, double &width SIP_OUT, double &height SIP_OUT ) const;
999 
1009  QgsGeometry orientedMinimumBoundingBox() const SIP_SKIP;
1010 
1019  QgsGeometry minimalEnclosingCircle( QgsPointXY &center SIP_OUT, double &radius SIP_OUT, unsigned int segments = 36 ) const;
1020 
1026  QgsGeometry minimalEnclosingCircle( unsigned int segments = 36 ) const SIP_SKIP;
1027 
1036  QgsGeometry orthogonalize( double tolerance = 1.0E-8, int maxIterations = 1000, double angleThreshold = 15.0 ) const;
1037 
1050  QgsGeometry snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const;
1051 
1072  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false );
1073 
1083  bool intersects( const QgsRectangle &rectangle ) const;
1084 
1099  bool intersects( const QgsGeometry &geometry ) const;
1100 
1110  bool boundingBoxIntersects( const QgsRectangle &rectangle ) const;
1111 
1121  bool boundingBoxIntersects( const QgsGeometry &geometry ) const;
1122 
1126  bool contains( const QgsPointXY *p ) const;
1127 
1138  bool contains( const QgsGeometry &geometry ) const;
1139 
1150  bool disjoint( const QgsGeometry &geometry ) const;
1151 
1162  bool touches( const QgsGeometry &geometry ) const;
1163 
1174  bool overlaps( const QgsGeometry &geometry ) const;
1175 
1186  bool within( const QgsGeometry &geometry ) const;
1187 
1198  bool crosses( const QgsGeometry &geometry ) const;
1199 
1207  QgsGeometry buffer( double distance, int segments ) const;
1208 
1221  QgsGeometry buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1222 
1231  QgsGeometry offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1232 
1248  QgsGeometry singleSidedBuffer( double distance, int segments, Qgis::BufferSide side,
1249  Qgis::JoinStyle joinStyle = Qgis::JoinStyle::Round,
1250  double miterLimit = 2.0 ) const;
1251 
1269  QgsGeometry taperedBuffer( double startWidth, double endWidth, int segments ) const;
1270 
1285  QgsGeometry variableWidthBufferByM( int segments ) const;
1286 
1293  QgsGeometry extendLine( double startDistance, double endDistance ) const;
1294 
1296  QgsGeometry simplify( double tolerance ) const;
1297 
1307  QgsGeometry densifyByCount( int extraNodesPerSegment ) const;
1308 
1323  QgsGeometry densifyByDistance( double distance ) const;
1324 
1340  QgsGeometry convertToCurves( double distanceTolerance = 1e-8, double angleTolerance = 1e-8 ) const;
1341 
1355  QgsGeometry centroid() const;
1356 
1370  QgsGeometry pointOnSurface() const;
1371 
1384  QgsGeometry poleOfInaccessibility( double precision, double *distanceToBoundary SIP_OUT = nullptr ) const;
1385 
1409  QgsGeometry largestEmptyCircle( double tolerance, const QgsGeometry &boundary = QgsGeometry() ) const SIP_THROW( QgsNotSupportedException );
1410 
1425  QgsGeometry minimumWidth() const SIP_THROW( QgsNotSupportedException );
1426 
1448  double minimumClearance() const SIP_THROW( QgsNotSupportedException );
1449 
1461  QgsGeometry minimumClearanceLine() const SIP_THROW( QgsNotSupportedException );
1462 
1471  QgsGeometry convexHull() const;
1472 
1488  QgsGeometry voronoiDiagram( const QgsGeometry &extent = QgsGeometry(), double tolerance = 0.0, bool edgesOnly = false ) const;
1489 
1499  QgsGeometry delaunayTriangulation( double tolerance = 0.0, bool edgesOnly = false ) const;
1500 
1511  QgsGeometry node() const;
1512 
1527  QgsGeometry sharedPaths( const QgsGeometry &other ) const;
1528 
1548  QgsGeometry subdivide( int maxNodes = 256 ) const;
1549 
1565  QgsGeometry interpolate( double distance ) const;
1566 
1578  double lineLocatePoint( const QgsGeometry &point ) const;
1579 
1589  double interpolateAngle( double distance ) const;
1590 
1599  QgsGeometry intersection( const QgsGeometry &geometry ) const;
1600 
1608  QgsGeometry clipped( const QgsRectangle &rectangle );
1609 
1621  QgsGeometry combine( const QgsGeometry &geometry ) const;
1622 
1631  QgsGeometry mergeLines() const;
1632 
1641  QgsGeometry difference( const QgsGeometry &geometry ) const;
1642 
1651  QgsGeometry symDifference( const QgsGeometry &geometry ) const;
1652 
1654  QgsGeometry extrude( double x, double y );
1655 
1656 #ifndef SIP_RUN
1657 
1679  QVector< QgsPointXY > randomPointsInPolygon( int count, const std::function< bool( const QgsPointXY & ) > &acceptPoint, unsigned long seed = 0, QgsFeedback *feedback = nullptr, int maxTriesPerPoint = 0 ) const;
1680 
1694  QVector< QgsPointXY > randomPointsInPolygon( int count, unsigned long seed = 0, QgsFeedback *feedback = nullptr ) const;
1696 #else
1697 
1711  SIP_PYOBJECT randomPointsInPolygon( int count, unsigned long seed = 0 ) const SIP_TYPEHINT( QgsPolylineXY );
1712  % MethodCode
1713  const QgsWkbTypes::GeometryType type = sipCpp->type();
1714  if ( sipCpp->isNull() )
1715  {
1716  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Cannot generate points inside a null geometry." ).toUtf8().constData() );
1717  sipIsErr = 1;
1718  }
1719  else if ( type != QgsWkbTypes::PolygonGeometry )
1720  {
1721  PyErr_SetString( PyExc_TypeError, QStringLiteral( "Cannot generate points inside a %1 geometry. Only Polygon types are permitted." ).arg( QgsWkbTypes::displayString( sipCpp->wkbType() ) ).toUtf8().constData() );
1722  sipIsErr = 1;
1723  }
1724  else
1725  {
1726  const sipTypeDef *qvector_type = sipFindType( "QVector<QgsPointXY>" );
1727  sipRes = sipConvertFromNewType( new QVector< QgsPointXY >( sipCpp->randomPointsInPolygon( a0, a1 ) ), qvector_type, Py_None );
1728  }
1729  % End
1730 
1731 
1732 #endif
1734 
1742  int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1743 
1751  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1752 
1758  QString asWkt( int precision = 17 ) const;
1759 
1760 #ifdef SIP_RUN
1761  SIP_PYOBJECT __repr__();
1762  % MethodCode
1763  QString str;
1764  if ( sipCpp->isNull() )
1765  str = QStringLiteral( "<QgsGeometry: null>" );
1766  else
1767  {
1768  QString wkt = sipCpp->asWkt();
1769  if ( wkt.length() > 1000 )
1770  wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
1771  str = QStringLiteral( "<QgsGeometry: %1>" ).arg( wkt );
1772  }
1773  sipRes = PyUnicode_FromString( str.toUtf8().constData() );
1774  % End
1775 #endif
1776 
1780  QString asJson( int precision = 17 ) const;
1781 
1787  virtual json asJsonObject( int precision = 17 ) const SIP_SKIP;
1788 
1811  QVector< QgsGeometry > coerceToType( QgsWkbTypes::Type type ) const;
1812 
1825  QgsGeometry convertToType( QgsWkbTypes::GeometryType destType, bool destMultipart = false ) const;
1826 
1827  /* Accessor functions for getting geometry data */
1828 
1829 #ifndef SIP_RUN
1830 
1838  QgsPointXY asPoint() const;
1839 #else
1840 
1851  SIP_PYOBJECT asPoint() const SIP_TYPEHINT( QgsPointXY );
1852  % MethodCode
1853  const QgsWkbTypes::Type type = sipCpp->wkbType();
1854  if ( sipCpp->isNull() )
1855  {
1856  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a point." ).toUtf8().constData() );
1857  sipIsErr = 1;
1858  }
1859  else if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::Point )
1860  {
1861  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a point. Only Point types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1862  sipIsErr = 1;
1863  }
1864  else
1865  {
1866  sipRes = sipConvertFromNewType( new QgsPointXY( sipCpp->asPoint() ), sipType_QgsPointXY, Py_None );
1867  }
1868  % End
1869 #endif
1870 
1871 #ifndef SIP_RUN
1872 
1881  QgsPolylineXY asPolyline() const;
1882 #else
1883 
1895  SIP_PYOBJECT asPolyline() const SIP_TYPEHINT( QgsPolylineXY );
1896  % MethodCode
1897  const QgsWkbTypes::Type type = sipCpp->wkbType();
1898  if ( sipCpp->isNull() )
1899  {
1900  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polyline." ).toUtf8().constData() );
1901  sipIsErr = 1;
1902  }
1904  {
1905  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() );
1906  sipIsErr = 1;
1907  }
1908  else
1909  {
1910  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
1911  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asPolyline() ), qvector_type, Py_None );
1912  }
1913  % End
1914 #endif
1915 
1916 #ifndef SIP_RUN
1917 
1926  QgsPolygonXY asPolygon() const;
1927 #else
1928 
1940  SIP_PYOBJECT asPolygon() const SIP_TYPEHINT( QgsPolygonXY );
1941  % MethodCode
1942  const QgsWkbTypes::Type type = sipCpp->wkbType();
1943  if ( sipCpp->isNull() )
1944  {
1945  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polygon." ).toUtf8().constData() );
1946  sipIsErr = 1;
1947  }
1949  {
1950  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() );
1951  sipIsErr = 1;
1952  }
1953  else
1954  {
1955  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
1956  sipRes = sipConvertFromNewType( new QgsPolygonXY( sipCpp->asPolygon() ), qvector_type, Py_None );
1957  }
1958  % End
1959 #endif
1960 
1961 #ifndef SIP_RUN
1962 
1970  QgsMultiPointXY asMultiPoint() const;
1971 #else
1972 
1983  SIP_PYOBJECT asMultiPoint() const SIP_TYPEHINT( QgsMultiPointXY );
1984  % MethodCode
1985  const QgsWkbTypes::Type type = sipCpp->wkbType();
1986  if ( sipCpp->isNull() )
1987  {
1988  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipoint." ).toUtf8().constData() );
1989  sipIsErr = 1;
1990  }
1992  {
1993  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipoint. Only multipoint types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1994  sipIsErr = 1;
1995  }
1996  else
1997  {
1998  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
1999  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asMultiPoint() ), qvector_type, Py_None );
2000  }
2001  % End
2002 #endif
2003 
2004 #ifndef SIP_RUN
2005 
2014  QgsMultiPolylineXY asMultiPolyline() const;
2015 #else
2016 
2028  SIP_PYOBJECT asMultiPolyline() const SIP_TYPEHINT( QgsMultiPolylineXY );
2029  % MethodCode
2030  const QgsWkbTypes::Type type = sipCpp->wkbType();
2031  if ( sipCpp->isNull() )
2032  {
2033  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multilinestring." ).toUtf8().constData() );
2034  sipIsErr = 1;
2035  }
2037  {
2038  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() );
2039  sipIsErr = 1;
2040  }
2041  else
2042  {
2043  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
2044  sipRes = sipConvertFromNewType( new QgsMultiPolylineXY( sipCpp->asMultiPolyline() ), qvector_type, Py_None );
2045  }
2046  % End
2047 #endif
2048 
2049 #ifndef SIP_RUN
2050 
2059  QgsMultiPolygonXY asMultiPolygon() const;
2060 #else
2061 
2073  SIP_PYOBJECT asMultiPolygon() const SIP_TYPEHINT( QgsMultiPolygonXY );
2074  % MethodCode
2075  const QgsWkbTypes::Type type = sipCpp->wkbType();
2076  if ( sipCpp->isNull() )
2077  {
2078  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipolygon." ).toUtf8().constData() );
2079  sipIsErr = 1;
2080  }
2082  {
2083  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() );
2084  sipIsErr = 1;
2085  }
2086  else
2087  {
2088  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QVector<QgsPointXY>>>" );
2089  sipRes = sipConvertFromNewType( new QgsMultiPolygonXY( sipCpp->asMultiPolygon() ), qvector_type, Py_None );
2090  }
2091  % End
2092 #endif
2093 
2098  QVector<QgsGeometry> asGeometryCollection() const;
2099 
2105  QPointF asQPointF() const SIP_HOLDGIL;
2106 
2119  QPolygonF asQPolygonF() const SIP_HOLDGIL;
2120 
2127  bool deleteRing( int ringNum, int partNum = 0 );
2128 
2134  bool deletePart( int partNum );
2135 
2144  bool convertToMultiType();
2145 
2155  bool convertToSingleType();
2156 
2166  bool convertGeometryCollectionToSubclass( QgsWkbTypes::GeometryType geomType );
2167 
2178  int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
2179  const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) );
2180 
2201  QgsGeometry makeValid() const;
2202 
2210  QgsGeometry forceRHR() const;
2211 
2216  class CORE_EXPORT Error
2217  {
2218  public:
2220  : mMessage( QStringLiteral( "none" ) )
2221  {}
2222 
2223  explicit Error( const QString &m )
2224  : mMessage( m )
2225  {}
2226 
2227  Error( const QString &m, const QgsPointXY &p )
2228  : mMessage( m )
2229  , mLocation( p )
2230  , mHasLocation( true ) {}
2231 
2235  QString what() const;
2236 
2240  QgsPointXY where() const;
2241 
2245  bool hasWhere() const;
2246 
2247 #ifdef SIP_RUN
2248  SIP_PYOBJECT __repr__();
2249  % MethodCode
2250  QString str = QStringLiteral( "<QgsGeometry.Error: %1>" ).arg( sipCpp->what() );
2251  sipRes = PyUnicode_FromString( str.toUtf8().data() );
2252  % End
2253 #endif
2254 
2255  // TODO c++20 - replace with = default
2256  bool operator==( const QgsGeometry::Error &other ) const
2257  {
2258  return other.mMessage == mMessage && other.mHasLocation == mHasLocation && other.mLocation == mLocation;
2259  }
2260 
2261  private:
2262  QString mMessage;
2263  QgsPointXY mLocation;
2264  bool mHasLocation = false;
2265  };
2266 
2275  void validateGeometry( QVector<QgsGeometry::Error> &errors SIP_OUT, Qgis::GeometryValidationEngine method = Qgis::GeometryValidationEngine::QgisInternal, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
2276 
2286  void normalize();
2287 
2293  static QgsGeometry unaryUnion( const QVector<QgsGeometry> &geometries );
2294 
2303  static QgsGeometry polygonize( const QVector<QgsGeometry> &geometries );
2304 
2312  void convertToStraightSegment( double tolerance = M_PI / 180., QgsAbstractGeometry::SegmentationToleranceType toleranceType = QgsAbstractGeometry::MaximumAngle );
2313 
2320  bool requiresConversionToStraightSegments() const;
2321 
2327  void mapToPixel( const QgsMapToPixel &mtp );
2328 
2334  void draw( QPainter &p ) const;
2335 
2346  bool vertexIdFromVertexNr( int number, QgsVertexId &id SIP_OUT ) const;
2347 
2359  int vertexNrFromVertexId( QgsVertexId id ) const;
2360 
2368  QString lastError() const SIP_HOLDGIL;
2369 
2379  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) SIP_SKIP;
2380 
2395  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) SIP_SKIP;
2396 
2402  static QgsGeometry fromQPointF( QPointF point ) SIP_HOLDGIL;
2403 
2411  static QgsGeometry fromQPolygonF( const QPolygonF &polygon );
2412 
2420  Q_DECL_DEPRECATED static QgsPolylineXY createPolylineFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2421 
2429  Q_DECL_DEPRECATED static QgsPolygonXY createPolygonFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2430 
2431 #ifndef SIP_RUN
2432 
2442  static bool compare( const QgsPolylineXY &p1, const QgsPolylineXY &p2,
2443  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2444 
2454  static bool compare( const QgsPolygonXY &p1, const QgsPolygonXY &p2,
2455  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2456 
2467  static bool compare( const QgsMultiPolygonXY &p1, const QgsMultiPolygonXY &p2,
2468  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2469 #else
2470 
2490  static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2491  % MethodCode
2492  {
2493  sipRes = false;
2494  int state0;
2495  int state1;
2496  int sipIsErr = 0;
2497 
2498  if ( PyList_Check( a0 ) && PyList_Check( a1 ) &&
2499  PyList_GET_SIZE( a0 ) && PyList_GET_SIZE( a1 ) )
2500  {
2501  PyObject *o0 = PyList_GetItem( a0, 0 );
2502  PyObject *o1 = PyList_GetItem( a1, 0 );
2503  if ( o0 && o1 )
2504  {
2505  // compare polyline - polyline
2506  if ( sipCanConvertToType( o0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2507  sipCanConvertToType( o1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2508  sipCanConvertToType( a0, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2509  sipCanConvertToType( a1, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2510  {
2511  QgsPolylineXY *p0;
2512  QgsPolylineXY *p1;
2513  p0 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a0, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2514  p1 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a1, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2515  if ( sipIsErr )
2516  {
2517  sipReleaseType( p0, sipType_QVector_0100QgsPointXY, state0 );
2518  sipReleaseType( p1, sipType_QVector_0100QgsPointXY, state1 );
2519  }
2520  else
2521  {
2522  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2523  }
2524  }
2525  else if ( PyList_Check( o0 ) && PyList_Check( o1 ) &&
2526  PyList_GET_SIZE( o0 ) && PyList_GET_SIZE( o1 ) )
2527  {
2528  PyObject *oo0 = PyList_GetItem( o0, 0 );
2529  PyObject *oo1 = PyList_GetItem( o1, 0 );
2530  if ( oo0 && oo1 )
2531  {
2532  // compare polygon - polygon
2533  if ( sipCanConvertToType( oo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2534  sipCanConvertToType( oo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2535  sipCanConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2536  sipCanConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2537  {
2538  QgsPolygonXY *p0;
2539  QgsPolygonXY *p1;
2540  p0 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2541  p1 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2542  if ( sipIsErr )
2543  {
2544  sipReleaseType( p0, sipType_QVector_0600QVector_0100QgsPointXY, state0 );
2545  sipReleaseType( p1, sipType_QVector_0600QVector_0100QgsPointXY, state1 );
2546  }
2547  else
2548  {
2549  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2550  }
2551  }
2552  else if ( PyList_Check( oo0 ) && PyList_Check( oo1 ) &&
2553  PyList_GET_SIZE( oo0 ) && PyList_GET_SIZE( oo1 ) )
2554  {
2555  PyObject *ooo0 = PyList_GetItem( oo0, 0 );
2556  PyObject *ooo1 = PyList_GetItem( oo1, 0 );
2557  if ( ooo0 && ooo1 )
2558  {
2559  // compare multipolygon - multipolygon
2560  if ( sipCanConvertToType( ooo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2561  sipCanConvertToType( ooo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2562  sipCanConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2563  sipCanConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2564  {
2565  QgsMultiPolygonXY *p0;
2566  QgsMultiPolygonXY *p1;
2567  p0 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2568  p1 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2569  if ( sipIsErr )
2570  {
2571  sipReleaseType( p0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state0 );
2572  sipReleaseType( p1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state1 );
2573  }
2574  else
2575  {
2576  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2577  }
2578  }
2579  }
2580  }
2581  }
2582  }
2583  }
2584  }
2585  }
2586  % End
2587 #endif
2588 
2605  QgsGeometry smooth( unsigned int iterations = 1, double offset = 0.25,
2606  double minimumDistance = -1.0, double maxAngle = 180.0 ) const;
2607 
2645  static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry ) SIP_FACTORY;
2646 
2652  static void convertPointList( const QVector<QgsPointXY> &input, QgsPointSequence &output );
2653 
2659  static void convertPointList( const QgsPointSequence &input, QVector<QgsPointXY> &output );
2660 
2662  operator QVariant() const
2663  {
2664  return QVariant::fromValue( *this );
2665  }
2666 
2667  private:
2668 
2669  QgsGeometryPrivate *d; //implicitly shared data pointer
2670 
2672  mutable QString mLastError;
2673 
2678  void detach();
2679 
2684  void reset( std::unique_ptr< QgsAbstractGeometry > newGeometry );
2685 
2686  static void convertPolygon( const QgsPolygon &input, QgsPolygonXY &output );
2687 
2689  QgsGeometry convertToPoint( bool destMultipart ) const;
2691  QgsGeometry convertToLine( bool destMultipart ) const;
2693  QgsGeometry convertToPolygon( bool destMultipart ) const;
2694 
2706  std::unique_ptr< QgsLineString > smoothLine( const QgsLineString &line, unsigned int iterations = 1, double offset = 0.25,
2707  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2708 
2720  std::unique_ptr< QgsPolygon > smoothPolygon( const QgsPolygon &polygon, unsigned int iterations = 1, double offset = 0.25,
2721  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2722 
2723 
2725 
2726 }; // class QgsGeometry
2727 
2729 
2730 CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry );
2733 CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry );
2734 
2735 #endif
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:63
GeometryOperationResult
Success or failure of a geometry operation.
Definition: qgis.h:624
GeometryValidationEngine
Available engines for validating geometries.
Definition: qgis.h:663
The part_iterator class provides STL-style iterator for const references to geometry parts.
The part_iterator class provides STL-style iterator for geometry parts.
The vertex_iterator class provides STL-style iterator for vertices.
Abstract base class for all geometries.
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle.
@ MaximumAngle
Maximum angle between generating radii (lines from arc center to output vertices)
A const WKB pointer.
Definition: qgswkbptr.h:138
Class for doing transforms between two map coordinate systems.
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
@ ForwardTransform
Transform from source to destination CRS.
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:66
Abstract base class for curved geometry type.
Definition: qgscurve.h:36
Base class for feedback objects to be used for cancellation of something running in a worker thread.
Definition: qgsfeedback.h:45
Java-style iterator for const traversal of parts of a geometry.
A geometry engine is a low-level representation of a QgsAbstractGeometry object, optimised for use wi...
Java-style iterator for traversal of parts of a geometry.
A geometry error.
Definition: qgsgeometry.h:2217
Error(const QString &m)
Definition: qgsgeometry.h:2223
Error(const QString &m, const QgsPointXY &p)
Definition: qgsgeometry.h:2227
bool operator==(const QgsGeometry::Error &other) const
Definition: qgsgeometry.h:2256
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:124
QVector< QgsPointXY > randomPointsInPolygon(int count, const std::function< bool(const QgsPointXY &) > &acceptPoint, unsigned long seed=0, QgsFeedback *feedback=nullptr, int maxTriesPerPoint=0) const
Returns a list of count random points generated inside a (multi)polygon geometry (if acceptPoint is s...
QVector< QgsPointXY > randomPointsInPolygon(int count, unsigned long seed=0, QgsFeedback *feedback=nullptr) const
Returns a list of count random points generated inside a (multi)polygon geometry.
static bool compare(const QgsPolylineXY &p1, const QgsPolylineXY &p2, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compares two polylines for equality within a specified tolerance.
This class offers geometry processing methods.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:44
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:39
Custom exception class which is raised when an operation is not supported.
Definition: qgsexception.h:118
A class to represent a 2D point.
Definition: qgspointxy.h:59
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Polygon geometry type.
Definition: qgspolygon.h:34
A rectangle specified with double values.
Definition: qgsrectangle.h:42
Represents a vector layer which manages a vector based data sets.
Java-style iterator for traversal of vertices of a geometry.
Handles storage of information regarding WKB types and their properties.
Definition: qgswkbtypes.h:42
static GeometryType geometryType(Type type) SIP_HOLDGIL
Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a Polyg...
Definition: qgswkbtypes.h:938
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:832
GeometryType
The geometry types are used to group QgsWkbTypes::Type in a coarse way.
Definition: qgswkbtypes.h:141
static QString displayString(Type type) SIP_HOLDGIL
Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geom...
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:702
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored)
Definition: MathUtils.cpp:786
CORE_EXPORT QgsMeshVertex centroid(const QgsMeshFace &face, const QVector< QgsMeshVertex > &vertices)
Returns the centroid of the face.
std::unique_ptr< GEOSGeometry, GeosDeleter > unique_ptr
Scoped GEOS pointer.
Definition: qgsgeos.h:79
#define str(x)
Definition: qgis.cpp:37
const double DEFAULT_SEGMENT_EPSILON
Default snapping tolerance for segments.
Definition: qgis.h:1563
#define SIP_THROW(name)
Definition: qgis_sip.h:189
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:218
#define SIP_IN
Definition: qgis_sip.h:63
#define SIP_DEPRECATED
Definition: qgis_sip.h:106
#define SIP_SKIP
Definition: qgis_sip.h:126
#define SIP_PYNAME(name)
Definition: qgis_sip.h:81
#define SIP_PYARGREMOVE
Definition: qgis_sip.h:146
#define SIP_TRANSFER
Definition: qgis_sip.h:36
#define SIP_OUT
Definition: qgis_sip.h:58
#define SIP_HOLDGIL
Definition: qgis_sip.h:157
#define SIP_FACTORY
Definition: qgis_sip.h:76
QVector< QgsPoint > QgsPointSequence
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
Definition: qgsgeometry.h:75
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:85
CORE_EXPORT QDataStream & operator>>(QDataStream &in, QgsGeometry &geometry)
Reads a geometry from stream in into geometry. QGIS version compatibility is not guaranteed.
QVector< QgsPointXY > QgsMultiPointXY
A collection of QgsPoints that share a common collection of attributes.
Definition: qgsgeometry.h:81
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:51
CORE_EXPORT QDataStream & operator<<(QDataStream &out, const QgsGeometry &geometry)
Writes the geometry to stream out. QGIS version compatibility is not guaranteed.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
Definition: qgsgeometry.h:92
QgsPointSequence QgsPolyline
Polyline as represented as a vector of points.
Definition: qgsgeometry.h:71
Q_DECLARE_METATYPE(QgsMeshTimeSettings)
int precision
Utility class for identifying a unique vertex within a geometry.