QGIS API Documentation  2.14.11-Essen
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 "qgswkbptr.h"
23 
26 {
28 }
29 
30 bool QgsPolygonV2::operator==( const QgsPolygonV2& other ) const
31 {
32  //run cheap checks first
33  if ( mWkbType != other.mWkbType )
34  return false;
35 
36  if (( !mExteriorRing && other.mExteriorRing ) || ( mExteriorRing && !other.mExteriorRing ) )
37  return false;
38 
39  if ( mInteriorRings.count() != other.mInteriorRings.count() )
40  return false;
41 
42  // compare rings
43  if ( mExteriorRing && other.mExteriorRing )
44  {
45  if ( *mExteriorRing != *other.mExteriorRing )
46  return false;
47  }
48 
49  for ( int i = 0; i < mInteriorRings.count(); ++i )
50  {
51  if (( !mInteriorRings.at( i ) && other.mInteriorRings.at( i ) ) ||
52  ( mInteriorRings.at( i ) && !other.mInteriorRings.at( i ) ) )
53  return false;
54 
55  if ( mInteriorRings.at( i ) && other.mInteriorRings.at( i ) &&
56  *mInteriorRings.at( i ) != *other.mInteriorRings.at( i ) )
57  return false;
58  }
59 
60  return true;
61 }
62 
63 bool QgsPolygonV2::operator!=( const QgsPolygonV2& other ) const
64 {
65  return !operator==( other );
66 }
67 
69 {
70  return new QgsPolygonV2( *this );
71 }
72 
74 {
75  clear();
76  if ( !wkbPtr )
77  {
78  return false;
79  }
80 
81  QgsWKBTypes::Type type = wkbPtr.readHeader();
83  {
84  return false;
85  }
86  mWkbType = type;
87 
88  QgsWKBTypes::Type ringType;
89  switch ( mWkbType )
90  {
92  ringType = QgsWKBTypes::LineStringZ;
93  break;
95  ringType = QgsWKBTypes::LineStringM;
96  break;
98  ringType = QgsWKBTypes::LineStringZM;
99  break;
101  ringType = QgsWKBTypes::LineString25D;
102  break;
103  default:
104  ringType = QgsWKBTypes::LineString;
105  break;
106  }
107 
108  int nRings;
109  wkbPtr >> nRings;
110  for ( int i = 0; i < nRings; ++i )
111  {
112  QgsLineStringV2* line = new QgsLineStringV2();
113  line->fromWkbPoints( ringType, wkbPtr );
114  /*if ( !line->isRing() )
115  {
116  delete line; continue;
117  }*/
118 
119  if ( !mExteriorRing )
120  {
121  mExteriorRing = line;
122  }
123  else
124  {
125  mInteriorRings.append( line );
126  }
127  }
128 
129  return true;
130 }
131 
133 {
134  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
135  if ( mExteriorRing )
136  {
137  // Endianness and WkbType is not stored for LinearRings
138  size += mExteriorRing->wkbSize() - ( sizeof( char ) + sizeof( quint32 ) );
139  }
140  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
141  {
142  // Endianness and WkbType is not stored for LinearRings
143  size += curve->wkbSize() - ( sizeof( char ) + sizeof( quint32 ) );
144  }
145  return size;
146 }
147 
148 unsigned char* QgsPolygonV2::asWkb( int& binarySize ) const
149 {
150  binarySize = wkbSize();
151  unsigned char* geomPtr = new unsigned char[binarySize];
152  QgsWkbPtr wkb( geomPtr, binarySize );
153  wkb << static_cast<char>( QgsApplication::endian() );
154  wkb << static_cast<quint32>( wkbType() );
155  wkb << static_cast<quint32>(( nullptr != mExteriorRing ) + mInteriorRings.size() );
156  if ( mExteriorRing )
157  {
158  QgsPointSequenceV2 pts;
159  mExteriorRing->points( pts );
161  }
162  Q_FOREACH ( const QgsCurveV2* curve, mInteriorRings )
163  {
164  QgsPointSequenceV2 pts;
165  curve->points( pts );
166  QgsGeometryUtils::pointsToWKB( wkb, pts, curve->is3D(), curve->isMeasure() );
167  }
168 
169  return geomPtr;
170 }
171 
173 {
174  if ( !ring )
175  return;
176 
177  if ( ring->hasCurvedSegments() )
178  {
179  //can't add a curved ring to a QgsPolygonV2
180  QgsLineStringV2* segmented = ring->curveToLine();
181  delete ring;
182  ring = segmented;
183  }
184 
185  QgsLineStringV2* lineString = dynamic_cast< QgsLineStringV2*>( ring );
186  if ( lineString && !lineString->isClosed() )
187  {
188  lineString->close();
189  }
190 
192  {
194  mInteriorRings.append( ring );
195  }
196  else
197  {
199  }
200  clearCache();
201 }
202 
204 {
205  if ( !ring )
206  {
207  return;
208  }
209  delete mExteriorRing;
210 
211  if ( ring->hasCurvedSegments() )
212  {
213  //need to segmentize ring as polygon does not support curves
214  QgsCurveV2* line = ring->segmentize();
215  delete ring;
216  ring = line;
217  }
218 
219  QgsLineStringV2* lineString = dynamic_cast< QgsLineStringV2*>( ring );
220  if ( lineString && !lineString->isClosed() )
221  {
222  lineString->close();
223  }
224 
225  mExteriorRing = ring;
226 
227  //set proper wkb type
229 
230  //match dimensionality for rings
231  Q_FOREACH ( QgsCurveV2* ring, mInteriorRings )
232  {
233  ring->convertTo( mExteriorRing->wkbType() );
234  }
235 
236  clearCache();
237 }
238 
240 {
241  return clone();
242 }
243 
245 {
246  QgsCurvePolygonV2* curvePolygon = new QgsCurvePolygonV2();
247  curvePolygon->setExteriorRing( mExteriorRing->clone() );
248  int nInteriorRings = mInteriorRings.size();
249  for ( int i = 0; i < nInteriorRings; ++i )
250  {
251  curvePolygon->addInteriorRing( mInteriorRings.at( i )->clone() );
252  }
253  return curvePolygon;
254 }
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.
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.
QgsCurveV2 * segmentize() const override
Returns a geometry without curves.
Definition: qgscurvev2.cpp:82
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.
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:45
Polygon geometry type.
Definition: qgspolygonv2.h:29
QgsAbstractGeometryV2 * toCurveType() const override
Returns the geometry converted to 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:27
Line string geometry type, with support for z-dimension and m-values.
bool isMeasure() const
Returns true if the geometry contains m values.
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 QgsLineStringV2 * curveToLine() const =0
Returns a new line string geometry corresponding to a segmentized approximation of the curve...
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
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:37
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