QGIS API Documentation  2.10.1-Pisa
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsgeometrycollectionv2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsgeometrycollectionv2.cpp
3  -------------------------------------------------------------------
4 Date : 28 Oct 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 
17 #include "qgsapplication.h"
18 #include "qgsgeometryfactory.h"
19 #include "qgsgeometryutils.h"
20 #include "qgscircularstringv2.h"
21 #include "qgscompoundcurvev2.h"
22 #include "qgslinestringv2.h"
23 #include "qgspointv2.h"
24 #include "qgspolygonv2.h"
25 #include "qgswkbptr.h"
26 
28 {
30 }
31 
33 {
34  int nGeoms = c.mGeometries.size();
35  mGeometries.resize( nGeoms );
36  for ( int i = 0; i < nGeoms; ++i )
37  {
38  mGeometries[i] = c.mGeometries.at( i )->clone();
39  }
40 }
41 
43 {
44  if ( &c != this )
45  {
47  int nGeoms = c.mGeometries.size();
48  mGeometries.resize( nGeoms );
49  for ( int i = 0; i < nGeoms; ++i )
50  {
51  mGeometries[i] = c.mGeometries.at( i )->clone();
52  }
53  }
54  return *this;
55 }
56 
58 {
59  clear();
60 }
61 
63 {
64  return new QgsGeometryCollectionV2( *this );
65 }
66 
68 {
69  qDeleteAll( mGeometries );
72 }
73 
75 {
76  return mGeometries.size();
77 }
78 
80 {
81  if ( n >= mGeometries.size() )
82  {
83  return 0;
84  }
85  return mGeometries.at( n );
86 }
87 
89 {
90  if ( n >= mGeometries.size() )
91  {
92  return 0;
93  }
94  return mGeometries.at( n );
95 }
96 
98 {
99  if ( !g )
100  {
101  return false;
102  }
103 
104  mGeometries.append( g );
105  return true;
106 }
107 
109 {
110  if ( nr >= mGeometries.size() )
111  {
112  return false;
113  }
114  mGeometries.remove( nr );
115  return true;
116 }
117 
119 {
120  int maxDim = 0;
122  for ( ; it != mGeometries.constEnd(); ++it )
123  {
124  int dim = ( *it )->dimension();
125  if ( dim > maxDim )
126  {
127  maxDim = dim;
128  }
129  }
130  return maxDim;
131 }
132 
134 {
136  for ( ; it != mGeometries.end(); ++it )
137  {
138  ( *it )->transform( ct );
139  }
140 }
141 
143 {
145  for ( ; it != mGeometries.end(); ++it )
146  {
147  ( *it )->transform( t );
148  }
149 }
150 
151 #if 0
152 void QgsGeometryCollectionV2::clip( const QgsRectangle& rect )
153 {
155  for ( ; it != mGeometries.end(); ++it )
156  {
157  ( *it )->clip( rect );
158  }
159 }
160 #endif
161 
163 {
165  for ( ; it != mGeometries.constEnd(); ++it )
166  {
167  ( *it )->draw( p );
168  }
169 }
170 
171 bool QgsGeometryCollectionV2::fromWkb( const unsigned char * wkb )
172 {
173  if ( !wkb )
174  {
175  return false;
176  }
177  QgsConstWkbPtr wkbPtr( wkb + 1 );
178  //type
179  wkbPtr >> mWkbType;
180  int nGeometries = 0;
181  wkbPtr >> nGeometries;
182 
183  QList<QgsAbstractGeometryV2*> geometryList;
184  for ( int i = 0; i < nGeometries; ++i )
185  {
187  if ( geom )
188  {
189  geometryList.append( geom );
190  wkbPtr += geom->wkbSize();
191  }
192  }
193 
194  mGeometries.resize( geometryList.size() );
195  for ( int i = 0; i < geometryList.size(); ++i )
196  {
197  mGeometries[i] = geometryList.at( i );
198  }
199 
200  return true;
201 }
202 
204 {
206  << new QgsCircularStringV2 << new QgsCompoundCurveV2, "GeometryCollection" );
207 }
208 
210 {
211  int size = sizeof( char ) + sizeof( quint32 ) + sizeof( quint32 );
212  foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
213  {
214  if ( geom )
215  {
216  size += geom->wkbSize();
217  }
218  }
219  return size;
220 }
221 
222 unsigned char* QgsGeometryCollectionV2::asWkb( int& binarySize ) const
223 {
224  binarySize = wkbSize();
225  unsigned char* geomPtr = new unsigned char[binarySize];
226  QgsWkbPtr wkb( geomPtr );
227  wkb << static_cast<char>( QgsApplication::endian() );
228  wkb << static_cast<quint32>( wkbType() );
229  wkb << static_cast<quint32>( mGeometries.size() );
230  foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
231  {
232  int geomWkbLen = 0;
233  if ( geom )
234  {
235  unsigned char* geomWkb = geom->asWkb( geomWkbLen );
236  memcpy( wkb, geomWkb, geomWkbLen );
237  wkb += geomWkbLen;
238  delete[] geomWkb;
239  }
240  }
241  return geomPtr;
242 }
243 
245 {
246  QString wkt = wktTypeStr() + " (";
247  foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
248  {
249  QString childWkt = geom->asWkt( precision );
250  if ( dynamic_cast<const QgsPointV2*>( geom ) ||
251  dynamic_cast<const QgsLineStringV2*>( geom ) ||
252  dynamic_cast<const QgsPolygonV2*>( geom ) )
253  {
254  // Type names of linear geometries are omitted
255  childWkt = childWkt.mid( childWkt.indexOf( "(" ) );
256  }
257  wkt += childWkt + ",";
258  }
259  if ( wkt.endsWith( "," ) )
260  {
261  wkt.chop( 1 ); // Remove last ","
262  }
263  wkt += ")";
264  return wkt;
265 }
266 
267 QDomElement QgsGeometryCollectionV2::asGML2( QDomDocument& doc, int precision, const QString& ns ) const
268 {
269  QDomElement elemMultiGeometry = doc.createElementNS( ns, "MultiGeometry" );
270  foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
271  {
272  QDomElement elemGeometryMember = doc.createElementNS( ns, "geometryMember" );
273  elemGeometryMember.appendChild( geom->asGML2( doc, precision, ns ) );
274  elemMultiGeometry.appendChild( elemGeometryMember );
275  }
276  return elemMultiGeometry;
277 }
278 
279 QDomElement QgsGeometryCollectionV2::asGML3( QDomDocument& doc, int precision, const QString& ns ) const
280 {
281  QDomElement elemMultiGeometry = doc.createElementNS( ns, "MultiGeometry" );
282  foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
283  {
284  QDomElement elemGeometryMember = doc.createElementNS( ns, "geometryMember" );
285  elemGeometryMember.appendChild( geom->asGML3( doc, precision, ns ) );
286  elemMultiGeometry.appendChild( elemGeometryMember );
287  }
288  return elemMultiGeometry;
289 }
290 
292 {
293  QString json = "{\"type\": \"GeometryCollection\", \"geometries\": [";
294  foreach ( const QgsAbstractGeometryV2 *geom, mGeometries )
295  {
296  json += geom->asJSON( precision ) + ", ";
297  }
298  if ( json.endsWith( ", " ) )
299  {
300  json.chop( 2 ); // Remove last ", "
301  }
302  json += "] }";
303  return json;
304 }
305 
307 {
308  if ( mGeometries.size() < 1 )
309  {
310  return QgsRectangle();
311  }
312 
313  QgsRectangle bbox = mGeometries.at( 0 )->calculateBoundingBox();
314  for ( int i = 1; i < mGeometries.size(); ++i )
315  {
316  QgsRectangle geomBox = mGeometries.at( i )->calculateBoundingBox();
317  bbox.combineExtentWith( &geomBox );
318  }
319  return bbox;
320 }
321 
323 {
324  coord.clear();
326  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
327  {
328  QList< QList< QList< QgsPointV2 > > > geomCoords;
329  ( *geomIt )->coordinateSequence( geomCoords );
330  QList< QList< QList< QgsPointV2 > > >::const_iterator cIt = geomCoords.constBegin();
331  for ( ; cIt != geomCoords.constEnd(); ++cIt )
332  {
333  coord.push_back( *cIt );
334  }
335  }
336 }
337 
338 double QgsGeometryCollectionV2::closestSegment( const QgsPointV2& pt, QgsPointV2& segmentPt, QgsVertexId& vertexAfter, bool* leftOf, double epsilon ) const
339 {
340  return QgsGeometryUtils::closestSegmentFromComponents( mGeometries, QgsGeometryUtils::PART, pt, segmentPt, vertexAfter, leftOf, epsilon );
341 }
342 
344 {
345  if ( id.part < 0 )
346  {
347  id.part = 0; id.ring = -1; id.vertex = -1;
348  }
349 
350  QgsAbstractGeometryV2* geom = mGeometries.at( id.part );
351  if ( geom->nextVertex( id, vertex ) )
352  {
353  return true;
354  }
355  if (( id.part + 1 ) >= numGeometries() )
356  {
357  return false;
358  }
359  ++id.part; id.ring = -1; id.vertex = -1;
360  return mGeometries.at( id.part )->nextVertex( id, vertex );
361 }
362 
363 bool QgsGeometryCollectionV2::insertVertex( const QgsVertexId& position, const QgsPointV2& vertex )
364 {
365  if ( position.part >= mGeometries.size() )
366  {
367  return false;
368  }
369 
370  return mGeometries[position.part]->insertVertex( position, vertex );
371 }
372 
373 bool QgsGeometryCollectionV2::moveVertex( const QgsVertexId& position, const QgsPointV2& newPos )
374 {
375  if ( position.part >= mGeometries.size() )
376  {
377  return false;
378  }
379 
380  return mGeometries[position.part]->moveVertex( position, newPos );
381 }
382 
384 {
385  if ( position.part >= mGeometries.size() )
386  {
387  return false;
388  }
389 
390  QgsAbstractGeometryV2* geom = mGeometries[position.part];
391  if ( !geom )
392  {
393  return false;
394  }
395 
396  bool success = geom->deleteVertex( position );
397 
398  //remove geometry if no vertices left
399  if ( geom->isEmpty() )
400  {
401  removeGeometry( position.part );
402  }
403 
404  return success;
405 }
406 
408 {
409  double length = 0.0;
411  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
412  {
413  length += ( *geomIt )->length();
414  }
415  return length;
416 }
417 
419 {
420  double area = 0.0;
422  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
423  {
424  area += ( *geomIt )->area();
425  }
426  return area;
427 }
428 
429 bool QgsGeometryCollectionV2::fromCollectionWkt( const QString &wkt, const QList<QgsAbstractGeometryV2*>& subtypes, const QString& defaultChildWkbType )
430 {
431  clear();
432 
434 
435  if ( QgsWKBTypes::flatType( parts.first ) != QgsWKBTypes::parseType( geometryType() ) )
436  return false;
437  mWkbType = parts.first;
438 
439  QString defChildWkbType = QString( "%1%2%3 " ).arg( defaultChildWkbType ).arg( is3D() ? "Z" : "" ).arg( isMeasure() ? "M" : "" );
440 
441  foreach ( const QString& childWkt, QgsGeometryUtils::wktGetChildBlocks( parts.second, defChildWkbType ) )
442  {
444 
445  bool success = false;
446  foreach ( const QgsAbstractGeometryV2* geom, subtypes )
447  {
448  if ( QgsWKBTypes::flatType( childParts.first ) == QgsWKBTypes::parseType( geom->geometryType() ) )
449  {
450  mGeometries.append( geom->clone() );
451  if ( mGeometries.back()->fromWkt( childWkt ) )
452  {
453  success = true;
454  break;
455  }
456  }
457  }
458  if ( !success )
459  {
460  clear();
461  qDeleteAll( subtypes );
462  return false;
463  }
464  }
465  qDeleteAll( subtypes );
466  return true;
467 }
468 
470 {
472  for ( ; it != mGeometries.constEnd(); ++it )
473  {
474  if (( *it )->hasCurvedSegments() )
475  {
476  return true;
477  }
478  }
479  return false;
480 }
481 
483 {
485  QgsGeometryCollectionV2* geomCollection = dynamic_cast<QgsGeometryCollectionV2*>( geom );
486  if ( !geomCollection )
487  {
488  delete geom; return clone();
489  }
490 
492  for ( ; geomIt != mGeometries.constEnd(); ++geomIt )
493  {
494  geomCollection->addGeometry(( *geomIt )->segmentize() );
495  }
496  return geomCollection;
497 }
virtual void transform(const QgsCoordinateTransform &ct) override
Transforms the geometry using a coordinate transform.
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
bool fromWkb(const unsigned char *wkb) override
Sets the geometry from a WKB string.
QgsWKBTypes::Type wkbType() const
Returns the WKB type of the geometry.
A rectangle specified with double values.
Definition: qgsrectangle.h:35
static QPair< QgsWKBTypes::Type, QString > wktReadBlock(const QString &wkt)
Parses a WKT block of the format "TYPE( contents )" and returns a pair of geometry type to contents (...
virtual void coordinateSequence(QList< QList< QList< QgsPointV2 > > > &coord) const override
Retrieves the sequence of geometries, rings and nodes.
QgsGeometryCollectionV2 & operator=(const QgsGeometryCollectionV2 &c)
virtual QgsAbstractGeometryV2 & operator=(const QgsAbstractGeometryV2 &geom)
QDomNode appendChild(const QDomNode &newChild)
void append(const T &value)
iterator begin()
Circular string geometry type.
const_iterator constEnd() const
const T & at(int i) const
virtual QString asJSON(int precision=17) const =0
Returns a GeoJSON representation of the geometry.
Abstract base class for all geometries.
static QStringList wktGetChildBlocks(const QString &wkt, const QString &defaultType="")
Parses a WKT string and returns of list of blocks contained in the WKT.
static double closestSegmentFromComponents(T &container, componentType ctype, const QgsPointV2 &pt, QgsPointV2 &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon)
virtual bool insertVertex(const QgsVertexId &position, const QgsPointV2 &vertex) override
Inserts a vertex into the geometry.
QDomElement createElementNS(const QString &nsURI, const QString &qName)
QString asWkt(int precision=17) const override
Returns a WKT representation of the geometry.
virtual void clear() override
Clears the geometry, ie reset it to a null geometry.
void chop(int n)
static endian_t endian()
Returns whether this machine uses big or little endian.
QString wktTypeStr() const
Returns the WKT type string of the geometry.
virtual int wkbSize() const =0
Returns the size of the WKB representation of the geometry.
QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
reference back()
int size() const
bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const override
Returns next vertex id and coordinates.
void clear()
static Type flatType(Type type)
Definition: qgswkbtypes.cpp:46
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
unsigned char * asWkb(int &binarySize) const override
Returns a WKB representation of the geometry.
bool hasCurvedSegments() const override
Returns true if the geometry contains curved segments.
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
void append(const T &value)
QDomElement asGML3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
void resize(int size)
int wkbSize() const override
Returns the size of the WKB representation of the geometry.
Utility class for identifying a unique vertex within a geometry.
bool isMeasure() const
Returns true if the geometry contains m values.
Line string geometry type.
bool isEmpty() const
Returns true if the geometry is empty.
Point geometry type.
Definition: qgspointv2.h:29
void remove(int i)
virtual unsigned char * asWkb(int &binarySize) const =0
Returns a WKB representation of the geometry.
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
virtual QDomElement asGML3(QDomDocument &doc, int precision=17, const QString &ns="gml") const =0
Returns a GML3 representation of the geometry.
virtual bool nextVertex(QgsVertexId &id, QgsPointV2 &vertex) const =0
Returns next vertex id and coordinates.
static QgsAbstractGeometryV2 * geomFromWkbType(QgsWKBTypes::Type t)
return empty geometry from wkb type
virtual double length() const override
Returns the length (or perimeter for area geometries) of the geometry.
QString asJSON(int precision=17) const override
Returns a GeoJSON representation of the geometry.
Compound curve geometry type.
bool fromCollectionWkt(const QString &wkt, const QList< QgsAbstractGeometryV2 * > &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
virtual double area() const override
Returns the area of the geometry.
virtual QString geometryType() const =0
Returns a unique string representing the geometry type.
static QgsAbstractGeometryV2 * geomFromWkb(const unsigned char *wkb)
Construct geometry from a WKB string.
virtual bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
virtual bool deleteVertex(const QgsVertexId &position) override
Deletes a vertex within the geometry.
QVector< QgsAbstractGeometryV2 * > mGeometries
virtual bool deleteVertex(const QgsVertexId &position)=0
Deletes a vertex within the geometry.
int numGeometries() const
Returns the number of geometries within the collection.
const T & at(int i) const
const_iterator constBegin() const
QString mid(int position, int n) const
virtual QgsAbstractGeometryV2 * clone() const override
Clones the geometry by performing a deep copy.
virtual bool addGeometry(QgsAbstractGeometryV2 *g)
Adds a geometry and takes ownership.
virtual void draw(QPainter &p) const override
Draws the geometry using the specified QPainter.
virtual double closestSegment(const QgsPointV2 &pt, QgsPointV2 &segmentPt, QgsVertexId &vertexAfter, bool *leftOf, double epsilon) const override
Searches for the closest segment of the geometry to a given point.
Class for doing transforms between two map coordinate systems.
virtual QString asWkt(int precision=17) const =0
Returns a WKT representation of the geometry.
const QgsAbstractGeometryV2 * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
virtual QString geometryType() const override
Returns a unique string representing the geometry type.
virtual bool removeGeometry(int nr)
Removes a geometry from the collection.
static Type parseType(const QString &wktStr)
Definition: qgswkbtypes.cpp:56
double ANALYSIS_EXPORT leftOf(Point3D *thepoint, Point3D *p1, Point3D *p2)
Returns whether 'thepoint' is left or right of the line from 'p1' to 'p2'.
virtual QDomElement asGML2(QDomDocument &doc, int precision=17, const QString &ns="gml") const =0
Returns a GML2 representation of the geometry.
const_iterator constEnd() const
QgsAbstractGeometryV2 * segmentize() const override
Returns a geometry without curves.
const_iterator constBegin() const
virtual QgsAbstractGeometryV2 * clone() const =0
Clones the geometry by performing a deep copy.
virtual bool moveVertex(const QgsVertexId &position, const QgsPointV2 &newPos) override
Moves a vertex within the geometry.
int size() const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
iterator end()
virtual QgsRectangle calculateBoundingBox() const override
Calculates the minimal bounding box for the geometry.
virtual int dimension() const override
Returns the inherent dimension of the geometry.