QGIS API Documentation  3.23.0-Master (dd0cd13a00)
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 #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 
63 typedef QVector<QgsPointXY> QgsPolylineXY;
64 
73 
75 #ifndef SIP_RUN
76 typedef QVector<QgsPolylineXY> QgsPolygonXY;
77 #else
78 typedef QVector<QVector<QgsPointXY>> QgsPolygonXY;
79 #endif
80 
82 typedef QVector<QgsPointXY> QgsMultiPointXY;
83 
85 #ifndef SIP_RUN
86 typedef QVector<QgsPolylineXY> QgsMultiPolylineXY;
87 #else
88 typedef QVector<QVector<QgsPointXY>> QgsMultiPolylineXY;
89 #endif
90 
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 
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 
134 
136  QgsGeometry( const QgsGeometry & );
137 
142  QgsGeometry &operator=( QgsGeometry const &rhs ) SIP_SKIP;
143 
149  explicit QgsGeometry( QgsAbstractGeometry *geom SIP_TRANSFER );
150 
156  explicit QgsGeometry( std::unique_ptr< QgsAbstractGeometry > geom ) SIP_SKIP;
157 
158  virtual ~QgsGeometry();
159 
171  const QgsAbstractGeometry *constGet() const SIP_HOLDGIL;
172 
185  QgsAbstractGeometry *get();
186 
199  void set( QgsAbstractGeometry *geometry SIP_TRANSFER ) SIP_DEPRECATED;
200 
208  bool isNull() const SIP_HOLDGIL;
209 
211  static QgsGeometry fromWkt( const QString &wkt );
213  static QgsGeometry fromPointXY( const QgsPointXY &point ) SIP_HOLDGIL;
215  static QgsGeometry fromMultiPointXY( const QgsMultiPointXY &multipoint );
216 
228  static QgsGeometry fromPolylineXY( const QgsPolylineXY &polyline );
229 
239  static QgsGeometry fromPolyline( const QgsPolyline &polyline );
240 
244  static QgsGeometry fromMultiPolylineXY( const QgsMultiPolylineXY &multiline );
245 
246 #ifndef SIP_RUN
247 
251 #else
252 
270 #endif
271  static QgsGeometry fromPolygonXY( const QgsPolygonXY &polygon );
272 
276  static QgsGeometry fromMultiPolygonXY( const QgsMultiPolygonXY &multipoly );
277 
279  static QgsGeometry fromRect( const QgsRectangle &rect ) SIP_HOLDGIL;
281  static QgsGeometry collectGeometry( const QVector<QgsGeometry> &geometries );
282 
298  static QgsGeometry createWedgeBuffer( const QgsPoint &center, double azimuth, double angularWidth,
299  double outerRadius, double innerRadius = 0 );
300 
306  void fromWkb( unsigned char *wkb, int length ) SIP_SKIP;
307 
312  void fromWkb( const QByteArray &wkb );
313 
318  QgsWkbTypes::Type wkbType() const SIP_HOLDGIL;
319 
324  QgsWkbTypes::GeometryType type() const SIP_HOLDGIL;
325 
332  bool isEmpty() const;
333 
335  bool isMultipart() const SIP_HOLDGIL;
336 
351  bool equals( const QgsGeometry &geometry ) const;
352 
369  bool isGeosEqual( const QgsGeometry & ) const;
370 
378  bool isGeosValid( Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
379 
388  bool isSimple() const;
389 
403  bool isAxisParallelRectangle( double maximumDeviation, bool simpleRectanglesOnly = false ) const;
404 
417  double area() const;
418 
433  double length() const;
434 
442  double distance( const QgsGeometry &geom ) const;
443 
444 #ifndef SIP_RUN
445 
446  // TODO QGIS 4: consider renaming vertices_begin, vertices_end, parts_begin, parts_end, etc
447  // to camelCase
448 
453  QgsAbstractGeometry::vertex_iterator vertices_begin() const;
454 
459  QgsAbstractGeometry::vertex_iterator vertices_end() const;
460 #endif
461 
485  QgsVertexIterator vertices() const;
486 
487 #ifndef SIP_RUN
488 
498 
508 
517  QgsAbstractGeometry::const_part_iterator const_parts_begin() const;
518 
527  QgsAbstractGeometry::const_part_iterator const_parts_end() const;
528 #endif
529 
567  QgsGeometryPartIterator parts();
568 
601  QgsGeometryConstPartIterator constParts() const;
602 
620  double hausdorffDistance( const QgsGeometry &geom ) const;
621 
640  double hausdorffDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const;
641 
656  double frechetDistance( const QgsGeometry &geom ) const SIP_THROW( QgsNotSupportedException );
657 
680  double frechetDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const SIP_THROW( QgsNotSupportedException );
681 
694  QgsPointXY closestVertex( const QgsPointXY &point, int &closestVertexIndex SIP_OUT, int &previousVertexIndex SIP_OUT, int &nextVertexIndex SIP_OUT, double &sqrDist SIP_OUT ) const;
695 
704  double distanceToVertex( int vertex ) const;
705 
713  double angleAtVertex( int vertex ) const;
714 
727  void adjacentVertices( int atVertex, int &beforeVertex SIP_OUT, int &afterVertex SIP_OUT ) const;
728 
741  bool insertVertex( double x, double y, int beforeVertex );
742 
755  bool insertVertex( const QgsPoint &point, int beforeVertex );
756 
764  bool moveVertex( double x, double y, int atVertex );
765 
773  bool moveVertex( const QgsPoint &p, int atVertex );
774 
786  bool deleteVertex( int atVertex );
787 
795  bool toggleCircularAtVertex( int atVertex );
796 
802  QgsPoint vertexAt( int atVertex ) const;
803 
809  double sqrDistToVertexAt( QgsPointXY &point SIP_IN, int atVertex ) const;
810 
816  QgsGeometry nearestPoint( const QgsGeometry &other ) const;
817 
828  QgsGeometry shortestLine( const QgsGeometry &other ) const;
829 
836  double closestVertexWithContext( const QgsPointXY &point, int &atVertex SIP_OUT ) const;
837 
849  double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &nextVertexIndex SIP_OUT, int *leftOrRightOfSegment SIP_OUT = nullptr, double epsilon = DEFAULT_SEGMENT_EPSILON ) const;
850 
856  Qgis::GeometryOperationResult addRing( const QVector<QgsPointXY> &ring );
857 
864 
871  Qgis::GeometryOperationResult addPart( const QVector<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsXY );
872 
880 
888 
894  Qgis::GeometryOperationResult addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
895 
902  QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
903 
908  Qgis::GeometryOperationResult translate( double dx, double dy, double dz = 0.0, double dm = 0.0 );
909 
924  Qgis::GeometryOperationResult transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward, bool transformZ = false ) SIP_THROW( QgsCsException );
925 
934  Qgis::GeometryOperationResult transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
935 
942  Qgis::GeometryOperationResult rotate( double rotation, const QgsPointXY &center );
943 
954  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;
955 
978  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 );
979 
991  Qgis::GeometryOperationResult splitGeometry( const QgsCurve *curve, QVector<QgsGeometry> &newGeometries SIP_OUT, bool preserveCircular, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true );
992 
997  Qgis::GeometryOperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
998 
1004  int makeDifferenceInPlace( const QgsGeometry &other ) SIP_SKIP;
1005 
1013  QgsGeometry makeDifference( const QgsGeometry &other ) const;
1014 
1019  QgsRectangle boundingBox() const;
1020 
1032  QgsGeometry orientedMinimumBoundingBox( double &area SIP_OUT, double &angle SIP_OUT, double &width SIP_OUT, double &height SIP_OUT ) const;
1033 
1043  QgsGeometry orientedMinimumBoundingBox() const SIP_SKIP;
1044 
1053  QgsGeometry minimalEnclosingCircle( QgsPointXY &center SIP_OUT, double &radius SIP_OUT, unsigned int segments = 36 ) const;
1054 
1060  QgsGeometry minimalEnclosingCircle( unsigned int segments = 36 ) const SIP_SKIP;
1061 
1070  QgsGeometry orthogonalize( double tolerance = 1.0E-8, int maxIterations = 1000, double angleThreshold = 15.0 ) const;
1071 
1084  QgsGeometry triangularWaves( double wavelength, double amplitude, bool strictWavelength = false ) const;
1085 
1104  QgsGeometry triangularWavesRandomized( double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed = 0 ) const;
1105 
1118  QgsGeometry squareWaves( double wavelength, double amplitude, bool strictWavelength = false ) const;
1119 
1138  QgsGeometry squareWavesRandomized( double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed = 0 ) const;
1139 
1152  QgsGeometry roundWaves( double wavelength, double amplitude, bool strictWavelength = false ) const;
1153 
1172  QgsGeometry roundWavesRandomized( double minimumWavelength, double maximumWavelength, double minimumAmplitude, double maximumAmplitude, unsigned long seed = 0 ) const;
1173 
1187  QgsGeometry applyDashPattern( const QVector< double > &pattern,
1188  Qgis::DashPatternLineEndingRule startRule = Qgis::DashPatternLineEndingRule::NoRule,
1189  Qgis::DashPatternLineEndingRule endRule = Qgis::DashPatternLineEndingRule::NoRule,
1190  Qgis::DashPatternSizeAdjustment adjustment = Qgis::DashPatternSizeAdjustment::ScaleBothDashAndGap,
1191  double patternOffset = 0 ) const;
1192 
1205  QgsGeometry snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const;
1206 
1227  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false );
1228 
1238  bool intersects( const QgsRectangle &rectangle ) const;
1239 
1254  bool intersects( const QgsGeometry &geometry ) const;
1255 
1265  bool boundingBoxIntersects( const QgsRectangle &rectangle ) const;
1266 
1276  bool boundingBoxIntersects( const QgsGeometry &geometry ) const;
1277 
1281  bool contains( const QgsPointXY *p ) const;
1282 
1293  bool contains( const QgsGeometry &geometry ) const;
1294 
1305  bool disjoint( const QgsGeometry &geometry ) const;
1306 
1317  bool touches( const QgsGeometry &geometry ) const;
1318 
1329  bool overlaps( const QgsGeometry &geometry ) const;
1330 
1341  bool within( const QgsGeometry &geometry ) const;
1342 
1353  bool crosses( const QgsGeometry &geometry ) const;
1354 
1362  QgsGeometry buffer( double distance, int segments ) const;
1363 
1376  QgsGeometry buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1377 
1386  QgsGeometry offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1387 
1403  QgsGeometry singleSidedBuffer( double distance, int segments, Qgis::BufferSide side,
1404  Qgis::JoinStyle joinStyle = Qgis::JoinStyle::Round,
1405  double miterLimit = 2.0 ) const;
1406 
1424  QgsGeometry taperedBuffer( double startWidth, double endWidth, int segments ) const;
1425 
1440  QgsGeometry variableWidthBufferByM( int segments ) const;
1441 
1448  QgsGeometry extendLine( double startDistance, double endDistance ) const;
1449 
1451  QgsGeometry simplify( double tolerance ) const;
1452 
1462  QgsGeometry densifyByCount( int extraNodesPerSegment ) const;
1463 
1478  QgsGeometry densifyByDistance( double distance ) const;
1479 
1495  QgsGeometry convertToCurves( double distanceTolerance = 1e-8, double angleTolerance = 1e-8 ) const;
1496 
1510  QgsGeometry centroid() const;
1511 
1525  QgsGeometry pointOnSurface() const;
1526 
1539  QgsGeometry poleOfInaccessibility( double precision, double *distanceToBoundary SIP_OUT = nullptr ) const;
1540 
1564  QgsGeometry largestEmptyCircle( double tolerance, const QgsGeometry &boundary = QgsGeometry() ) const SIP_THROW( QgsNotSupportedException );
1565 
1580  QgsGeometry minimumWidth() const SIP_THROW( QgsNotSupportedException );
1581 
1603  double minimumClearance() const SIP_THROW( QgsNotSupportedException );
1604 
1616  QgsGeometry minimumClearanceLine() const SIP_THROW( QgsNotSupportedException );
1617 
1626  QgsGeometry convexHull() const;
1627 
1643  QgsGeometry voronoiDiagram( const QgsGeometry &extent = QgsGeometry(), double tolerance = 0.0, bool edgesOnly = false ) const;
1644 
1654  QgsGeometry delaunayTriangulation( double tolerance = 0.0, bool edgesOnly = false ) const;
1655 
1666  QgsGeometry node() const;
1667 
1682  QgsGeometry sharedPaths( const QgsGeometry &other ) const;
1683 
1703  QgsGeometry subdivide( int maxNodes = 256 ) const;
1704 
1720  QgsGeometry interpolate( double distance ) const;
1721 
1733  double lineLocatePoint( const QgsGeometry &point ) const;
1734 
1744  double interpolateAngle( double distance ) const;
1745 
1754  QgsGeometry intersection( const QgsGeometry &geometry ) const;
1755 
1763  QgsGeometry clipped( const QgsRectangle &rectangle );
1764 
1776  QgsGeometry combine( const QgsGeometry &geometry ) const;
1777 
1786  QgsGeometry mergeLines() const;
1787 
1796  QgsGeometry difference( const QgsGeometry &geometry ) const;
1797 
1806  QgsGeometry symDifference( const QgsGeometry &geometry ) const;
1807 
1809  QgsGeometry extrude( double x, double y );
1810 
1811 #ifndef SIP_RUN
1812 
1834  QVector< QgsPointXY > randomPointsInPolygon( int count, const std::function< bool( const QgsPointXY & ) > &acceptPoint, unsigned long seed = 0, QgsFeedback *feedback = nullptr, int maxTriesPerPoint = 0 ) const;
1835 
1849  QVector< QgsPointXY > randomPointsInPolygon( int count, unsigned long seed = 0, QgsFeedback *feedback = nullptr ) const;
1851 #else
1852 
1866  SIP_PYOBJECT randomPointsInPolygon( int count, unsigned long seed = 0 ) const SIP_TYPEHINT( QgsPolylineXY );
1867  % MethodCode
1868  const QgsWkbTypes::GeometryType type = sipCpp->type();
1869  if ( sipCpp->isNull() )
1870  {
1871  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Cannot generate points inside a null geometry." ).toUtf8().constData() );
1872  sipIsErr = 1;
1873  }
1874  else if ( type != QgsWkbTypes::PolygonGeometry )
1875  {
1876  PyErr_SetString( PyExc_TypeError, QStringLiteral( "Cannot generate points inside a %1 geometry. Only Polygon types are permitted." ).arg( QgsWkbTypes::displayString( sipCpp->wkbType() ) ).toUtf8().constData() );
1877  sipIsErr = 1;
1878  }
1879  else
1880  {
1881  const sipTypeDef *qvector_type = sipFindType( "QVector<QgsPointXY>" );
1882  sipRes = sipConvertFromNewType( new QVector< QgsPointXY >( sipCpp->randomPointsInPolygon( a0, a1 ) ), qvector_type, Py_None );
1883  }
1884  % End
1885 
1886 
1887 #endif
1889 
1897  int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1898 
1906  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1907 
1913  QString asWkt( int precision = 17 ) const;
1914 
1915 #ifdef SIP_RUN
1916  SIP_PYOBJECT __repr__();
1917  % MethodCode
1918  QString str;
1919  if ( sipCpp->isNull() )
1920  str = QStringLiteral( "<QgsGeometry: null>" );
1921  else
1922  {
1923  QString wkt = sipCpp->asWkt();
1924  if ( wkt.length() > 1000 )
1925  wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
1926  str = QStringLiteral( "<QgsGeometry: %1>" ).arg( wkt );
1927  }
1928  sipRes = PyUnicode_FromString( str.toUtf8().constData() );
1929  % End
1930 #endif
1931 
1935  QString asJson( int precision = 17 ) const;
1936 
1942  virtual json asJsonObject( int precision = 17 ) const SIP_SKIP;
1943 
1966  QVector< QgsGeometry > coerceToType( QgsWkbTypes::Type type ) const;
1967 
1980  QgsGeometry convertToType( QgsWkbTypes::GeometryType destType, bool destMultipart = false ) const;
1981 
1982  /* Accessor functions for getting geometry data */
1983 
1984 #ifndef SIP_RUN
1985 
1994  QgsPointXY asPoint() const;
1995 #else
1996 
2007  SIP_PYOBJECT asPoint() const SIP_TYPEHINT( QgsPointXY );
2008  % MethodCode
2009  if ( sipCpp->isNull() )
2010  {
2011  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a point." ).toUtf8().constData() );
2012  sipIsErr = 1;
2013  }
2014  else
2015  {
2016  const QgsAbstractGeometry *geom = sipCpp->constGet();
2018  {
2019  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a point. Only Point types are permitted." ).arg( QgsWkbTypes::displayString( geom->wkbType() ) ).toUtf8().constData() );
2020  sipIsErr = 1;
2021  }
2022  else
2023  {
2024  sipRes = sipConvertFromNewType( new QgsPointXY( sipCpp->asPoint() ), sipType_QgsPointXY, Py_None );
2025  }
2026  }
2027  % End
2028 #endif
2029 
2030 #ifndef SIP_RUN
2031 
2040  QgsPolylineXY asPolyline() const;
2041 #else
2042 
2054  SIP_PYOBJECT asPolyline() const SIP_TYPEHINT( QgsPolylineXY );
2055  % MethodCode
2056  const QgsWkbTypes::Type type = sipCpp->wkbType();
2057  if ( sipCpp->isNull() )
2058  {
2059  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polyline." ).toUtf8().constData() );
2060  sipIsErr = 1;
2061  }
2063  {
2064  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() );
2065  sipIsErr = 1;
2066  }
2067  else
2068  {
2069  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
2070  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asPolyline() ), qvector_type, Py_None );
2071  }
2072  % End
2073 #endif
2074 
2075 #ifndef SIP_RUN
2076 
2085  QgsPolygonXY asPolygon() const;
2086 #else
2087 
2099  SIP_PYOBJECT asPolygon() const SIP_TYPEHINT( QgsPolygonXY );
2100  % MethodCode
2101  const QgsWkbTypes::Type type = sipCpp->wkbType();
2102  if ( sipCpp->isNull() )
2103  {
2104  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polygon." ).toUtf8().constData() );
2105  sipIsErr = 1;
2106  }
2108  {
2109  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() );
2110  sipIsErr = 1;
2111  }
2112  else
2113  {
2114  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
2115  sipRes = sipConvertFromNewType( new QgsPolygonXY( sipCpp->asPolygon() ), qvector_type, Py_None );
2116  }
2117  % End
2118 #endif
2119 
2120 #ifndef SIP_RUN
2121 
2129  QgsMultiPointXY asMultiPoint() const;
2130 #else
2131 
2142  SIP_PYOBJECT asMultiPoint() const SIP_TYPEHINT( QgsMultiPointXY );
2143  % MethodCode
2144  const QgsWkbTypes::Type type = sipCpp->wkbType();
2145  if ( sipCpp->isNull() )
2146  {
2147  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipoint." ).toUtf8().constData() );
2148  sipIsErr = 1;
2149  }
2151  {
2152  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipoint. Only multipoint types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2153  sipIsErr = 1;
2154  }
2155  else
2156  {
2157  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
2158  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asMultiPoint() ), qvector_type, Py_None );
2159  }
2160  % End
2161 #endif
2162 
2163 #ifndef SIP_RUN
2164 
2173  QgsMultiPolylineXY asMultiPolyline() const;
2174 #else
2175 
2187  SIP_PYOBJECT asMultiPolyline() const SIP_TYPEHINT( QgsMultiPolylineXY );
2188  % MethodCode
2189  const QgsWkbTypes::Type type = sipCpp->wkbType();
2190  if ( sipCpp->isNull() )
2191  {
2192  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multilinestring." ).toUtf8().constData() );
2193  sipIsErr = 1;
2194  }
2196  {
2197  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() );
2198  sipIsErr = 1;
2199  }
2200  else
2201  {
2202  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
2203  sipRes = sipConvertFromNewType( new QgsMultiPolylineXY( sipCpp->asMultiPolyline() ), qvector_type, Py_None );
2204  }
2205  % End
2206 #endif
2207 
2208 #ifndef SIP_RUN
2209 
2218  QgsMultiPolygonXY asMultiPolygon() const;
2219 #else
2220 
2232  SIP_PYOBJECT asMultiPolygon() const SIP_TYPEHINT( QgsMultiPolygonXY );
2233  % MethodCode
2234  const QgsWkbTypes::Type type = sipCpp->wkbType();
2235  if ( sipCpp->isNull() )
2236  {
2237  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipolygon." ).toUtf8().constData() );
2238  sipIsErr = 1;
2239  }
2241  {
2242  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() );
2243  sipIsErr = 1;
2244  }
2245  else
2246  {
2247  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QVector<QgsPointXY>>>" );
2248  sipRes = sipConvertFromNewType( new QgsMultiPolygonXY( sipCpp->asMultiPolygon() ), qvector_type, Py_None );
2249  }
2250  % End
2251 #endif
2252 
2257  QVector<QgsGeometry> asGeometryCollection() const;
2258 
2264  QPointF asQPointF() const SIP_HOLDGIL;
2265 
2278  QPolygonF asQPolygonF() const SIP_HOLDGIL;
2279 
2286  bool deleteRing( int ringNum, int partNum = 0 );
2287 
2293  bool deletePart( int partNum );
2294 
2303  bool convertToMultiType();
2304 
2314  bool convertToSingleType();
2315 
2325  bool convertGeometryCollectionToSubclass( QgsWkbTypes::GeometryType geomType );
2326 
2337  int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
2338  const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) );
2339 
2360  QgsGeometry makeValid() const;
2361 
2374  QgsGeometry forceRHR() const;
2375 
2384  QgsGeometry forcePolygonClockwise() const;
2385 
2394  QgsGeometry forcePolygonCounterClockwise() const;
2395 
2400  class CORE_EXPORT Error
2401  {
2402  public:
2404  : mMessage( QStringLiteral( "none" ) )
2405  {}
2406 
2407  explicit Error( const QString &m )
2408  : mMessage( m )
2409  {}
2410 
2411  Error( const QString &m, const QgsPointXY &p )
2412  : mMessage( m )
2413  , mLocation( p )
2414  , mHasLocation( true ) {}
2415 
2419  QString what() const;
2420 
2424  QgsPointXY where() const;
2425 
2429  bool hasWhere() const;
2430 
2431 #ifdef SIP_RUN
2432  SIP_PYOBJECT __repr__();
2433  % MethodCode
2434  QString str = QStringLiteral( "<QgsGeometry.Error: %1>" ).arg( sipCpp->what() );
2435  sipRes = PyUnicode_FromString( str.toUtf8().data() );
2436  % End
2437 #endif
2438 
2439  // TODO c++20 - replace with = default
2440  bool operator==( const QgsGeometry::Error &other ) const
2441  {
2442  return other.mMessage == mMessage && other.mHasLocation == mHasLocation && other.mLocation == mLocation;
2443  }
2444 
2445  private:
2446  QString mMessage;
2447  QgsPointXY mLocation;
2448  bool mHasLocation = false;
2449  };
2450 
2459  void validateGeometry( QVector<QgsGeometry::Error> &errors SIP_OUT, Qgis::GeometryValidationEngine method = Qgis::GeometryValidationEngine::QgisInternal, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
2460 
2470  void normalize();
2471 
2477  static QgsGeometry unaryUnion( const QVector<QgsGeometry> &geometries );
2478 
2487  static QgsGeometry polygonize( const QVector<QgsGeometry> &geometries );
2488 
2496  void convertToStraightSegment( double tolerance = M_PI / 180., QgsAbstractGeometry::SegmentationToleranceType toleranceType = QgsAbstractGeometry::MaximumAngle );
2497 
2504  bool requiresConversionToStraightSegments() const;
2505 
2511  void mapToPixel( const QgsMapToPixel &mtp );
2512 
2518  void draw( QPainter &p ) const;
2519 
2530  bool vertexIdFromVertexNr( int number, QgsVertexId &id SIP_OUT ) const;
2531 
2543  int vertexNrFromVertexId( QgsVertexId id ) const;
2544 
2552  QString lastError() const SIP_HOLDGIL;
2553 
2563  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) SIP_SKIP;
2564 
2579  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) SIP_SKIP;
2580 
2586  static QgsGeometry fromQPointF( QPointF point ) SIP_HOLDGIL;
2587 
2595  static QgsGeometry fromQPolygonF( const QPolygonF &polygon );
2596 
2604  Q_DECL_DEPRECATED static QgsPolylineXY createPolylineFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2605 
2613  Q_DECL_DEPRECATED static QgsPolygonXY createPolygonFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2614 
2615 #ifndef SIP_RUN
2616 
2626  static bool compare( const QgsPolylineXY &p1, const QgsPolylineXY &p2,
2627  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2628 
2638  static bool compare( const QgsPolygonXY &p1, const QgsPolygonXY &p2,
2639  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2640 
2651  static bool compare( const QgsMultiPolygonXY &p1, const QgsMultiPolygonXY &p2,
2652  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2653 #else
2654 
2674  static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2675  % MethodCode
2676  {
2677  sipRes = false;
2678  int state0;
2679  int state1;
2680  int sipIsErr = 0;
2681 
2682  if ( PyList_Check( a0 ) && PyList_Check( a1 ) &&
2683  PyList_GET_SIZE( a0 ) && PyList_GET_SIZE( a1 ) )
2684  {
2685  PyObject *o0 = PyList_GetItem( a0, 0 );
2686  PyObject *o1 = PyList_GetItem( a1, 0 );
2687  if ( o0 && o1 )
2688  {
2689  // compare polyline - polyline
2690  if ( sipCanConvertToType( o0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2691  sipCanConvertToType( o1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2692  sipCanConvertToType( a0, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2693  sipCanConvertToType( a1, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2694  {
2695  QgsPolylineXY *p0;
2696  QgsPolylineXY *p1;
2697  p0 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a0, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2698  p1 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a1, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2699  if ( sipIsErr )
2700  {
2701  sipReleaseType( p0, sipType_QVector_0100QgsPointXY, state0 );
2702  sipReleaseType( p1, sipType_QVector_0100QgsPointXY, state1 );
2703  }
2704  else
2705  {
2706  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2707  }
2708  }
2709  else if ( PyList_Check( o0 ) && PyList_Check( o1 ) &&
2710  PyList_GET_SIZE( o0 ) && PyList_GET_SIZE( o1 ) )
2711  {
2712  PyObject *oo0 = PyList_GetItem( o0, 0 );
2713  PyObject *oo1 = PyList_GetItem( o1, 0 );
2714  if ( oo0 && oo1 )
2715  {
2716  // compare polygon - polygon
2717  if ( sipCanConvertToType( oo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2718  sipCanConvertToType( oo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2719  sipCanConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2720  sipCanConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2721  {
2722  QgsPolygonXY *p0;
2723  QgsPolygonXY *p1;
2724  p0 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2725  p1 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2726  if ( sipIsErr )
2727  {
2728  sipReleaseType( p0, sipType_QVector_0600QVector_0100QgsPointXY, state0 );
2729  sipReleaseType( p1, sipType_QVector_0600QVector_0100QgsPointXY, state1 );
2730  }
2731  else
2732  {
2733  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2734  }
2735  }
2736  else if ( PyList_Check( oo0 ) && PyList_Check( oo1 ) &&
2737  PyList_GET_SIZE( oo0 ) && PyList_GET_SIZE( oo1 ) )
2738  {
2739  PyObject *ooo0 = PyList_GetItem( oo0, 0 );
2740  PyObject *ooo1 = PyList_GetItem( oo1, 0 );
2741  if ( ooo0 && ooo1 )
2742  {
2743  // compare multipolygon - multipolygon
2744  if ( sipCanConvertToType( ooo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2745  sipCanConvertToType( ooo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2746  sipCanConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2747  sipCanConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2748  {
2749  QgsMultiPolygonXY *p0;
2750  QgsMultiPolygonXY *p1;
2751  p0 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2752  p1 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2753  if ( sipIsErr )
2754  {
2755  sipReleaseType( p0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state0 );
2756  sipReleaseType( p1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state1 );
2757  }
2758  else
2759  {
2760  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2761  }
2762  }
2763  }
2764  }
2765  }
2766  }
2767  }
2768  }
2769  }
2770  % End
2771 #endif
2772 
2789  QgsGeometry smooth( unsigned int iterations = 1, double offset = 0.25,
2790  double minimumDistance = -1.0, double maxAngle = 180.0 ) const;
2791 
2829  static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry ) SIP_FACTORY;
2830 
2836  static void convertPointList( const QVector<QgsPointXY> &input, QgsPointSequence &output );
2837 
2843  static void convertPointList( const QgsPointSequence &input, QVector<QgsPointXY> &output );
2844 
2846  operator QVariant() const
2847  {
2848  return QVariant::fromValue( *this );
2849  }
2850 
2851  private:
2852 
2853  QgsGeometryPrivate *d; //implicitly shared data pointer
2854 
2856  mutable QString mLastError;
2857 
2862  void detach();
2863 
2868  void reset( std::unique_ptr< QgsAbstractGeometry > newGeometry );
2869 
2870  static void convertPolygon( const QgsPolygon &input, QgsPolygonXY &output );
2871 
2873  QgsGeometry convertToPoint( bool destMultipart ) const;
2875  QgsGeometry convertToLine( bool destMultipart ) const;
2877  QgsGeometry convertToPolygon( bool destMultipart ) const;
2878 
2890  std::unique_ptr< QgsLineString > smoothLine( const QgsLineString &line, unsigned int iterations = 1, double offset = 0.25,
2891  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2892 
2904  std::unique_ptr< QgsPolygon > smoothPolygon( const QgsPolygon &polygon, unsigned int iterations = 1, double offset = 0.25,
2905  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2906 
2907 
2909 
2910 }; // class QgsGeometry
2911 
2913 
2914 CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry );
2917 CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry );
2918 
2919 #endif
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:64
GeometryOperationResult
Success or failure of a geometry operation.
Definition: qgis.h:661
GeometryValidationEngine
Available engines for validating geometries.
Definition: qgis.h:701
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition: qgis.h:910
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)
virtual const QgsAbstractGeometry * simplifiedTypeRef() const SIP_HOLDGIL
Returns a reference to the simplest lossless representation of this geometry, e.g.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
A const WKB pointer.
Definition: qgswkbptr.h:138
Class for doing transforms between two map coordinate systems.
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:2401
Error(const QString &m)
Definition: qgsgeometry.h:2407
Error(const QString &m, const QgsPointXY &p)
Definition: qgsgeometry.h:2411
bool operator==(const QgsGeometry::Error &other) const
Definition: qgsgeometry.h:2440
A geometry is the spatial representation of a feature.
Definition: qgsgeometry.h:125
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
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:70
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:1959
#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:76
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
Definition: qgsgeometry.h:86
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:82
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
Definition: qgsgeometry.h:52
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:93
QgsPointSequence QgsPolyline
Polyline as represented as a vector of points.
Definition: qgsgeometry.h:72
Q_DECLARE_METATYPE(QgsMeshTimeSettings)
int precision
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:31