QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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>
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 
62 class CORE_EXPORT QgsAbstractGeometry
63 {
64 
65 #ifdef SIP_RUN
67  if ( qgsgeometry_cast<QgsPoint *>( sipCpp ) != nullptr )
68  sipType = sipType_QgsPoint;
69  else if ( qgsgeometry_cast<QgsLineString *>( sipCpp ) != nullptr )
70  sipType = sipType_QgsLineString;
71  else if ( qgsgeometry_cast<QgsCircularString *>( sipCpp ) != nullptr )
72  sipType = sipType_QgsCircularString;
73  else if ( qgsgeometry_cast<QgsCompoundCurve *>( sipCpp ) != nullptr )
74  sipType = sipType_QgsCompoundCurve;
75  else if ( qgsgeometry_cast<QgsTriangle *>( sipCpp ) != nullptr )
76  sipType = sipType_QgsTriangle;
77  else if ( qgsgeometry_cast<QgsPolygon *>( sipCpp ) != nullptr )
78  sipType = sipType_QgsPolygon;
79  else if ( qgsgeometry_cast<QgsCurvePolygon *>( sipCpp ) != nullptr )
80  sipType = sipType_QgsCurvePolygon;
81  else if ( qgsgeometry_cast<QgsMultiPoint *>( sipCpp ) != nullptr )
82  sipType = sipType_QgsMultiPoint;
83  else if ( qgsgeometry_cast<QgsMultiLineString *>( sipCpp ) != nullptr )
84  sipType = sipType_QgsMultiLineString;
85  else if ( qgsgeometry_cast<QgsMultiPolygon *>( sipCpp ) != nullptr )
86  sipType = sipType_QgsMultiPolygon;
87  else if ( qgsgeometry_cast<QgsMultiSurface *>( sipCpp ) != nullptr )
88  sipType = sipType_QgsMultiSurface;
89  else if ( qgsgeometry_cast<QgsMultiCurve *>( sipCpp ) != nullptr )
90  sipType = sipType_QgsMultiCurve;
91  else if ( qgsgeometry_cast<QgsGeometryCollection *>( sipCpp ) != nullptr )
92  sipType = sipType_QgsGeometryCollection;
93  else
94  sipType = 0;
95  SIP_END
96 #endif
97 
98  Q_GADGET
99 
100  public:
101 
104  {
105 
109  MaximumAngle = 0,
110 
114  MaximumDifference
115  };
116  Q_ENUM( SegmentationToleranceType )
117 
118 
120  {
121 
125  XY = 0,
126 
130  YX
131  };
133 
134 
137  QgsAbstractGeometry() = default;
138  virtual ~QgsAbstractGeometry() = default;
140  QgsAbstractGeometry &operator=( const QgsAbstractGeometry &geom );
141 
142  virtual bool operator==( const QgsAbstractGeometry &other ) const = 0;
143  virtual bool operator!=( const QgsAbstractGeometry &other ) const = 0;
144 
148  virtual QgsAbstractGeometry *clone() const = 0 SIP_FACTORY;
149 
153  virtual void clear() = 0;
154 
158  virtual QgsRectangle boundingBox() const = 0;
159 
160  //mm-sql interface
161 
166  virtual int dimension() const = 0;
167 
173  virtual QString geometryType() const = 0;
174 
180  inline QgsWkbTypes::Type wkbType() const { return mWkbType; }
181 
187  QString wktTypeStr() const;
188 
193  bool is3D() const
194  {
195  return QgsWkbTypes::hasZ( mWkbType );
196  }
197 
202  bool isMeasure() const
203  {
204  return QgsWkbTypes::hasM( mWkbType );
205  }
206 
213  virtual QgsAbstractGeometry *boundary() const = 0 SIP_FACTORY;
214 
215  //import
216 
222  virtual bool fromWkb( QgsConstWkbPtr &wkb ) = 0;
223 
228  virtual bool fromWkt( const QString &wkt ) = 0;
229 
230  //export
231 
240  virtual QByteArray asWkb() const = 0;
241 
250  virtual QString asWkt( int precision = 17 ) const = 0;
251 
263  virtual QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const = 0;
264 
276  virtual QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const = 0;
277 
287  QString asJson( int precision = 17 );
288 
299  virtual json asJsonObject( int precision = 17 ) SIP_SKIP const;
300 
301 
302  //render pipeline
303 
314  virtual void transform( const QgsCoordinateTransform &ct, QgsCoordinateTransform::TransformDirection d = QgsCoordinateTransform::ForwardTransform, bool transformZ = false ) SIP_THROW( QgsCsException ) = 0;
315 
322  virtual void transform( const QTransform &t, double zTranslate = 0.0, double zScale = 1.0,
323  double mTranslate = 0.0, double mScale = 1.0 ) = 0;
324 
329  virtual void draw( QPainter &p ) const = 0;
330 
341  virtual int vertexNumberFromVertexId( QgsVertexId id ) const = 0;
342 
350  virtual bool nextVertex( QgsVertexId &id, QgsPoint &vertex SIP_OUT ) const = 0;
351 
356  virtual void adjacentVertices( QgsVertexId vertex, QgsVertexId &previousVertex SIP_OUT, QgsVertexId &nextVertex SIP_OUT ) const = 0;
357 
362  virtual QgsCoordinateSequence coordinateSequence() const = 0;
363 
367  virtual int nCoordinates() const;
368 
372  virtual QgsPoint vertexAt( QgsVertexId id ) const = 0;
373 
386  virtual double closestSegment( const QgsPoint &pt, QgsPoint &segmentPt SIP_OUT,
387  QgsVertexId &vertexAfter SIP_OUT,
388  int *leftOf SIP_OUT = nullptr, double epsilon = 4 * std::numeric_limits<double>::epsilon() ) const = 0;
389 
390  //low-level editing
391 
400  virtual bool insertVertex( QgsVertexId position, const QgsPoint &vertex ) = 0;
401 
410  virtual bool moveVertex( QgsVertexId position, const QgsPoint &newPos ) = 0;
411 
419  virtual bool deleteVertex( QgsVertexId position ) = 0;
420 
426  virtual double length() const;
427 
433  virtual double perimeter() const;
434 
440  virtual double area() const;
441 
446  virtual double segmentLength( QgsVertexId startVertex ) const = 0;
447 
449  virtual QgsPoint centroid() const;
450 
454  virtual bool isEmpty() const;
455 
459  virtual bool hasCurvedSegments() const;
460 
467  virtual QgsAbstractGeometry *segmentize( double tolerance = M_PI / 180., SegmentationToleranceType toleranceType = MaximumAngle ) const SIP_FACTORY;
468 
475  virtual QgsAbstractGeometry *toCurveType() const = 0 SIP_FACTORY;
476 
496  virtual QgsAbstractGeometry *snappedToGrid( double hSpacing, double vSpacing, double dSpacing = 0, double mSpacing = 0 ) const = 0 SIP_FACTORY;
497 
518  virtual bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) = 0;
519 
527  virtual double vertexAngle( QgsVertexId vertex ) const = 0;
528 
532  virtual int vertexCount( int part = 0, int ring = 0 ) const = 0;
533 
537  virtual int ringCount( int part = 0 ) const = 0;
538 
544  virtual int partCount() const = 0;
545 
554  virtual bool addZValue( double zValue = 0 ) = 0;
555 
564  virtual bool addMValue( double mValue = 0 ) = 0;
565 
573  virtual bool dropZValue() = 0;
574 
582  virtual bool dropMValue() = 0;
583 
590  virtual void swapXy() = 0;
591 
597  virtual bool convertTo( QgsWkbTypes::Type type );
598 
610  virtual bool isValid( QString &error SIP_OUT, int flags = 0 ) const = 0;
611 
612 #ifndef SIP_RUN
613 
623  virtual void filterVertices( const std::function< bool( const QgsPoint & ) > &filter );
624 
639  virtual void transformVertices( const std::function< QgsPoint( const QgsPoint & ) > &transform );
640 
646  class CORE_EXPORT part_iterator
647  {
648  private:
649 
650  int mIndex = 0;
651  QgsAbstractGeometry *mGeometry = nullptr;
652 
653  public:
655  part_iterator() = default;
656 
658  part_iterator( QgsAbstractGeometry *g, int index );
659 
664  part_iterator &operator++();
665 
667  part_iterator operator++( int );
668 
671 
673  int partNumber() const;
674 
675  bool operator==( part_iterator other ) const;
676  bool operator!=( part_iterator other ) const { return !( *this == other ); }
677  };
678 
688  {
689  return part_iterator( this, 0 );
690  }
691 
700  part_iterator parts_end();
701 
709  QgsGeometryConstPartIterator parts() const;
710 
716  class CORE_EXPORT const_part_iterator
717  {
718  private:
719 
720  int mIndex = 0;
721  const QgsAbstractGeometry *mGeometry = nullptr;
722 
723  public:
725  const_part_iterator() = default;
726 
728  const_part_iterator( const QgsAbstractGeometry *g, int index );
729 
734  const_part_iterator &operator++();
735 
737  const_part_iterator operator++( int );
738 
740  const QgsAbstractGeometry *operator*() const;
741 
743  int partNumber() const;
744 
745  bool operator==( const_part_iterator other ) const;
746  bool operator!=( const_part_iterator other ) const { return !( *this == other ); }
747  };
748 
757  {
758  return const_part_iterator( this, 0 );
759  }
760 
768  const_part_iterator const_parts_end() const;
769 
770 
776  class CORE_EXPORT vertex_iterator
777  {
778  private:
779 
785  struct Level
786  {
787  const QgsAbstractGeometry *g = nullptr;
788  int index = 0;
789  };
790 
791  Level levels[3];
792  int depth = -1;
793 
794  void digDown();
795 
796  public:
798  vertex_iterator() = default;
799 
801  vertex_iterator( const QgsAbstractGeometry *g, int index );
802 
807  vertex_iterator &operator++();
808 
810  vertex_iterator operator++( int );
811 
813  QgsPoint operator*() const;
814 
816  QgsVertexId vertexId() const;
817 
818  bool operator==( const vertex_iterator &other ) const;
819  bool operator!=( const vertex_iterator &other ) const { return !( *this == other ); }
820  };
821 
831  {
832  return vertex_iterator( this, 0 );
833  }
834 
844  {
845  return vertex_iterator( this, childCount() );
846  }
847 #endif
848 
881  QgsGeometryPartIterator parts();
882 
883 
906  QgsVertexIterator vertices() const;
907 
914  virtual QgsAbstractGeometry *createEmptyWithSameType() const = 0 SIP_FACTORY;
915 
916  protected:
917 
923  virtual bool hasChildGeometries() const;
924 
930  virtual int childCount() const { return 0; }
931 
937  virtual QgsAbstractGeometry *childGeometry( int index ) const { Q_UNUSED( index ) return nullptr; }
938 
944  virtual QgsPoint childPoint( int index ) const;
945 
946  protected:
948 
952  void setZMTypeFromSubGeometry( const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType );
953 
958  virtual QgsRectangle calculateBoundingBox() const;
959 
963  virtual void clearCache() const;
964 
965  friend class TestQgsGeometry;
966 };
967 
968 
975 struct CORE_EXPORT QgsVertexId
976 {
978  {
979  SegmentVertex = 1, //start / endpoint of a segment
980  CurveVertex
981  };
982 
983  explicit QgsVertexId( int _part = -1, int _ring = -1, int _vertex = -1, VertexType _type = SegmentVertex )
984  : part( _part )
985  , ring( _ring )
986  , vertex( _vertex )
987  , type( _type )
988  {}
989 
993  bool isValid() const { return part >= 0 && ring >= 0 && vertex >= 0; }
994 
995  bool operator==( QgsVertexId other ) const
996  {
997  return part == other.part && ring == other.ring && vertex == other.vertex;
998  }
999  bool operator!=( QgsVertexId other ) const
1000  {
1001  return part != other.part || ring != other.ring || vertex != other.vertex;
1002  }
1003  bool partEqual( QgsVertexId o ) const
1004  {
1005  return part >= 0 && o.part == part;
1006  }
1007  bool ringEqual( QgsVertexId o ) const
1008  {
1009  return partEqual( o ) && ( ring >= 0 && o.ring == ring );
1010  }
1011  bool vertexEqual( QgsVertexId o ) const
1012  {
1013  return ringEqual( o ) && ( vertex >= 0 && o.ring == ring );
1014  }
1015  bool isValid( const QgsAbstractGeometry *geom ) const
1016  {
1017  return ( part >= 0 && part < geom->partCount() ) &&
1018  ( ring < geom->ringCount( part ) ) &&
1019  ( vertex < 0 || vertex < geom->vertexCount( part, ring ) );
1020  }
1021 
1022  int part;
1023  int ring;
1024  int vertex;
1026 };
1027 
1028 #ifndef SIP_RUN
1029 
1030 template <class T>
1031 inline T qgsgeometry_cast( const QgsAbstractGeometry *geom )
1032 {
1033  return const_cast<T>( reinterpret_cast<T>( 0 )->cast( geom ) );
1034 }
1035 
1036 #endif
1037 
1038 // clazy:excludeall=qstring-allocations
1039 
1045 class CORE_EXPORT QgsVertexIterator
1046 {
1047  public:
1049  QgsVertexIterator() = default;
1050 
1053  : g( geometry )
1054  , i( g->vertices_begin() )
1055  , n( g->vertices_end() )
1056  {
1057  }
1058 
1060  bool hasNext() const
1061  {
1062  return g && g->vertices_end() != i;
1063  }
1064 
1066  QgsPoint next();
1067 
1068 #ifdef SIP_RUN
1069  QgsVertexIterator *__iter__();
1070  % MethodCode
1071  sipRes = sipCpp;
1072  % End
1073 
1074  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsPoint );
1075  % MethodCode
1076  if ( sipCpp->hasNext() )
1077  sipRes = sipConvertFromType( new QgsPoint( sipCpp->next() ), sipType_QgsPoint, Py_None );
1078  else
1079  PyErr_SetString( PyExc_StopIteration, "" );
1080  % End
1081 #endif
1082 
1083  private:
1084  const QgsAbstractGeometry *g = nullptr;
1086 
1087 };
1088 
1094 class CORE_EXPORT QgsGeometryPartIterator
1095 {
1096  public:
1098  QgsGeometryPartIterator() = default;
1099 
1102  : g( geometry )
1103  , i( g->parts_begin() )
1104  , n( g->parts_end() )
1105  {
1106  }
1107 
1109  bool hasNext() const
1110  {
1111  return g && g->parts_end() != i;
1112  }
1113 
1115  QgsAbstractGeometry *next();
1116 
1117 #ifdef SIP_RUN
1118  QgsGeometryPartIterator *__iter__();
1119  % MethodCode
1120  sipRes = sipCpp;
1121  % End
1122 
1123  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1124  % MethodCode
1125  if ( sipCpp->hasNext() )
1126  sipRes = sipConvertFromType( sipCpp->next(), sipType_QgsAbstractGeometry, NULL );
1127  else
1128  PyErr_SetString( PyExc_StopIteration, "" );
1129  % End
1130 #endif
1131 
1132  private:
1133  QgsAbstractGeometry *g = nullptr;
1135 
1136 };
1137 
1138 
1145 {
1146  public:
1148  QgsGeometryConstPartIterator() = default;
1149 
1152  : g( geometry )
1153  , i( g->const_parts_begin() )
1154  , n( g->const_parts_end() )
1155  {
1156  }
1157 
1159  bool hasNext() const
1160  {
1161  return g && g->const_parts_end() != i;
1162  }
1163 
1165  const QgsAbstractGeometry *next();
1166 
1167 #ifdef SIP_RUN
1168  QgsGeometryConstPartIterator *__iter__();
1169  % MethodCode
1170  sipRes = sipCpp;
1171  % End
1172 
1173  SIP_PYOBJECT __next__() SIP_TYPEHINT( QgsAbstractGeometry );
1174  % MethodCode
1175  if ( sipCpp->hasNext() )
1176  sipRes = sipConvertFromType( const_cast< QgsAbstractGeometry * >( sipCpp->next() ), sipType_QgsAbstractGeometry, NULL );
1177  else
1178  PyErr_SetString( PyExc_StopIteration, "" );
1179  % End
1180 #endif
1181 
1182  private:
1183  const QgsAbstractGeometry *g = nullptr;
1185 
1186 };
1187 
1188 #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:206
static bool hasZ(Type type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:771
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:119
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:182
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:69
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.
nlohmann::json json
Definition: qgsjsonutils.h:27
double closestSegment(const QgsPolylineXY &pl, const QgsPointXY &pt, int &vertexAfter, double epsilon)
Definition: qgstracer.cpp:68
nlohmann::json json
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:51
#define SIP_CONVERT_TO_SUBCLASS_CODE(code)
Definition: qgis_sip.h:165
Class for doing transforms between two map coordinate systems.
#define SIP_THROW(name)
Definition: qgis_sip.h:177
static bool hasM(Type type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:821
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.