QGIS API Documentation  3.12.1-BucureČ™ti (121cc00ff0)
qgsabstractgeometry.h
Go to the documentation of this file.
1 /***************************************************************************
2  qgsabstractgeometry.h
3  -------------------------------------------------------------------
4 Date : 04 Sept 2014
5 Copyright : (C) 2014 by Marco Hugentobler
6 email : marco.hugentobler at sourcepole dot com
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 QGSABSTRACTGEOMETRYV2
17 #define QGSABSTRACTGEOMETRYV2
18 
19 #include <functional>
20 #include <QString>
21 
22 #include "qgis_core.h"
23 #include "qgscoordinatetransform.h"
24 #include "qgswkbtypes.h"
25 #include "qgswkbptr.h"
26 
27 #ifndef SIP_RUN
28 #include "json_fwd.hpp"
29 using namespace nlohmann;
30 #endif
31 
32 class QgsMapToPixel;
33 class QgsCurve;
34 class QgsMultiCurve;
35 class QgsMultiPoint;
36 
37 struct QgsVertexId;
38 class QgsVertexIterator;
39 class QPainter;
40 class QDomDocument;
41 class QDomElement;
45 
46 typedef QVector< QgsPoint > QgsPointSequence;
47 #ifndef SIP_RUN
48 typedef QVector< QgsPointSequence > QgsRingSequence;
49 typedef QVector< QgsRingSequence > QgsCoordinateSequence;
50 #else
51 typedef QVector< QVector< QgsPoint > > QgsRingSequence;
52 typedef QVector< QVector< QVector< QgsPoint > > > QgsCoordinateSequence;
53 #endif
54 
55 
71 class CORE_EXPORT QgsAbstractGeometry
72 {
73 
74 #ifdef SIP_RUN
76  if ( qgsgeometry_cast<QgsPoint *>( sipCpp ) != nullptr )
77  sipType = sipType_QgsPoint;
78  else if ( qgsgeometry_cast<QgsLineString *>( sipCpp ) != nullptr )
79  sipType = sipType_QgsLineString;
80  else if ( qgsgeometry_cast<QgsCircularString *>( sipCpp ) != nullptr )
81  sipType = sipType_QgsCircularString;
82  else if ( qgsgeometry_cast<QgsCompoundCurve *>( sipCpp ) != nullptr )
83  sipType = sipType_QgsCompoundCurve;
84  else if ( qgsgeometry_cast<QgsTriangle *>( sipCpp ) != nullptr )
85  sipType = sipType_QgsTriangle;
86  else if ( qgsgeometry_cast<QgsPolygon *>( sipCpp ) != nullptr )
87  sipType = sipType_QgsPolygon;
88  else if ( qgsgeometry_cast<QgsCurvePolygon *>( sipCpp ) != nullptr )
89  sipType = sipType_QgsCurvePolygon;
90  else if ( qgsgeometry_cast<QgsMultiPoint *>( sipCpp ) != nullptr )
91  sipType = sipType_QgsMultiPoint;
92  else if ( qgsgeometry_cast<QgsMultiLineString *>( sipCpp ) != nullptr )
93  sipType = sipType_QgsMultiLineString;
94  else if ( qgsgeometry_cast<QgsMultiPolygon *>( sipCpp ) != nullptr )
95  sipType = sipType_QgsMultiPolygon;
96  else if ( qgsgeometry_cast<QgsMultiSurface *>( sipCpp ) != nullptr )
97  sipType = sipType_QgsMultiSurface;
98  else if ( qgsgeometry_cast<QgsMultiCurve *>( sipCpp ) != nullptr )
99  sipType = sipType_QgsMultiCurve;
100  else if ( qgsgeometry_cast<QgsGeometryCollection *>( sipCpp ) != nullptr )
101  sipType = sipType_QgsGeometryCollection;
102  else
103  sipType = 0;
104  SIP_END
105 #endif
106 
107  Q_GADGET
108 
109  public:
110 
113  {
114 
118  MaximumAngle = 0,
119 
123  MaximumDifference
124  };
125  Q_ENUM( SegmentationToleranceType )
126 
127 
129  {
130 
134  XY = 0,
135 
139  YX
140  };
142 
143 
146  QgsAbstractGeometry() = default;
147  virtual ~QgsAbstractGeometry() = default;
149  QgsAbstractGeometry &operator=( const QgsAbstractGeometry &geom );
150 
151  virtual bool operator==( const QgsAbstractGeometry &other ) const = 0;
152  virtual bool operator!=( const QgsAbstractGeometry &other ) const = 0;
153 
157  virtual QgsAbstractGeometry *clone() const = 0 SIP_FACTORY;
158 
162  virtual void clear() = 0;
163 
167  virtual QgsRectangle boundingBox() const = 0;
168 
169  //mm-sql interface
170 
175  virtual int dimension() const = 0;
176 
182  virtual QString geometryType() const = 0;
183 
189  inline QgsWkbTypes::Type wkbType() const { return mWkbType; }
190 
196  QString wktTypeStr() const;
197 
202  bool is3D() const
203  {
204  return QgsWkbTypes::hasZ( mWkbType );
205  }
206 
211  bool isMeasure() const
212  {
213  return QgsWkbTypes::hasM( mWkbType );
214  }
215 
222  virtual QgsAbstractGeometry *boundary() const = 0 SIP_FACTORY;
223 
224  //import
225 
231  virtual bool fromWkb( QgsConstWkbPtr &wkb ) = 0;
232 
237  virtual bool fromWkt( const QString &wkt ) = 0;
238 
239  //export
240 
249  virtual QByteArray asWkb() const = 0;
250 
259  virtual QString asWkt( int precision = 17 ) const = 0;
260 
272  virtual QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const = 0;
273 
285  virtual QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const = 0;
286 
296  QString asJson( int precision = 17 );
297 
308  virtual json asJsonObject( int precision = 17 ) SIP_SKIP const;
309 
314  virtual QString asKml( int precision = 17 ) const = 0;
315 
316 
317  //render pipeline
318 
329  virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) SIP_THROW( QgsCsException ) = 0;
330 
337  virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0,
338  double mTranslate = 0.0, double mScale = 1.0 ) = 0;
339 
344  virtual void draw( QPainter &p ) const = 0;
345 
356  virtual int vertexNumberFromVertexId( QgsVertexId id ) const = 0;
357 
365  virtual bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const = 0;
366 
371  virtual void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const = 0;
372 
377  virtual QgsCoordinateSequence coordinateSequence() const = 0;
378 
382  virtual int nCoordinates() const;
383 
387  virtual QgsPoint vertexAt( QgsVertexId id ) const = 0;
388 
401  virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT,
402  QgsVertexId &vertexAfter SIP_OUT,
403  int *leftOf SIP_OUT = nullptr, double epsilon = 4 * std::numeric_limits<double>::epsilon() ) const = 0;
404 
405  //low-level editing
406 
415  virtual bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) = 0;
416 
425  virtual bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) = 0;
426 
434  virtual bool deleteVertex( QgsVertexId position ) = 0;
435 
448  virtual double length() const;
449 
462  virtual double perimeter() const;
463 
476  virtual double area() const;
477 
486  virtual double segmentLength( QgsVertexId startVertex ) const = 0;
487 
489  virtual QgsPoint centroid() const;
490 
494  virtual bool isEmpty() const;
495 
499  virtual bool hasCurvedSegments() const;
500 
507  virtual QgsAbstractGeometry *segmentize( double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
508 
515  virtual QgsAbstractGeometry *toCurveType() const = 0 SIP_FACTORY;
516 
536  virtual QgsAbstractGeometry *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const = 0 SIP_FACTORY;
537 
558  virtual bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) = 0;
559 
567  virtual double vertexAngle( QgsVertexId vertex ) const = 0;
568 
572  virtual int vertexCount( int part = 0, int ring = 0 ) const = 0;
573 
577  virtual int ringCount( int part = 0 ) const = 0;
578 
584  virtual int partCount() const = 0;
585 
594  virtual bool addZValue( double zValue = 0 ) = 0;
595 
604  virtual bool addMValue( double mValue = 0 ) = 0;
605 
613  virtual bool dropZValue() = 0;
614 
622  virtual bool dropMValue() = 0;
623 
630  virtual void swapXy() = 0;
631 
637  virtual bool convertTo( QgsWkbTypes::Type type );
638 
650  virtual bool isValid( QString &error SIP_OUT, int flags = 0 ) const = 0;
651 
652 #ifndef SIP_RUN
653 
663  virtual void filterVertices( const std::function< bool( const QgsPoint & ) > &filter );
664 
679  virtual void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform );
680 
686  class CORE_EXPORT part_iterator
687  {
688  private:
689 
690  int mIndex = 0;
691  QgsAbstractGeometry *mGeometry = nullptr;
692 
693  public:
695  part_iterator() = default;
696 
698  part_iterator( QgsAbstractGeometry *g, int index );
699 
704  part_iterator &operator++();
705 
707  part_iterator operator++( int );
708 
711 
713  int partNumber() const;
714 
715  bool operator==( part_iterator other ) const;
716  bool operator!=( part_iterator other ) const { return !( *this == other ); }
717  };
718 
728  {
729  return part_iterator( this, 0 );
730  }
731 
740  part_iterator parts_end();
741 
749  QgsGeometryConstPartIterator parts() const;
750 
756  class CORE_EXPORT const_part_iterator
757  {
758  private:
759 
760  int mIndex = 0;
761  const QgsAbstractGeometry *mGeometry = nullptr;
762 
763  public:
765  const_part_iterator() = default;
766 
768  const_part_iterator( const QgsAbstractGeometry *g, int index );
769 
774  const_part_iterator &operator++();
775 
777  const_part_iterator operator++( int );
778 
780  const QgsAbstractGeometry *operator*() const;
781 
783  int partNumber() const;
784 
785  bool operator==( const_part_iterator other ) const;
786  bool operator!=( const_part_iterator other ) const { return !( *this == other ); }
787  };
788 
797  {
798  return const_part_iterator( this, 0 );
799  }
800 
808  const_part_iterator const_parts_end() const;
809 
810 
816  class CORE_EXPORT vertex_iterator
817  {
818  private:
819 
825  struct Level
826  {
827  const QgsAbstractGeometry *g = nullptr;
828  int index = 0;
829  };
830 
831  Level levels[3];
832  int depth = -1;
833 
834  void digDown();
835 
836  public:
838  vertex_iterator() = default;
839 
841  vertex_iterator( const QgsAbstractGeometry *g, int index );
842 
847  vertex_iterator &operator++();
848 
850  vertex_iterator operator++( int );
851 
853  QgsPoint operator*() const;
854 
856  QgsVertexId vertexId() const;
857 
858  bool operator==( const vertex_iterator &other ) const;
859  bool operator!=( const vertex_iterator &other ) const { return !( *this == other ); }
860  };
861 
871  {
872  return vertex_iterator( this, 0 );
873  }
874 
884  {
885  return vertex_iterator( this, childCount() );
886  }
887 #endif
888 
921  QgsGeometryPartIterator parts();
922 
923 
946  QgsVertexIterator vertices() const;
947 
954  virtual QgsAbstractGeometry *createEmptyWithSameType() const = 0 SIP_FACTORY;
955 
956  protected:
957 
963  virtual bool hasChildGeometries() const;
964 
970  virtual int childCount() const { return 0; }
971 
977  virtual QgsAbstractGeometry *childGeometry( int index ) const { Q_UNUSED( index ) return nullptr; }
978 
984  virtual QgsPoint childPoint( int index ) const;
985 
986  protected:
988 
992  void setZMTypeFromSubGeometry( const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType );
993 
998  virtual QgsRectangle calculateBoundingBox() const;
999 
1003  virtual void clearCache() const;
1004 
1005  friend class TestQgsGeometry;
1006 };
1007 
1008 
1015 struct CORE_EXPORT QgsVertexId
1016 {
1018  {
1019  SegmentVertex = 1, //start / endpoint of a segment
1020  CurveVertex
1021  };
1022 
1023  explicit QgsVertexId( int _part = -1, int _ring = -1, int _vertex = -1, VertexType _type = SegmentVertex )
1024  : part( _part )
1025  , ring( _ring )
1026  , vertex( _vertex )
1027  , type( _type )
1028  {}
1029 
1033  bool isValid() const { return part >= 0 && ring >= 0 && vertex >= 0; }
1034 
1035  bool operator==( QgsVertexId other ) const
1036  {
1037  return part == other.part && ring == other.ring && vertex == other.vertex;
1038  }
1039  bool operator!=( QgsVertexId other ) const
1040  {
1041  return part != other.part || ring != other.ring || vertex != other.vertex;
1042  }
1043  bool partEqual( QgsVertexId o ) const
1044  {
1045  return part >= 0 && o.part == part;
1046  }
1047  bool ringEqual( QgsVertexId o ) const
1048  {
1049  return partEqual( o ) && ( ring >= 0 && o.ring == ring );
1050  }
1051  bool vertexEqual( QgsVertexId o ) const
1052  {
1053  return ringEqual( o ) && ( vertex >= 0 && o.ring == ring );
1054  }
1055  bool isValid( const QgsAbstractGeometry *geom ) const
1056  {
1057  return ( part >= 0 && part < geom->partCount() ) &&
1058  ( ring < geom->ringCount( part ) ) &&
1059  ( vertex < 0 || vertex < geom->vertexCount( part, ring ) );
1060  }
1061 
1062  int part;
1063  int ring;
1064  int vertex;
1066 };
1067 
1068 #ifndef SIP_RUN
1069 
1070 template <class T>
1071 inline T qgsgeometry_cast( const QgsAbstractGeometry *geom )
1072 {
1073  return const_cast<T>( reinterpret_cast<T>( 0 )->cast( geom ) );
1074 }
1075 
1076 #endif
1077 
1078 // clazy:excludeall=qstring-allocations
1079 
1085 class CORE_EXPORT QgsVertexIterator
1086 {
1087  public:
1089  QgsVertexIterator() = default;
1090 
1093  : g( geometry )
1094  , i( g->vertices_begin() )
1095  , n( g->vertices_end() )
1096  {
1097  }
1098 
1100  bool hasNext() const
1101  {
1102  return g && g->vertices_end() != i;
1103  }
1104 
1106  QgsPoint next();
1107 
1108 #ifdef SIP_RUN
1109  QgsVertexIterator *__iter__();
1110  % MethodCode
1111  sipRes = sipCpp;
1112  % End
1113 
1114  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsPoint );
1115  % MethodCode
1116  if ( sipCpp->hasNext() )
1117  sipRes = sipConvertFromType( new QgsPoint( sipCpp->next() ), sipType_QgsPoint, Py_None );
1118  else
1119  PyErr_SetString( PyExc_StopIteration, "" );
1120  % End
1121 #endif
1122 
1123  private:
1124  const QgsAbstractGeometry *g = nullptr;
1126 
1127 };
1128 
1134 class CORE_EXPORT QgsGeometryPartIterator
1135 {
1136  public:
1138  QgsGeometryPartIterator() = default;
1139 
1142  : g( geometry )
1143  , i( g->parts_begin() )
1144  , n( g->parts_end() )
1145  {
1146  }
1147 
1149  bool hasNext() const
1150  {
1151  return g && g->parts_end() != i;
1152  }
1153 
1155  QgsAbstractGeometry *next();
1156 
1157 #ifdef SIP_RUN
1158  QgsGeometryPartIterator *__iter__();
1159  % MethodCode
1160  sipRes = sipCpp;
1161  % End
1162 
1163  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1164  % MethodCode
1165  if ( sipCpp->hasNext() )
1166  sipRes = sipConvertFromType( sipCpp->next(), sipType_QgsAbstractGeometry, NULL );
1167  else
1168  PyErr_SetString( PyExc_StopIteration, "" );
1169  % End
1170 #endif
1171 
1172  private:
1173  QgsAbstractGeometry *g = nullptr;
1175 
1176 };
1177 
1178 
1185 {
1186  public:
1188  QgsGeometryConstPartIterator() = default;
1189 
1192  : g( geometry )
1193  , i( g->const_parts_begin() )
1194  , n( g->const_parts_end() )
1195  {
1196  }
1197 
1199  bool hasNext() const
1200  {
1201  return g && g->const_parts_end() != i;
1202  }
1203 
1205  const QgsAbstractGeometry *next();
1206 
1207 #ifdef SIP_RUN
1208  QgsGeometryConstPartIterator *__iter__();
1209  % MethodCode
1210  sipRes = sipCpp;
1211  % End
1212 
1213  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1214  % MethodCode
1215  if ( sipCpp->hasNext() )
1216  sipRes = sipConvertFromType( const_cast< QgsAbstractGeometry * >( sipCpp->next() ), sipType_QgsAbstractGeometry, NULL );
1217  else
1218  PyErr_SetString( PyExc_StopIteration, "" );
1219  % End
1220 #endif
1221 
1222  private:
1223  const QgsAbstractGeometry *g = nullptr;
1225 
1226 };
1227 
1228 #endif //QGSABSTRACTGEOMETRYV2
bool isMeasure() const
Returns true if the geometry contains m values.
int precision
A rectangle specified with double values.
Definition: qgsrectangle.h:41
Java-style iterator for traversal of parts of a geometry.
QgsVertexId(int _part=-1, int _ring=-1, int _vertex=-1, VertexType _type=SegmentVertex)
virtual int childCount() const
Returns number of child geometries (for geometries with child geometries) or child points (for geomet...
bool operator!=(const_part_iterator other) const
Java-style iterator for traversal of vertices of a geometry.
Multi point geometry collection.
Definition: qgsmultipoint.h:29
bool isValid() const
Returns true if the vertex id is valid.
bool operator==(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
QVector< QgsRingSequence > QgsCoordinateSequence
Java-style iterator for const traversal of parts of a geometry.
bool operator!=(const QgsFeatureIterator &fi1, const QgsFeatureIterator &fi2)
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
virtual QgsAbstractGeometry * childGeometry(int index) const
Returns pointer to child geometry (for geometries with child geometries - i.e.
The part_iterator class provides STL-style iterator for const references to geometry parts...
SegmentationToleranceType
Segmentation tolerance as maximum angle or maximum difference between approximation and circle...
bool operator!=(const vertex_iterator &other) const
#define SIP_TYPEHINT(type)
Definition: qgis_sip.h:213
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:917
bool vertexEqual(QgsVertexId o) const
bool operator!=(QgsVertexId other) const
bool hasNext() const
Find out whether there are more parts.
QgsVertexIterator(const QgsAbstractGeometry *geometry)
Constructs iterator for the given geometry.
Perform transforms between map coordinates and device coordinates.
Definition: qgsmaptopixel.h:37
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:68
QgsGeometryPartIterator(QgsAbstractGeometry *geometry)
Constructs iterator for the given geometry.
Utility class for identifying a unique vertex within a geometry.
#define SIP_SKIP
Definition: qgis_sip.h:126
The part_iterator class provides STL-style iterator for geometry parts.
vertex_iterator vertices_end() const
Returns STL-style iterator pointing to the imaginary vertex after the last vertex of the geometry...
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
#define SIP_END
Definition: qgis_sip.h:189
Multi curve geometry collection.
Definition: qgsmulticurve.h:29
virtual int ringCount(int part=0) const =0
Returns the number of rings of which this geometry is built.
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
#define SIP_FACTORY
Definition: qgis_sip.h:76
Abstract base class for all geometries.
The vertex_iterator class provides STL-style iterator for vertices.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
AxisOrder
Axis order for GML generation.
QgsGeometryConstPartIterator(const QgsAbstractGeometry *geometry)
Constructs iterator for the given geometry.
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition: qgstracer.cpp:68
QVector< QgsPoint > QgsPointSequence
bool operator==(QgsVertexId other) const
QVector< QgsPointSequence > QgsRingSequence
bool partEqual(QgsVertexId o) const
bool ringEqual(QgsVertexId o) const
const_part_iterator const_parts_begin() const
Returns STL-style iterator pointing to the const first part of the geometry.
#define SIP_OUT
Definition: qgis_sip.h:58
#define SIP_CONVERT_TO_SUBCLASS_CODE(code)
Definition: qgis_sip.h:172
Class for doing transforms between two map coordinate systems.
#define SIP_THROW(name)
Definition: qgis_sip.h:184
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:967
Transform from source to destination CRS.
QgsMargins operator*(const QgsMargins &margins, double factor)
Returns a QgsMargins object that is formed by multiplying each component of the given margins by fact...
Definition: qgsmargins.h:242
Custom exception class for Coordinate Reference System related exceptions.
Definition: qgsexception.h:65
vertex_iterator vertices_begin() const
Returns STL-style iterator pointing to the first vertex of the geometry.
bool hasNext() const
Find out whether there are more vertices.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
bool operator!=(part_iterator other) const
part_iterator parts_begin()
Returns STL-style iterator pointing to the first part of the geometry.
double ANALYSIS_EXPORT leftOf(const QgsPoint &thepoint, const QgsPoint *p1, const QgsPoint *p2)
Returns whether &#39;thepoint&#39; is left or right of the line from &#39;p1&#39; to &#39;p2&#39;. Negative values mean left ...
Definition: MathUtils.cpp:292
bool isValid(const QgsAbstractGeometry *geom) const
bool hasNext() const
Find out whether there are more parts.