QGIS API Documentation  2.18.21-Las Palmas (9fba24a)
qgspolygonv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgspolygonv2.cpp
3  ----------------
4  begin : September 2014
5  copyright : (C) 2014 by Marco Hugentobler
6  email : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This program is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU General Public License as published by *
13  * the Free Software Foundation; either version 2 of the License, or *
14  * (at your option) any later version. *
15  * *
16  ***************************************************************************/
17 
18 #include "qgspolygonv2.h"
19 #include "qgsapplication.h"
20 #include "qgsgeometryutils.h"
21 #include "qgslinestringv2.h"
22 #include "qgsmultilinestringv2.h"
23 #include "qgswkbptr.h"
24 
27 {
29 }
30 
31 bool QgsPolygonV2::operator==( const QgsPolygonV2& other ) const
32 {
33  //run cheap checks first
34  if ( mWkbType != other.mWkbType )
35  return false;
36 
37  if (( !mExteriorRing && other.mExteriorRing ) || ( mExteriorRing && !other.mExteriorRing ) )
38  return false;
39 
40  if ( mInteriorRings.count() != other.mInteriorRings.count() )
41  return false;
42 
43  // compare rings
44  if ( mExteriorRing && other.mExteriorRing )
45  {
46  if ( *mExteriorRing != *other.mExteriorRing )
47  return false;
48  }
49 
50  for ( int i = 0; i < mInteriorRings.count(); ++i )
51  {
52  if (( !mInteriorRings.at( i ) && other.mInteriorRings.at( i ) ) ||
53  ( mInteriorRings.at( i ) && !other.mInteriorRings.at( i ) ) )
54  return false;
55 
56  if ( mInteriorRings.at( i ) && other.mInteriorRings.at( i ) &&
57  *mInteriorRings.at( i ) != *other.mInteriorRings.at( i ) )
58  return false;
59  }
60 
61  return true;
62 }
63 
64 bool QgsPolygonV2::operator!=( const QgsPolygonV2& other ) const
65 {
66  return !operator==( other );
67 }
68 
70 {
71  return new QgsPolygonV2( *this );
72 }
73 
75 {
78 }
79 
81 {
82  clear();
83  if ( !wkbPtr )
84  {
85  return false;
86  }
87 
88  QgsWKBTypes::Type type = wkbPtr.readHeader();
90  {
91  return false;
92  }
93  mWkbType = type;
94 
95  QgsWKBTypes::Type ringType;
96  switch ( mWkbType )
97  {
99  ringType = QgsWKBTypes::LineStringZ;
100  break;
102  ringType = QgsWKBTypes::LineStringM;
103  break;
105  ringType = QgsWKBTypes::LineStringZM;
106  break;
108  ringType = QgsWKBTypes::LineString25D;
109  break;
110  default:
111  ringType = QgsWKBTypes::LineString;
112  break;
113  }
114 
115  int nRings;
116  wkbPtr >> nRings;
117  for ( int i = 0; i < nRings; ++i )
118  {
119  QgsLineStringV2* line = new QgsLineStringV2();
120  line->fromWkbPoints( ringType, wkbPtr );
121  /*if ( !line->isRing() )
122  {
123  delete line; continue;
124  }*/
125 
126  if ( !mExteriorRing )
127  {
128  mExteriorRing = line;
129  }
130  else
131  {
132  mInteriorRings.append( line );
133  }
134  }
135 
136  return true;
137 }
138 
140 {
141  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
142  if ( mExteriorRing )
143  {
144  // Endianness and WkbType is not stored for LinearRings
145  size += mExteriorRing->wkbSize() - ( sizeof( char ) + sizeof( quint32 ) );
146  }
147  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
148  {
149  // Endianness and WkbType is not stored for LinearRings
150  size += curve->wkbSize() - ( sizeof( char ) + sizeof( quint32 ) );
151  }
152  return size;
153 }
154 
155 unsigned char* QgsPolygonV2::asWkb( int& binarySize ) const
156 {
157  binarySize = wkbSize();
158  unsigned char* geomPtr = new unsigned char[binarySize];
159  QgsWkbPtr wkb( geomPtr, binarySize );
160  wkb << static_cast<char>( QgsApplication::endian() );
161  wkb << static_cast<quint32>( wkbType() );
162  wkb << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
163  if ( mExteriorRing )
164  {
165  QgsPointSequenceV2 pts;
166  mExteriorRing->points( pts );
168  }
169  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
170  {
171  QgsPointSequenceV2 pts;
172  curve->points( pts );
173  QgsGeometryUtils::pointsToWKB( wkb, pts, curve->is3D(), curve->isMeasure() );
174  }
175 
176  return geomPtr;
177 }
178 
180 {
181  if ( !ring )
182  return;
183 
184  if ( ring->hasCurvedSegments() )
185  {
186  //can't add a curved ring to a QgsPolygonV2
187  QgsLineStringV2* segmented = ring->curveToLine();
188  delete ring;
189  ring = segmented;
190  }
191 
192  QgsLineStringV2* lineString = dynamic_cast< QgsLineStringV2*>( ring );
193  if ( lineString && !lineString->isClosed() )
194  {
195  lineString->close();
196  }
197 
199  {
201  mInteriorRings.append( ring );
202  }
203  else
204  {
206  }
207  clearCache();
208 }
209 
211 {
212  if ( !ring )
213  {
214  return;
215  }
216  delete mExteriorRing;
217 
218  if ( ring->hasCurvedSegments() )
219  {
220  //need to segmentize ring as polygon does not support curves
221  QgsCurveV2* line = ring->segmentize();
222  delete ring;
223  ring = line;
224  }
225 
226  QgsLineStringV2* lineString = dynamic_cast< QgsLineStringV2*>( ring );
227  if ( lineString && !lineString->isClosed() )
228  {
229  lineString->close();
230  }
231 
232  mExteriorRing = ring;
233 
234  //set proper wkb type
236 
237  //match dimensionality for rings
238  Q_FOREACH ( QgsCurveV2* ring, mInteriorRings )
239  {
240  ring->convertTo( mExteriorRing->wkbType() );
241  }
242 
243  clearCache();
244 }
245 
247 {
248  if ( !mExteriorRing )
249  return nullptr;
250 
251  if ( mInteriorRings.isEmpty() )
252  {
253  return mExteriorRing->clone();
254  }
255  else
256  {
257  QgsMultiLineStringV2* multiLine = new QgsMultiLineStringV2();
258  multiLine->addGeometry( mExteriorRing->clone() );
259  int nInteriorRings = mInteriorRings.size();
260  for ( int i = 0; i < nInteriorRings; ++i )
261  {
262  multiLine->addGeometry( mInteriorRings.at( i )->clone() );
263  }
264  return multiLine;
265  }
266 }
267 
269 {
270  return clone();
271 }
272 
274 {
275  QgsCurvePolygonV2* curvePolygon = new QgsCurvePolygonV2();
276  curvePolygon->setExteriorRing( mExteriorRing->clone() );
277  int nInteriorRings = mInteriorRings.size();
278  for ( int i = 0; i < nInteriorRings; ++i )
279  {
280  curvePolygon->addInteriorRing( mInteriorRings.at( i )->clone() );
281  }
282  return curvePolygon;
283 }
void clear() override
Clears the geometry, ie reset it to a null geometry.
void close()
Closes the line string by appending the first point to the end of the line, if it is not already clos...
bool operator!=(const QgsPolygonV2 &other) const
virtual bool fromWkb(QgsConstWkbPtr wkb) override
Sets the geometry from a WKB string.
virtual void addInteriorRing(QgsCurveV2 *ring)
Adds an interior ring to the geometry (takes ownership)
void clear() override
Clears the geometry, ie reset it to a null geometry.
virtual bool addGeometry(QgsAbstractGeometryV2 *g) override
Adds a geometry and takes ownership.
static void pointsToWKB(QgsWkbPtr &wkb, const QgsPointSequenceV2 &points, bool is3D, bool isMeasure)
Returns a LinearRing { uint32 numPoints; Point points[numPoints]; }.
const T & at(int i) const
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
Abstract base class for all geometries.
unsigned char * asWkb(int &binarySize) const override
Returns a WKB representation of the geometry.
virtual QgsCurveV2 * clone() const override=0
Clones the geometry by performing a deep copy.
static endian_t endian()
Returns whether this machine uses big or little endian.
Multi line string geometry collection.
virtual int wkbSize() const =0
Returns the size of the WKB representation of the geometry.
int size() const
virtual void clearCache() const override
Clears any cached parameters associated with the geometry, eg bounding boxes.
Definition: qgssurfacev2.h:48
Polygon geometry type.
Definition: qgspolygonv2.h:29
QgsAbstractGeometryV2 * toCurveType() const override
Returns the geometry converted to the more generic curve type QgsCurvePolygonV2.
int count(const T &value) const
void append(const T &value)
virtual void setExteriorRing(QgsCurveV2 *ring) override
Sets the exterior ring of the polygon.
virtual bool isClosed() const
Returns true if the curve is closed.
Definition: qgscurvev2.cpp:29
Line string geometry type, with support for z-dimension and m-values.
QgsCurveV2 * segmentize(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const override
Returns a geometry without curves.
Definition: qgscurvev2.cpp:98
bool isMeasure() const
Returns true if the geometry contains m values.
bool isEmpty() const
virtual QgsPolygonV2 * clone() const override
Clones the geometry by performing a deep copy.
void addInteriorRing(QgsCurveV2 *ring) override
Adds an interior ring to the geometry (takes ownership)
void setZMTypeFromSubGeometry(const QgsAbstractGeometryV2 *subggeom, QgsWKBTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
bool operator==(const QgsPolygonV2 &other) const
virtual bool convertTo(QgsWKBTypes::Type type)
Converts the geometry to a specified type.
QList< QgsCurveV2 * > mInteriorRings
virtual void setExteriorRing(QgsCurveV2 *ring)
Sets the exterior ring of the polygon.
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
QgsPolygonV2 * surfaceToPolygon() const override
virtual QgsLineStringV2 * curveToLine(double tolerance=M_PI_2/90, SegmentationToleranceType toleranceType=MaximumAngle) const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
virtual QgsAbstractGeometryV2 * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:366
Curve polygon geometry type.
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:38
Abstract base class for curved geometry type.
Definition: qgscurvev2.h:32
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
virtual void points(QgsPointSequenceV2 &pt) const =0
Returns a list of points within the curve.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
QgsCurveV2 * mExteriorRing