QGIS API Documentation  3.9.0-Master (224899f119)
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 <nlohmann/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 
310 
311  //render pipeline
312 
323  virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) SIP_THROW( QgsCsException ) = 0;
324 
331  virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0,
332  double mTranslate = 0.0, double mScale = 1.0 ) = 0;
333 
338  virtual void draw( QPainter &p ) const = 0;
339 
350  virtual int vertexNumberFromVertexId( QgsVertexId id ) const = 0;
351 
359  virtual bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const = 0;
360 
365  virtual void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const = 0;
366 
371  virtual QgsCoordinateSequence coordinateSequence() const = 0;
372 
376  virtual int nCoordinates() const;
377 
381  virtual QgsPoint vertexAt( QgsVertexId id ) const = 0;
382 
395  virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT,
396  QgsVertexId &vertexAfter SIP_OUT,
397  int *leftOf SIP_OUT = nullptr, double epsilon = 4 * std::numeric_limits<double>::epsilon() ) const = 0;
398 
399  //low-level editing
400 
409  virtual bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) = 0;
410 
419  virtual bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) = 0;
420 
428  virtual bool deleteVertex( QgsVertexId position ) = 0;
429 
442  virtual double length() const;
443 
456  virtual double perimeter() const;
457 
470  virtual double area() const;
471 
480  virtual double segmentLength( QgsVertexId startVertex ) const = 0;
481 
483  virtual QgsPoint centroid() const;
484 
488  virtual bool isEmpty() const;
489 
493  virtual bool hasCurvedSegments() const;
494 
501  virtual QgsAbstractGeometry *segmentize( double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
502 
509  virtual QgsAbstractGeometry *toCurveType() const = 0 SIP_FACTORY;
510 
530  virtual QgsAbstractGeometry *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const = 0 SIP_FACTORY;
531 
552  virtual bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) = 0;
553 
561  virtual double vertexAngle( QgsVertexId vertex ) const = 0;
562 
566  virtual int vertexCount( int part = 0, int ring = 0 ) const = 0;
567 
571  virtual int ringCount( int part = 0 ) const = 0;
572 
578  virtual int partCount() const = 0;
579 
588  virtual bool addZValue( double zValue = 0 ) = 0;
589 
598  virtual bool addMValue( double mValue = 0 ) = 0;
599 
607  virtual bool dropZValue() = 0;
608 
616  virtual bool dropMValue() = 0;
617 
624  virtual void swapXy() = 0;
625 
631  virtual bool convertTo( QgsWkbTypes::Type type );
632 
644  virtual bool isValid( QString &error SIP_OUT, int flags = 0 ) const = 0;
645 
646 #ifndef SIP_RUN
647 
657  virtual void filterVertices( const std::function< bool( const QgsPoint & ) > &filter );
658 
673  virtual void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform );
674 
680  class CORE_EXPORT part_iterator
681  {
682  private:
683 
684  int mIndex = 0;
685  QgsAbstractGeometry *mGeometry = nullptr;
686 
687  public:
689  part_iterator() = default;
690 
692  part_iterator( QgsAbstractGeometry *g, int index );
693 
698  part_iterator &operator++();
699 
701  part_iterator operator++( int );
702 
705 
707  int partNumber() const;
708 
709  bool operator==( part_iterator other ) const;
710  bool operator!=( part_iterator other ) const { return !( *this == other ); }
711  };
712 
722  {
723  return part_iterator( this, 0 );
724  }
725 
734  part_iterator parts_end();
735 
743  QgsGeometryConstPartIterator parts() const;
744 
750  class CORE_EXPORT const_part_iterator
751  {
752  private:
753 
754  int mIndex = 0;
755  const QgsAbstractGeometry *mGeometry = nullptr;
756 
757  public:
759  const_part_iterator() = default;
760 
762  const_part_iterator( const QgsAbstractGeometry *g, int index );
763 
768  const_part_iterator &operator++();
769 
771  const_part_iterator operator++( int );
772 
774  const QgsAbstractGeometry *operator*() const;
775 
777  int partNumber() const;
778 
779  bool operator==( const_part_iterator other ) const;
780  bool operator!=( const_part_iterator other ) const { return !( *this == other ); }
781  };
782 
791  {
792  return const_part_iterator( this, 0 );
793  }
794 
802  const_part_iterator const_parts_end() const;
803 
804 
810  class CORE_EXPORT vertex_iterator
811  {
812  private:
813 
819  struct Level
820  {
821  const QgsAbstractGeometry *g = nullptr;
822  int index = 0;
823  };
824 
825  Level levels[3];
826  int depth = -1;
827 
828  void digDown();
829 
830  public:
832  vertex_iterator() = default;
833 
835  vertex_iterator( const QgsAbstractGeometry *g, int index );
836 
841  vertex_iterator &operator++();
842 
844  vertex_iterator operator++( int );
845 
847  QgsPoint operator*() const;
848 
850  QgsVertexId vertexId() const;
851 
852  bool operator==( const vertex_iterator &other ) const;
853  bool operator!=( const vertex_iterator &other ) const { return !( *this == other ); }
854  };
855 
865  {
866  return vertex_iterator( this, 0 );
867  }
868 
878  {
879  return vertex_iterator( this, childCount() );
880  }
881 #endif
882 
915  QgsGeometryPartIterator parts();
916 
917 
940  QgsVertexIterator vertices() const;
941 
948  virtual QgsAbstractGeometry *createEmptyWithSameType() const = 0 SIP_FACTORY;
949 
950  protected:
951 
957  virtual bool hasChildGeometries() const;
958 
964  virtual int childCount() const { return 0; }
965 
971  virtual QgsAbstractGeometry *childGeometry( int index ) const { Q_UNUSED( index ) return nullptr; }
972 
978  virtual QgsPoint childPoint( int index ) const;
979 
980  protected:
982 
986  void setZMTypeFromSubGeometry( const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType );
987 
992  virtual QgsRectangle calculateBoundingBox() const;
993 
997  virtual void clearCache() const;
998 
999  friend class TestQgsGeometry;
1000 };
1001 
1002 
1009 struct CORE_EXPORT QgsVertexId
1010 {
1012  {
1013  SegmentVertex = 1, //start / endpoint of a segment
1014  CurveVertex
1015  };
1016 
1017  explicit QgsVertexId( int _part = -1, int _ring = -1, int _vertex = -1, VertexType _type = SegmentVertex )
1018  : part( _part )
1019  , ring( _ring )
1020  , vertex( _vertex )
1021  , type( _type )
1022  {}
1023 
1027  bool isValid() const { return part >= 0 && ring >= 0 && vertex >= 0; }
1028 
1029  bool operator==( QgsVertexId other ) const
1030  {
1031  return part == other.part && ring == other.ring && vertex == other.vertex;
1032  }
1033  bool operator!=( QgsVertexId other ) const
1034  {
1035  return part != other.part || ring != other.ring || vertex != other.vertex;
1036  }
1037  bool partEqual( QgsVertexId o ) const
1038  {
1039  return part >= 0 && o.part == part;
1040  }
1041  bool ringEqual( QgsVertexId o ) const
1042  {
1043  return partEqual( o ) && ( ring >= 0 && o.ring == ring );
1044  }
1045  bool vertexEqual( QgsVertexId o ) const
1046  {
1047  return ringEqual( o ) && ( vertex >= 0 && o.ring == ring );
1048  }
1049  bool isValid( const QgsAbstractGeometry *geom ) const
1050  {
1051  return ( part >= 0 && part < geom->partCount() ) &&
1052  ( ring < geom->ringCount( part ) ) &&
1053  ( vertex < 0 || vertex < geom->vertexCount( part, ring ) );
1054  }
1055 
1056  int part;
1057  int ring;
1058  int vertex;
1060 };
1061 
1062 #ifndef SIP_RUN
1063 
1064 template <class T>
1065 inline T qgsgeometry_cast( const QgsAbstractGeometry *geom )
1066 {
1067  return const_cast<T>( reinterpret_cast<T>( 0 )->cast( geom ) );
1068 }
1069 
1070 #endif
1071 
1072 // clazy:excludeall=qstring-allocations
1073 
1079 class CORE_EXPORT QgsVertexIterator
1080 {
1081  public:
1083  QgsVertexIterator() = default;
1084 
1087  : g( geometry )
1088  , i( g->vertices_begin() )
1089  , n( g->vertices_end() )
1090  {
1091  }
1092 
1094  bool hasNext() const
1095  {
1096  return g && g->vertices_end() != i;
1097  }
1098 
1100  QgsPoint next();
1101 
1102 #ifdef SIP_RUN
1103  QgsVertexIterator *__iter__();
1104  % MethodCode
1105  sipRes = sipCpp;
1106  % End
1107 
1108  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsPoint );
1109  % MethodCode
1110  if ( sipCpp->hasNext() )
1111  sipRes = sipConvertFromType( new QgsPoint( sipCpp->next() ), sipType_QgsPoint, Py_None );
1112  else
1113  PyErr_SetString( PyExc_StopIteration, "" );
1114  % End
1115 #endif
1116 
1117  private:
1118  const QgsAbstractGeometry *g = nullptr;
1120 
1121 };
1122 
1128 class CORE_EXPORT QgsGeometryPartIterator
1129 {
1130  public:
1132  QgsGeometryPartIterator() = default;
1133 
1136  : g( geometry )
1137  , i( g->parts_begin() )
1138  , n( g->parts_end() )
1139  {
1140  }
1141 
1143  bool hasNext() const
1144  {
1145  return g && g->parts_end() != i;
1146  }
1147 
1149  QgsAbstractGeometry *next();
1150 
1151 #ifdef SIP_RUN
1152  QgsGeometryPartIterator *__iter__();
1153  % MethodCode
1154  sipRes = sipCpp;
1155  % End
1156 
1157  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1158  % MethodCode
1159  if ( sipCpp->hasNext() )
1160  sipRes = sipConvertFromType( sipCpp->next(), sipType_QgsAbstractGeometry, NULL );
1161  else
1162  PyErr_SetString( PyExc_StopIteration, "" );
1163  % End
1164 #endif
1165 
1166  private:
1167  QgsAbstractGeometry *g = nullptr;
1169 
1170 };
1171 
1172 
1179 {
1180  public:
1182  QgsGeometryConstPartIterator() = default;
1183 
1186  : g( geometry )
1187  , i( g->const_parts_begin() )
1188  , n( g->const_parts_end() )
1189  {
1190  }
1191 
1193  bool hasNext() const
1194  {
1195  return g && g->const_parts_end() != i;
1196  }
1197 
1199  const QgsAbstractGeometry *next();
1200 
1201 #ifdef SIP_RUN
1202  QgsGeometryConstPartIterator *__iter__();
1203  % MethodCode
1204  sipRes = sipCpp;
1205  % End
1206 
1207  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1208  % MethodCode
1209  if ( sipCpp->hasNext() )
1210  sipRes = sipConvertFromType( const_cast< QgsAbstractGeometry * >( sipCpp->next() ), sipType_QgsAbstractGeometry, NULL );
1211  else
1212  PyErr_SetString( PyExc_StopIteration, "" );
1213  % End
1214 #endif
1215 
1216  private:
1217  const QgsAbstractGeometry *g = nullptr;
1219 
1220 };
1221 
1222 #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;. Negativ values mean left a...
Definition: MathUtils.cpp:292
bool isValid(const QgsAbstractGeometry *geom) const
bool hasNext() const
Find out whether there are more parts.