QGIS API Documentation  3.27.0-Master (597e8eebd4)
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 
1970  QVector< QgsGeometry > coerceToType( QgsWkbTypes::Type type, double defaultZ = 0, double defaultM = 0 ) const;
1971 
1984  QgsGeometry convertToType( QgsWkbTypes::GeometryType destType, bool destMultipart = false ) const;
1985 
1986  /* Accessor functions for getting geometry data */
1987 
1988 #ifndef SIP_RUN
1989 
1998  QgsPointXY asPoint() const;
1999 #else
2000 
2011  SIP_PYOBJECT asPoint() const SIP_TYPEHINT( QgsPointXY );
2012  % MethodCode
2013  if ( sipCpp->isNull() )
2014  {
2015  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a point." ).toUtf8().constData() );
2016  sipIsErr = 1;
2017  }
2018  else
2019  {
2020  const QgsAbstractGeometry *geom = sipCpp->constGet();
2022  {
2023  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() );
2024  sipIsErr = 1;
2025  }
2026  else
2027  {
2028  sipRes = sipConvertFromNewType( new QgsPointXY( sipCpp->asPoint() ), sipType_QgsPointXY, Py_None );
2029  }
2030  }
2031  % End
2032 #endif
2033 
2034 #ifndef SIP_RUN
2035 
2044  QgsPolylineXY asPolyline() const;
2045 #else
2046 
2058  SIP_PYOBJECT asPolyline() const SIP_TYPEHINT( QgsPolylineXY );
2059  % MethodCode
2060  const QgsWkbTypes::Type type = sipCpp->wkbType();
2061  if ( sipCpp->isNull() )
2062  {
2063  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polyline." ).toUtf8().constData() );
2064  sipIsErr = 1;
2065  }
2067  {
2068  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() );
2069  sipIsErr = 1;
2070  }
2071  else
2072  {
2073  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
2074  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asPolyline() ), qvector_type, Py_None );
2075  }
2076  % End
2077 #endif
2078 
2079 #ifndef SIP_RUN
2080 
2089  QgsPolygonXY asPolygon() const;
2090 #else
2091 
2103  SIP_PYOBJECT asPolygon() const SIP_TYPEHINT( QgsPolygonXY );
2104  % MethodCode
2105  const QgsWkbTypes::Type type = sipCpp->wkbType();
2106  if ( sipCpp->isNull() )
2107  {
2108  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polygon." ).toUtf8().constData() );
2109  sipIsErr = 1;
2110  }
2112  {
2113  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() );
2114  sipIsErr = 1;
2115  }
2116  else
2117  {
2118  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
2119  sipRes = sipConvertFromNewType( new QgsPolygonXY( sipCpp->asPolygon() ), qvector_type, Py_None );
2120  }
2121  % End
2122 #endif
2123 
2124 #ifndef SIP_RUN
2125 
2133  QgsMultiPointXY asMultiPoint() const;
2134 #else
2135 
2146  SIP_PYOBJECT asMultiPoint() const SIP_TYPEHINT( QgsMultiPointXY );
2147  % MethodCode
2148  const QgsWkbTypes::Type type = sipCpp->wkbType();
2149  if ( sipCpp->isNull() )
2150  {
2151  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipoint." ).toUtf8().constData() );
2152  sipIsErr = 1;
2153  }
2155  {
2156  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipoint. Only multipoint types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2157  sipIsErr = 1;
2158  }
2159  else
2160  {
2161  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
2162  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asMultiPoint() ), qvector_type, Py_None );
2163  }
2164  % End
2165 #endif
2166 
2167 #ifndef SIP_RUN
2168 
2177  QgsMultiPolylineXY asMultiPolyline() const;
2178 #else
2179 
2191  SIP_PYOBJECT asMultiPolyline() const SIP_TYPEHINT( QgsMultiPolylineXY );
2192  % MethodCode
2193  const QgsWkbTypes::Type type = sipCpp->wkbType();
2194  if ( sipCpp->isNull() )
2195  {
2196  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multilinestring." ).toUtf8().constData() );
2197  sipIsErr = 1;
2198  }
2200  {
2201  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() );
2202  sipIsErr = 1;
2203  }
2204  else
2205  {
2206  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
2207  sipRes = sipConvertFromNewType( new QgsMultiPolylineXY( sipCpp->asMultiPolyline() ), qvector_type, Py_None );
2208  }
2209  % End
2210 #endif
2211 
2212 #ifndef SIP_RUN
2213 
2222  QgsMultiPolygonXY asMultiPolygon() const;
2223 #else
2224 
2236  SIP_PYOBJECT asMultiPolygon() const SIP_TYPEHINT( QgsMultiPolygonXY );
2237  % MethodCode
2238  const QgsWkbTypes::Type type = sipCpp->wkbType();
2239  if ( sipCpp->isNull() )
2240  {
2241  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipolygon." ).toUtf8().constData() );
2242  sipIsErr = 1;
2243  }
2245  {
2246  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() );
2247  sipIsErr = 1;
2248  }
2249  else
2250  {
2251  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QVector<QgsPointXY>>>" );
2252  sipRes = sipConvertFromNewType( new QgsMultiPolygonXY( sipCpp->asMultiPolygon() ), qvector_type, Py_None );
2253  }
2254  % End
2255 #endif
2256 
2261  QVector<QgsGeometry> asGeometryCollection() const;
2262 
2268  QPointF asQPointF() const SIP_HOLDGIL;
2269 
2282  QPolygonF asQPolygonF() const SIP_HOLDGIL;
2283 
2290  bool deleteRing( int ringNum, int partNum = 0 );
2291 
2297  bool deletePart( int partNum );
2298 
2307  bool convertToMultiType();
2308 
2318  bool convertToSingleType();
2319 
2329  bool convertGeometryCollectionToSubclass( QgsWkbTypes::GeometryType geomType );
2330 
2341  int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
2342  const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) );
2343 
2364  QgsGeometry makeValid() const;
2365 
2378  QgsGeometry forceRHR() const;
2379 
2388  QgsGeometry forcePolygonClockwise() const;
2389 
2398  QgsGeometry forcePolygonCounterClockwise() const;
2399 
2404  class CORE_EXPORT Error
2405  {
2406  public:
2408  : mMessage( QStringLiteral( "none" ) )
2409  {}
2410 
2411  explicit Error( const QString &m )
2412  : mMessage( m )
2413  {}
2414 
2415  Error( const QString &m, const QgsPointXY &p )
2416  : mMessage( m )
2417  , mLocation( p )
2418  , mHasLocation( true ) {}
2419 
2423  QString what() const;
2424 
2428  QgsPointXY where() const;
2429 
2433  bool hasWhere() const;
2434 
2435 #ifdef SIP_RUN
2436  SIP_PYOBJECT __repr__();
2437  % MethodCode
2438  QString str = QStringLiteral( "<QgsGeometry.Error: %1>" ).arg( sipCpp->what() );
2439  sipRes = PyUnicode_FromString( str.toUtf8().data() );
2440  % End
2441 #endif
2442 
2443  // TODO c++20 - replace with = default
2444  bool operator==( const QgsGeometry::Error &other ) const
2445  {
2446  return other.mMessage == mMessage && other.mHasLocation == mHasLocation && other.mLocation == mLocation;
2447  }
2448 
2449  private:
2450  QString mMessage;
2451  QgsPointXY mLocation;
2452  bool mHasLocation = false;
2453  };
2454 
2463  void validateGeometry( QVector<QgsGeometry::Error> &errors SIP_OUT, Qgis::GeometryValidationEngine method = Qgis::GeometryValidationEngine::QgisInternal, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
2464 
2474  void normalize();
2475 
2481  static QgsGeometry unaryUnion( const QVector<QgsGeometry> &geometries );
2482 
2491  static QgsGeometry polygonize( const QVector<QgsGeometry> &geometries );
2492 
2500  void convertToStraightSegment( double tolerance = M_PI / 180., QgsAbstractGeometry::SegmentationToleranceType toleranceType = QgsAbstractGeometry::MaximumAngle );
2501 
2508  bool requiresConversionToStraightSegments() const;
2509 
2515  void mapToPixel( const QgsMapToPixel &mtp );
2516 
2522  void draw( QPainter &p ) const;
2523 
2534  bool vertexIdFromVertexNr( int number, QgsVertexId &id SIP_OUT ) const;
2535 
2547  int vertexNrFromVertexId( QgsVertexId id ) const;
2548 
2556  QString lastError() const SIP_HOLDGIL;
2557 
2567  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) SIP_SKIP;
2568 
2583  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) SIP_SKIP;
2584 
2590  static QgsGeometry fromQPointF( QPointF point ) SIP_HOLDGIL;
2591 
2599  static QgsGeometry fromQPolygonF( const QPolygonF &polygon );
2600 
2608  Q_DECL_DEPRECATED static QgsPolylineXY createPolylineFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2609 
2617  Q_DECL_DEPRECATED static QgsPolygonXY createPolygonFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2618 
2619 #ifndef SIP_RUN
2620 
2630  static bool compare( const QgsPolylineXY &p1, const QgsPolylineXY &p2,
2631  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2632 
2642  static bool compare( const QgsPolygonXY &p1, const QgsPolygonXY &p2,
2643  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2644 
2655  static bool compare( const QgsMultiPolygonXY &p1, const QgsMultiPolygonXY &p2,
2656  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2657 #else
2658 
2678  static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2679  % MethodCode
2680  {
2681  sipRes = false;
2682  int state0;
2683  int state1;
2684  int sipIsErr = 0;
2685 
2686  if ( PyList_Check( a0 ) && PyList_Check( a1 ) &&
2687  PyList_GET_SIZE( a0 ) && PyList_GET_SIZE( a1 ) )
2688  {
2689  PyObject *o0 = PyList_GetItem( a0, 0 );
2690  PyObject *o1 = PyList_GetItem( a1, 0 );
2691  if ( o0 && o1 )
2692  {
2693  // compare polyline - polyline
2694  if ( sipCanConvertToType( o0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2695  sipCanConvertToType( o1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2696  sipCanConvertToType( a0, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2697  sipCanConvertToType( a1, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2698  {
2699  QgsPolylineXY *p0;
2700  QgsPolylineXY *p1;
2701  p0 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a0, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2702  p1 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a1, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2703  if ( sipIsErr )
2704  {
2705  sipReleaseType( p0, sipType_QVector_0100QgsPointXY, state0 );
2706  sipReleaseType( p1, sipType_QVector_0100QgsPointXY, state1 );
2707  }
2708  else
2709  {
2710  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2711  }
2712  }
2713  else if ( PyList_Check( o0 ) && PyList_Check( o1 ) &&
2714  PyList_GET_SIZE( o0 ) && PyList_GET_SIZE( o1 ) )
2715  {
2716  PyObject *oo0 = PyList_GetItem( o0, 0 );
2717  PyObject *oo1 = PyList_GetItem( o1, 0 );
2718  if ( oo0 && oo1 )
2719  {
2720  // compare polygon - polygon
2721  if ( sipCanConvertToType( oo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2722  sipCanConvertToType( oo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2723  sipCanConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2724  sipCanConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2725  {
2726  QgsPolygonXY *p0;
2727  QgsPolygonXY *p1;
2728  p0 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2729  p1 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2730  if ( sipIsErr )
2731  {
2732  sipReleaseType( p0, sipType_QVector_0600QVector_0100QgsPointXY, state0 );
2733  sipReleaseType( p1, sipType_QVector_0600QVector_0100QgsPointXY, state1 );
2734  }
2735  else
2736  {
2737  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2738  }
2739  }
2740  else if ( PyList_Check( oo0 ) && PyList_Check( oo1 ) &&
2741  PyList_GET_SIZE( oo0 ) && PyList_GET_SIZE( oo1 ) )
2742  {
2743  PyObject *ooo0 = PyList_GetItem( oo0, 0 );
2744  PyObject *ooo1 = PyList_GetItem( oo1, 0 );
2745  if ( ooo0 && ooo1 )
2746  {
2747  // compare multipolygon - multipolygon
2748  if ( sipCanConvertToType( ooo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2749  sipCanConvertToType( ooo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2750  sipCanConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2751  sipCanConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2752  {
2753  QgsMultiPolygonXY *p0;
2754  QgsMultiPolygonXY *p1;
2755  p0 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2756  p1 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2757  if ( sipIsErr )
2758  {
2759  sipReleaseType( p0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state0 );
2760  sipReleaseType( p1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state1 );
2761  }
2762  else
2763  {
2764  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2765  }
2766  }
2767  }
2768  }
2769  }
2770  }
2771  }
2772  }
2773  }
2774  % End
2775 #endif
2776 
2793  QgsGeometry smooth( unsigned int iterations = 1, double offset = 0.25,
2794  double minimumDistance = -1.0, double maxAngle = 180.0 ) const;
2795 
2833  static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry ) SIP_FACTORY;
2834 
2840  static void convertPointList( const QVector<QgsPointXY> &input, QgsPointSequence &output );
2841 
2847  static void convertPointList( const QgsPointSequence &input, QVector<QgsPointXY> &output );
2848 
2850  operator QVariant() const
2851  {
2852  return QVariant::fromValue( *this );
2853  }
2854 
2855  private:
2856 
2857  QgsGeometryPrivate *d; //implicitly shared data pointer
2858 
2860  mutable QString mLastError;
2861 
2866  void detach();
2867 
2872  void reset( std::unique_ptr< QgsAbstractGeometry > newGeometry );
2873 
2874  static void convertPolygon( const QgsPolygon &input, QgsPolygonXY &output );
2875 
2877  QgsGeometry convertToPoint( bool destMultipart ) const;
2879  QgsGeometry convertToLine( bool destMultipart ) const;
2881  QgsGeometry convertToPolygon( bool destMultipart ) const;
2882 
2894  std::unique_ptr< QgsLineString > smoothLine( const QgsLineString &line, unsigned int iterations = 1, double offset = 0.25,
2895  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2896 
2908  std::unique_ptr< QgsPolygon > smoothPolygon( const QgsPolygon &polygon, unsigned int iterations = 1, double offset = 0.25,
2909  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2910 
2911 
2913 
2914 }; // class QgsGeometry
2915 
2917 
2918 CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry );
2921 CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry );
2922 
2923 #endif
The Qgis class provides global constants for use throughout the application.
Definition: qgis.h:72
GeometryOperationResult
Success or failure of a geometry operation.
Definition: qgis.h:902
GeometryValidationEngine
Available engines for validating geometries.
Definition: qgis.h:943
TransformDirection
Flags for raster layer temporal capabilities.
Definition: qgis.h:1255
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:2405
Error(const QString &m)
Definition: qgsgeometry.h:2411
Error(const QString &m, const QgsPointXY &p)
Definition: qgsgeometry.h:2415
bool operator==(const QgsGeometry::Error &other) const
Definition: qgsgeometry.h:2444
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:45
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:968
static bool isMultiType(Type type) SIP_HOLDGIL
Returns true if the WKB type is a multi type.
Definition: qgswkbtypes.h:862
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:732
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:2774
#define SIP_THROW(name)
Definition: qgis_sip.h:198
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:227
#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:151
#define SIP_TRANSFER
Definition: qgis_sip.h:36
#define SIP_OUT
Definition: qgis_sip.h:58
#define SIP_HOLDGIL
Definition: qgis_sip.h:166
#define SIP_FACTORY
Definition: qgis_sip.h:76
QVector< QgsPoint > QgsPointSequence
Q_DECLARE_METATYPE(QgsDatabaseQueryLogEntry)
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
int precision
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:31