QGIS API Documentation  3.22.4-Białowieża (ce8e65e95e)
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 
431  double length() const;
432 
440  double distance( const QgsGeometry &geom ) const;
441 
442 #ifndef SIP_RUN
443 
444  // TODO QGIS 4: consider renaming vertices_begin, vertices_end, parts_begin, parts_end, etc
445  // to camelCase
446 
451  QgsAbstractGeometry::vertex_iterator vertices_begin() const;
452 
457  QgsAbstractGeometry::vertex_iterator vertices_end() const;
458 #endif
459 
483  QgsVertexIterator vertices() const;
484 
485 #ifndef SIP_RUN
486 
496 
506 
515  QgsAbstractGeometry::const_part_iterator const_parts_begin() const;
516 
525  QgsAbstractGeometry::const_part_iterator const_parts_end() const;
526 #endif
527 
565  QgsGeometryPartIterator parts();
566 
599  QgsGeometryConstPartIterator constParts() const;
600 
618  double hausdorffDistance( const QgsGeometry &geom ) const;
619 
638  double hausdorffDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const;
639 
654  double frechetDistance( const QgsGeometry &geom ) const SIP_THROW( QgsNotSupportedException );
655 
678  double frechetDistanceDensify( const QgsGeometry &geom, double densifyFraction ) const SIP_THROW( QgsNotSupportedException );
679 
692  QgsPointXY closestVertex( const QgsPointXY &point, int &closestVertexIndex SIP_OUT, int &previousVertexIndex SIP_OUT, int &nextVertexIndex SIP_OUT, double &sqrDist SIP_OUT ) const;
693 
702  double distanceToVertex( int vertex ) const;
703 
711  double angleAtVertex( int vertex ) const;
712 
725  void adjacentVertices( int atVertex, int &beforeVertex SIP_OUT, int &afterVertex SIP_OUT ) const;
726 
739  bool insertVertex( double x, double y, int beforeVertex );
740 
753  bool insertVertex( const QgsPoint &point, int beforeVertex );
754 
762  bool moveVertex( double x, double y, int atVertex );
763 
771  bool moveVertex( const QgsPoint &p, int atVertex );
772 
784  bool deleteVertex( int atVertex );
785 
793  bool toggleCircularAtVertex( int atVertex );
794 
800  QgsPoint vertexAt( int atVertex ) const;
801 
807  double sqrDistToVertexAt( QgsPointXY &point SIP_IN, int atVertex ) const;
808 
814  QgsGeometry nearestPoint( const QgsGeometry &other ) const;
815 
826  QgsGeometry shortestLine( const QgsGeometry &other ) const;
827 
834  double closestVertexWithContext( const QgsPointXY &point, int &atVertex SIP_OUT ) const;
835 
847  double closestSegmentWithContext( const QgsPointXY &point, QgsPointXY &minDistPoint SIP_OUT, int &nextVertexIndex SIP_OUT, int *leftOrRightOfSegment SIP_OUT = nullptr, double epsilon = DEFAULT_SEGMENT_EPSILON ) const;
848 
854  Qgis::GeometryOperationResult addRing( const QVector<QgsPointXY> &ring );
855 
862 
869  Qgis::GeometryOperationResult addPart( const QVector<QgsPointXY> &points, QgsWkbTypes::GeometryType geomType = QgsWkbTypes::UnknownGeometry ) SIP_PYNAME( addPointsXY );
870 
878 
886 
892  Qgis::GeometryOperationResult addPart( const QgsGeometry &newPart ) SIP_PYNAME( addPartGeometry );
893 
900  QgsGeometry removeInteriorRings( double minimumAllowedArea = -1 ) const;
901 
906  Qgis::GeometryOperationResult translate( double dx, double dy, double dz = 0.0, double dm = 0.0 );
907 
922  Qgis::GeometryOperationResult transform( const QgsCoordinateTransform &ct, Qgis::TransformDirection direction = Qgis::TransformDirection::Forward, bool transformZ = false ) SIP_THROW( QgsCsException );
923 
932  Qgis::GeometryOperationResult transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0, double mTranslate = 0.0, double mScale = 1.0 );
933 
940  Qgis::GeometryOperationResult rotate( double rotation, const QgsPointXY &center );
941 
952  Q_DECL_DEPRECATED Qgis::GeometryOperationResult splitGeometry( const QVector<QgsPointXY> &splitLine, QVector<QgsGeometry> &newGeometries SIP_OUT, bool topological, QVector<QgsPointXY> &topologyTestPoints SIP_OUT, bool splitFeature = true ) SIP_DEPRECATED;
953 
976  Qgis::GeometryOperationResult splitGeometry( const QgsPointSequence &splitLine, QVector<QgsGeometry> &newGeometries SIP_OUT, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true, bool skipIntersectionTest SIP_PYARGREMOVE = false );
977 
989  Qgis::GeometryOperationResult splitGeometry( const QgsCurve *curve, QVector<QgsGeometry> &newGeometries SIP_OUT, bool preserveCircular, bool topological, QgsPointSequence &topologyTestPoints SIP_OUT, bool splitFeature = true );
990 
995  Qgis::GeometryOperationResult reshapeGeometry( const QgsLineString &reshapeLineString );
996 
1002  int makeDifferenceInPlace( const QgsGeometry &other ) SIP_SKIP;
1003 
1011  QgsGeometry makeDifference( const QgsGeometry &other ) const;
1012 
1017  QgsRectangle boundingBox() const;
1018 
1030  QgsGeometry orientedMinimumBoundingBox( double &area SIP_OUT, double &angle SIP_OUT, double &width SIP_OUT, double &height SIP_OUT ) const;
1031 
1041  QgsGeometry orientedMinimumBoundingBox() const SIP_SKIP;
1042 
1051  QgsGeometry minimalEnclosingCircle( QgsPointXY &center SIP_OUT, double &radius SIP_OUT, unsigned int segments = 36 ) const;
1052 
1058  QgsGeometry minimalEnclosingCircle( unsigned int segments = 36 ) const SIP_SKIP;
1059 
1068  QgsGeometry orthogonalize( double tolerance = 1.0E-8, int maxIterations = 1000, double angleThreshold = 15.0 ) const;
1069 
1082  QgsGeometry snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const;
1083 
1104  bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false );
1105 
1115  bool intersects( const QgsRectangle &rectangle ) const;
1116 
1131  bool intersects( const QgsGeometry &geometry ) const;
1132 
1142  bool boundingBoxIntersects( const QgsRectangle &rectangle ) const;
1143 
1153  bool boundingBoxIntersects( const QgsGeometry &geometry ) const;
1154 
1158  bool contains( const QgsPointXY *p ) const;
1159 
1170  bool contains( const QgsGeometry &geometry ) const;
1171 
1182  bool disjoint( const QgsGeometry &geometry ) const;
1183 
1194  bool touches( const QgsGeometry &geometry ) const;
1195 
1206  bool overlaps( const QgsGeometry &geometry ) const;
1207 
1218  bool within( const QgsGeometry &geometry ) const;
1219 
1230  bool crosses( const QgsGeometry &geometry ) const;
1231 
1239  QgsGeometry buffer( double distance, int segments ) const;
1240 
1253  QgsGeometry buffer( double distance, int segments, Qgis::EndCapStyle endCapStyle, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1254 
1263  QgsGeometry offsetCurve( double distance, int segments, Qgis::JoinStyle joinStyle, double miterLimit ) const;
1264 
1280  QgsGeometry singleSidedBuffer( double distance, int segments, Qgis::BufferSide side,
1281  Qgis::JoinStyle joinStyle = Qgis::JoinStyle::Round,
1282  double miterLimit = 2.0 ) const;
1283 
1301  QgsGeometry taperedBuffer( double startWidth, double endWidth, int segments ) const;
1302 
1317  QgsGeometry variableWidthBufferByM( int segments ) const;
1318 
1325  QgsGeometry extendLine( double startDistance, double endDistance ) const;
1326 
1328  QgsGeometry simplify( double tolerance ) const;
1329 
1339  QgsGeometry densifyByCount( int extraNodesPerSegment ) const;
1340 
1355  QgsGeometry densifyByDistance( double distance ) const;
1356 
1372  QgsGeometry convertToCurves( double distanceTolerance = 1e-8, double angleTolerance = 1e-8 ) const;
1373 
1387  QgsGeometry centroid() const;
1388 
1402  QgsGeometry pointOnSurface() const;
1403 
1416  QgsGeometry poleOfInaccessibility( double precision, double *distanceToBoundary SIP_OUT = nullptr ) const;
1417 
1441  QgsGeometry largestEmptyCircle( double tolerance, const QgsGeometry &boundary = QgsGeometry() ) const SIP_THROW( QgsNotSupportedException );
1442 
1457  QgsGeometry minimumWidth() const SIP_THROW( QgsNotSupportedException );
1458 
1480  double minimumClearance() const SIP_THROW( QgsNotSupportedException );
1481 
1493  QgsGeometry minimumClearanceLine() const SIP_THROW( QgsNotSupportedException );
1494 
1503  QgsGeometry convexHull() const;
1504 
1520  QgsGeometry voronoiDiagram( const QgsGeometry &extent = QgsGeometry(), double tolerance = 0.0, bool edgesOnly = false ) const;
1521 
1531  QgsGeometry delaunayTriangulation( double tolerance = 0.0, bool edgesOnly = false ) const;
1532 
1543  QgsGeometry node() const;
1544 
1559  QgsGeometry sharedPaths( const QgsGeometry &other ) const;
1560 
1580  QgsGeometry subdivide( int maxNodes = 256 ) const;
1581 
1597  QgsGeometry interpolate( double distance ) const;
1598 
1610  double lineLocatePoint( const QgsGeometry &point ) const;
1611 
1621  double interpolateAngle( double distance ) const;
1622 
1631  QgsGeometry intersection( const QgsGeometry &geometry ) const;
1632 
1640  QgsGeometry clipped( const QgsRectangle &rectangle );
1641 
1653  QgsGeometry combine( const QgsGeometry &geometry ) const;
1654 
1663  QgsGeometry mergeLines() const;
1664 
1673  QgsGeometry difference( const QgsGeometry &geometry ) const;
1674 
1683  QgsGeometry symDifference( const QgsGeometry &geometry ) const;
1684 
1686  QgsGeometry extrude( double x, double y );
1687 
1688 #ifndef SIP_RUN
1689 
1711  QVector< QgsPointXY > randomPointsInPolygon( int count, const std::function< bool( const QgsPointXY & ) > &acceptPoint, unsigned long seed = 0, QgsFeedback *feedback = nullptr, int maxTriesPerPoint = 0 ) const;
1712 
1726  QVector< QgsPointXY > randomPointsInPolygon( int count, unsigned long seed = 0, QgsFeedback *feedback = nullptr ) const;
1728 #else
1729 
1743  SIP_PYOBJECT randomPointsInPolygon( int count, unsigned long seed = 0 ) const SIP_TYPEHINT( QgsPolylineXY );
1744  % MethodCode
1745  const QgsWkbTypes::GeometryType type = sipCpp->type();
1746  if ( sipCpp->isNull() )
1747  {
1748  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Cannot generate points inside a null geometry." ).toUtf8().constData() );
1749  sipIsErr = 1;
1750  }
1751  else if ( type != QgsWkbTypes::PolygonGeometry )
1752  {
1753  PyErr_SetString( PyExc_TypeError, QStringLiteral( "Cannot generate points inside a %1 geometry. Only Polygon types are permitted." ).arg( QgsWkbTypes::displayString( sipCpp->wkbType() ) ).toUtf8().constData() );
1754  sipIsErr = 1;
1755  }
1756  else
1757  {
1758  const sipTypeDef *qvector_type = sipFindType( "QVector<QgsPointXY>" );
1759  sipRes = sipConvertFromNewType( new QVector< QgsPointXY >( sipCpp->randomPointsInPolygon( a0, a1 ) ), qvector_type, Py_None );
1760  }
1761  % End
1762 
1763 
1764 #endif
1766 
1774  int wkbSize( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1775 
1783  QByteArray asWkb( QgsAbstractGeometry::WkbFlags flags = QgsAbstractGeometry::WkbFlags() ) const;
1784 
1790  QString asWkt( int precision = 17 ) const;
1791 
1792 #ifdef SIP_RUN
1793  SIP_PYOBJECT __repr__();
1794  % MethodCode
1795  QString str;
1796  if ( sipCpp->isNull() )
1797  str = QStringLiteral( "<QgsGeometry: null>" );
1798  else
1799  {
1800  QString wkt = sipCpp->asWkt();
1801  if ( wkt.length() > 1000 )
1802  wkt = wkt.left( 1000 ) + QStringLiteral( "..." );
1803  str = QStringLiteral( "<QgsGeometry: %1>" ).arg( wkt );
1804  }
1805  sipRes = PyUnicode_FromString( str.toUtf8().constData() );
1806  % End
1807 #endif
1808 
1812  QString asJson( int precision = 17 ) const;
1813 
1819  virtual json asJsonObject( int precision = 17 ) const SIP_SKIP;
1820 
1843  QVector< QgsGeometry > coerceToType( QgsWkbTypes::Type type ) const;
1844 
1857  QgsGeometry convertToType( QgsWkbTypes::GeometryType destType, bool destMultipart = false ) const;
1858 
1859  /* Accessor functions for getting geometry data */
1860 
1861 #ifndef SIP_RUN
1862 
1870  QgsPointXY asPoint() const;
1871 #else
1872 
1883  SIP_PYOBJECT asPoint() const SIP_TYPEHINT( QgsPointXY );
1884  % MethodCode
1885  const QgsWkbTypes::Type type = sipCpp->wkbType();
1886  if ( sipCpp->isNull() )
1887  {
1888  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a point." ).toUtf8().constData() );
1889  sipIsErr = 1;
1890  }
1891  else if ( QgsWkbTypes::flatType( type ) != QgsWkbTypes::Point )
1892  {
1893  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a point. Only Point types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1894  sipIsErr = 1;
1895  }
1896  else
1897  {
1898  sipRes = sipConvertFromNewType( new QgsPointXY( sipCpp->asPoint() ), sipType_QgsPointXY, Py_None );
1899  }
1900  % End
1901 #endif
1902 
1903 #ifndef SIP_RUN
1904 
1913  QgsPolylineXY asPolyline() const;
1914 #else
1915 
1927  SIP_PYOBJECT asPolyline() const SIP_TYPEHINT( QgsPolylineXY );
1928  % MethodCode
1929  const QgsWkbTypes::Type type = sipCpp->wkbType();
1930  if ( sipCpp->isNull() )
1931  {
1932  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polyline." ).toUtf8().constData() );
1933  sipIsErr = 1;
1934  }
1936  {
1937  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a polyline. Only single line or curve types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1938  sipIsErr = 1;
1939  }
1940  else
1941  {
1942  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
1943  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asPolyline() ), qvector_type, Py_None );
1944  }
1945  % End
1946 #endif
1947 
1948 #ifndef SIP_RUN
1949 
1958  QgsPolygonXY asPolygon() const;
1959 #else
1960 
1972  SIP_PYOBJECT asPolygon() const SIP_TYPEHINT( QgsPolygonXY );
1973  % MethodCode
1974  const QgsWkbTypes::Type type = sipCpp->wkbType();
1975  if ( sipCpp->isNull() )
1976  {
1977  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a polygon." ).toUtf8().constData() );
1978  sipIsErr = 1;
1979  }
1981  {
1982  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a polygon. Only single polygon or curve polygon types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
1983  sipIsErr = 1;
1984  }
1985  else
1986  {
1987  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
1988  sipRes = sipConvertFromNewType( new QgsPolygonXY( sipCpp->asPolygon() ), qvector_type, Py_None );
1989  }
1990  % End
1991 #endif
1992 
1993 #ifndef SIP_RUN
1994 
2002  QgsMultiPointXY asMultiPoint() const;
2003 #else
2004 
2015  SIP_PYOBJECT asMultiPoint() const SIP_TYPEHINT( QgsMultiPointXY );
2016  % MethodCode
2017  const QgsWkbTypes::Type type = sipCpp->wkbType();
2018  if ( sipCpp->isNull() )
2019  {
2020  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipoint." ).toUtf8().constData() );
2021  sipIsErr = 1;
2022  }
2024  {
2025  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipoint. Only multipoint types are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2026  sipIsErr = 1;
2027  }
2028  else
2029  {
2030  const sipTypeDef *qvector_type = sipFindType( "QVector< QgsPointXY >" );
2031  sipRes = sipConvertFromNewType( new QgsPolylineXY( sipCpp->asMultiPoint() ), qvector_type, Py_None );
2032  }
2033  % End
2034 #endif
2035 
2036 #ifndef SIP_RUN
2037 
2046  QgsMultiPolylineXY asMultiPolyline() const;
2047 #else
2048 
2060  SIP_PYOBJECT asMultiPolyline() const SIP_TYPEHINT( QgsMultiPolylineXY );
2061  % MethodCode
2062  const QgsWkbTypes::Type type = sipCpp->wkbType();
2063  if ( sipCpp->isNull() )
2064  {
2065  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multilinestring." ).toUtf8().constData() );
2066  sipIsErr = 1;
2067  }
2069  {
2070  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multilinestring. Only multi linestring or curves are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2071  sipIsErr = 1;
2072  }
2073  else
2074  {
2075  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QgsPointXY>>" );
2076  sipRes = sipConvertFromNewType( new QgsMultiPolylineXY( sipCpp->asMultiPolyline() ), qvector_type, Py_None );
2077  }
2078  % End
2079 #endif
2080 
2081 #ifndef SIP_RUN
2082 
2091  QgsMultiPolygonXY asMultiPolygon() const;
2092 #else
2093 
2105  SIP_PYOBJECT asMultiPolygon() const SIP_TYPEHINT( QgsMultiPolygonXY );
2106  % MethodCode
2107  const QgsWkbTypes::Type type = sipCpp->wkbType();
2108  if ( sipCpp->isNull() )
2109  {
2110  PyErr_SetString( PyExc_ValueError, QStringLiteral( "Null geometry cannot be converted to a multipolygon." ).toUtf8().constData() );
2111  sipIsErr = 1;
2112  }
2114  {
2115  PyErr_SetString( PyExc_TypeError, QStringLiteral( "%1 geometry cannot be converted to a multipolygon. Only multi polygon or curves are permitted." ).arg( QgsWkbTypes::displayString( type ) ).toUtf8().constData() );
2116  sipIsErr = 1;
2117  }
2118  else
2119  {
2120  const sipTypeDef *qvector_type = sipFindType( "QVector<QVector<QVector<QgsPointXY>>>" );
2121  sipRes = sipConvertFromNewType( new QgsMultiPolygonXY( sipCpp->asMultiPolygon() ), qvector_type, Py_None );
2122  }
2123  % End
2124 #endif
2125 
2130  QVector<QgsGeometry> asGeometryCollection() const;
2131 
2137  QPointF asQPointF() const SIP_HOLDGIL;
2138 
2151  QPolygonF asQPolygonF() const SIP_HOLDGIL;
2152 
2159  bool deleteRing( int ringNum, int partNum = 0 );
2160 
2166  bool deletePart( int partNum );
2167 
2176  bool convertToMultiType();
2177 
2187  bool convertToSingleType();
2188 
2198  bool convertGeometryCollectionToSubclass( QgsWkbTypes::GeometryType geomType );
2199 
2210  int avoidIntersections( const QList<QgsVectorLayer *> &avoidIntersectionsLayers,
2211  const QHash<QgsVectorLayer *, QSet<QgsFeatureId> > &ignoreFeatures SIP_PYARGREMOVE = ( QHash<QgsVectorLayer *, QSet<QgsFeatureId> >() ) );
2212 
2233  QgsGeometry makeValid() const;
2234 
2242  QgsGeometry forceRHR() const;
2243 
2248  class CORE_EXPORT Error
2249  {
2250  public:
2252  : mMessage( QStringLiteral( "none" ) )
2253  {}
2254 
2255  explicit Error( const QString &m )
2256  : mMessage( m )
2257  {}
2258 
2259  Error( const QString &m, const QgsPointXY &p )
2260  : mMessage( m )
2261  , mLocation( p )
2262  , mHasLocation( true ) {}
2263 
2267  QString what() const;
2268 
2272  QgsPointXY where() const;
2273 
2277  bool hasWhere() const;
2278 
2279 #ifdef SIP_RUN
2280  SIP_PYOBJECT __repr__();
2281  % MethodCode
2282  QString str = QStringLiteral( "<QgsGeometry.Error: %1>" ).arg( sipCpp->what() );
2283  sipRes = PyUnicode_FromString( str.toUtf8().data() );
2284  % End
2285 #endif
2286 
2287  // TODO c++20 - replace with = default
2288  bool operator==( const QgsGeometry::Error &other ) const
2289  {
2290  return other.mMessage == mMessage && other.mHasLocation == mHasLocation && other.mLocation == mLocation;
2291  }
2292 
2293  private:
2294  QString mMessage;
2295  QgsPointXY mLocation;
2296  bool mHasLocation = false;
2297  };
2298 
2307  void validateGeometry( QVector<QgsGeometry::Error> &errors SIP_OUT, Qgis::GeometryValidationEngine method = Qgis::GeometryValidationEngine::QgisInternal, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const;
2308 
2318  void normalize();
2319 
2325  static QgsGeometry unaryUnion( const QVector<QgsGeometry> &geometries );
2326 
2335  static QgsGeometry polygonize( const QVector<QgsGeometry> &geometries );
2336 
2344  void convertToStraightSegment( double tolerance = M_PI / 180., QgsAbstractGeometry::SegmentationToleranceType toleranceType = QgsAbstractGeometry::MaximumAngle );
2345 
2352  bool requiresConversionToStraightSegments() const;
2353 
2359  void mapToPixel( const QgsMapToPixel &mtp );
2360 
2366  void draw( QPainter &p ) const;
2367 
2378  bool vertexIdFromVertexNr( int number, QgsVertexId &id SIP_OUT ) const;
2379 
2391  int vertexNrFromVertexId( QgsVertexId id ) const;
2392 
2400  QString lastError() const SIP_HOLDGIL;
2401 
2411  void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) SIP_SKIP;
2412 
2427  void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform ) SIP_SKIP;
2428 
2434  static QgsGeometry fromQPointF( QPointF point ) SIP_HOLDGIL;
2435 
2443  static QgsGeometry fromQPolygonF( const QPolygonF &polygon );
2444 
2452  Q_DECL_DEPRECATED static QgsPolylineXY createPolylineFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2453 
2461  Q_DECL_DEPRECATED static QgsPolygonXY createPolygonFromQPolygonF( const QPolygonF &polygon ) SIP_DEPRECATED;
2462 
2463 #ifndef SIP_RUN
2464 
2474  static bool compare( const QgsPolylineXY &p1, const QgsPolylineXY &p2,
2475  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2476 
2486  static bool compare( const QgsPolygonXY &p1, const QgsPolygonXY &p2,
2487  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2488 
2499  static bool compare( const QgsMultiPolygonXY &p1, const QgsMultiPolygonXY &p2,
2500  double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2501 #else
2502 
2522  static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * std::numeric_limits<double>::epsilon() );
2523  % MethodCode
2524  {
2525  sipRes = false;
2526  int state0;
2527  int state1;
2528  int sipIsErr = 0;
2529 
2530  if ( PyList_Check( a0 ) && PyList_Check( a1 ) &&
2531  PyList_GET_SIZE( a0 ) && PyList_GET_SIZE( a1 ) )
2532  {
2533  PyObject *o0 = PyList_GetItem( a0, 0 );
2534  PyObject *o1 = PyList_GetItem( a1, 0 );
2535  if ( o0 && o1 )
2536  {
2537  // compare polyline - polyline
2538  if ( sipCanConvertToType( o0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2539  sipCanConvertToType( o1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2540  sipCanConvertToType( a0, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2541  sipCanConvertToType( a1, sipType_QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2542  {
2543  QgsPolylineXY *p0;
2544  QgsPolylineXY *p1;
2545  p0 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a0, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2546  p1 = reinterpret_cast<QgsPolylineXY *>( sipConvertToType( a1, sipType_QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2547  if ( sipIsErr )
2548  {
2549  sipReleaseType( p0, sipType_QVector_0100QgsPointXY, state0 );
2550  sipReleaseType( p1, sipType_QVector_0100QgsPointXY, state1 );
2551  }
2552  else
2553  {
2554  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2555  }
2556  }
2557  else if ( PyList_Check( o0 ) && PyList_Check( o1 ) &&
2558  PyList_GET_SIZE( o0 ) && PyList_GET_SIZE( o1 ) )
2559  {
2560  PyObject *oo0 = PyList_GetItem( o0, 0 );
2561  PyObject *oo1 = PyList_GetItem( o1, 0 );
2562  if ( oo0 && oo1 )
2563  {
2564  // compare polygon - polygon
2565  if ( sipCanConvertToType( oo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2566  sipCanConvertToType( oo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2567  sipCanConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2568  sipCanConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2569  {
2570  QgsPolygonXY *p0;
2571  QgsPolygonXY *p1;
2572  p0 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2573  p1 = reinterpret_cast<QgsPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2574  if ( sipIsErr )
2575  {
2576  sipReleaseType( p0, sipType_QVector_0600QVector_0100QgsPointXY, state0 );
2577  sipReleaseType( p1, sipType_QVector_0600QVector_0100QgsPointXY, state1 );
2578  }
2579  else
2580  {
2581  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2582  }
2583  }
2584  else if ( PyList_Check( oo0 ) && PyList_Check( oo1 ) &&
2585  PyList_GET_SIZE( oo0 ) && PyList_GET_SIZE( oo1 ) )
2586  {
2587  PyObject *ooo0 = PyList_GetItem( oo0, 0 );
2588  PyObject *ooo1 = PyList_GetItem( oo1, 0 );
2589  if ( ooo0 && ooo1 )
2590  {
2591  // compare multipolygon - multipolygon
2592  if ( sipCanConvertToType( ooo0, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2593  sipCanConvertToType( ooo1, sipType_QgsPointXY, SIP_NOT_NONE ) &&
2594  sipCanConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) &&
2595  sipCanConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, SIP_NOT_NONE ) )
2596  {
2597  QgsMultiPolygonXY *p0;
2598  QgsMultiPolygonXY *p1;
2599  p0 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
2600  p1 = reinterpret_cast<QgsMultiPolygonXY *>( sipConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
2601  if ( sipIsErr )
2602  {
2603  sipReleaseType( p0, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state0 );
2604  sipReleaseType( p1, sipType_QVector_0600QVector_0600QVector_0100QgsPointXY, state1 );
2605  }
2606  else
2607  {
2608  sipRes = QgsGeometry::compare( *p0, *p1, a2 );
2609  }
2610  }
2611  }
2612  }
2613  }
2614  }
2615  }
2616  }
2617  }
2618  % End
2619 #endif
2620 
2637  QgsGeometry smooth( unsigned int iterations = 1, double offset = 0.25,
2638  double minimumDistance = -1.0, double maxAngle = 180.0 ) const;
2639 
2677  static QgsGeometryEngine *createGeometryEngine( const QgsAbstractGeometry *geometry ) SIP_FACTORY;
2678 
2684  static void convertPointList( const QVector<QgsPointXY> &input, QgsPointSequence &output );
2685 
2691  static void convertPointList( const QgsPointSequence &input, QVector<QgsPointXY> &output );
2692 
2694  operator QVariant() const
2695  {
2696  return QVariant::fromValue( *this );
2697  }
2698 
2699  private:
2700 
2701  QgsGeometryPrivate *d; //implicitly shared data pointer
2702 
2704  mutable QString mLastError;
2705 
2710  void detach();
2711 
2716  void reset( std::unique_ptr< QgsAbstractGeometry > newGeometry );
2717 
2718  static void convertPolygon( const QgsPolygon &input, QgsPolygonXY &output );
2719 
2721  QgsGeometry convertToPoint( bool destMultipart ) const;
2723  QgsGeometry convertToLine( bool destMultipart ) const;
2725  QgsGeometry convertToPolygon( bool destMultipart ) const;
2726 
2738  std::unique_ptr< QgsLineString > smoothLine( const QgsLineString &line, unsigned int iterations = 1, double offset = 0.25,
2739  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2740 
2752  std::unique_ptr< QgsPolygon > smoothPolygon( const QgsPolygon &polygon, unsigned int iterations = 1, double offset = 0.25,
2753  double minimumDistance = -1, double maxAngle = 180.0 ) const;
2754 
2755 
2757 
2758 }; // class QgsGeometry
2759 
2761 
2762 CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsGeometry &geometry );
2765 CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsGeometry &geometry );
2766 
2767 #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:647
GeometryValidationEngine
Available engines for validating geometries.
Definition: qgis.h:687
TransformDirection
Indicates the direction (forward or inverse) of a transform.
Definition: qgis.h:896
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.
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:2249
Error(const QString &m)
Definition: qgsgeometry.h:2255
Error(const QString &m, const QgsPointXY &p)
Definition: qgsgeometry.h:2259
bool operator==(const QgsGeometry::Error &other) const
Definition: qgsgeometry.h:2288
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: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:1701
#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