QGIS API Documentation  2.18.3-Las Palmas (77b8c3d)
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.
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
void close()
Closes the line string by appending the first point to the end of the line, if it is not already clos...
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
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
bool operator==(const QgsPolygonV2 &other) const
QgsWKBTypes::Type readHeader() const
Definition: qgswkbptr.cpp:38
Polygon geometry type.
Definition: qgspolygonv2.h:29
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
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.
bool isMeasure() const
Returns true if the geometry contains m values.
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 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)
virtual bool hasCurvedSegments() const
Returns true if the geometry contains curved segments.
bool operator!=(const QgsPolygonV2 &other) const
void setZMTypeFromSubGeometry(const QgsAbstractGeometryV2 *subggeom, QgsWKBTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
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.
virtual bool isClosed() const
Returns true if the curve is closed.
Definition: qgscurvev2.cpp:29
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.
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.
QgsCurveV2 * mExteriorRing