QGIS API Documentation  3.0.2-Girona (307d082)
qgsmultipolygon.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmultipolygon.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 
16 #include "qgsmultipolygon.h"
17 #include "qgsapplication.h"
18 #include "qgsgeometryutils.h"
19 #include "qgssurface.h"
20 #include "qgslinestring.h"
21 #include "qgspolygon.h"
22 #include "qgscurvepolygon.h"
23 #include "qgsmultilinestring.h"
24 
26 {
28 }
29 
31 {
32  return QStringLiteral( "MultiPolygon" );
33 }
34 
36 {
39 }
40 
42 {
43  auto result = qgis::make_unique< QgsMultiPolygon >();
44  result->mWkbType = mWkbType;
45  return result.release();
46 }
47 
49 {
50  return new QgsMultiPolygon( *this );
51 }
52 
53 bool QgsMultiPolygon::fromWkt( const QString &wkt )
54 {
55  return fromCollectionWkt( wkt, QVector<QgsAbstractGeometry *>() << new QgsPolygon, QStringLiteral( "Polygon" ) );
56 }
57 
58 QDomElement QgsMultiPolygon::asGml2( QDomDocument &doc, int precision, const QString &ns ) const
59 {
60  // GML2 does not support curves
61  QDomElement elemMultiPolygon = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) );
62 
63  if ( isEmpty() )
64  return elemMultiPolygon;
65 
66  for ( const QgsAbstractGeometry *geom : mGeometries )
67  {
68  if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
69  {
70  QDomElement elemPolygonMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) );
71  elemPolygonMember.appendChild( geom->asGml2( doc, precision, ns ) );
72  elemMultiPolygon.appendChild( elemPolygonMember );
73  }
74  }
75 
76  return elemMultiPolygon;
77 }
78 
79 QDomElement QgsMultiPolygon::asGml3( QDomDocument &doc, int precision, const QString &ns ) const
80 {
81  QDomElement elemMultiSurface = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) );
82 
83  if ( isEmpty() )
84  return elemMultiSurface;
85 
86  for ( const QgsAbstractGeometry *geom : mGeometries )
87  {
88  if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
89  {
90  QDomElement elemSurfaceMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) );
91  elemSurfaceMember.appendChild( geom->asGml3( doc, precision, ns ) );
92  elemMultiSurface.appendChild( elemSurfaceMember );
93  }
94  }
95 
96  return elemMultiSurface;
97 }
98 
99 QString QgsMultiPolygon::asJson( int precision ) const
100 {
101  // GeoJSON does not support curves
102  QString json = QStringLiteral( "{\"type\": \"MultiPolygon\", \"coordinates\": [" );
103  for ( const QgsAbstractGeometry *geom : mGeometries )
104  {
105  if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
106  {
107  json += '[';
108 
109  const QgsPolygon *polygon = static_cast<const QgsPolygon *>( geom );
110 
111  std::unique_ptr< QgsLineString > exteriorLineString( polygon->exteriorRing()->curveToLine() );
112  QgsPointSequence exteriorPts;
113  exteriorLineString->points( exteriorPts );
114  json += QgsGeometryUtils::pointsToJSON( exteriorPts, precision ) + ", ";
115 
116  std::unique_ptr< QgsLineString > interiorLineString;
117  for ( int i = 0, n = polygon->numInteriorRings(); i < n; ++i )
118  {
119  interiorLineString.reset( polygon->interiorRing( i )->curveToLine() );
120  QgsPointSequence interiorPts;
121  interiorLineString->points( interiorPts );
122  json += QgsGeometryUtils::pointsToJSON( interiorPts, precision ) + ", ";
123  }
124  if ( json.endsWith( QLatin1String( ", " ) ) )
125  {
126  json.chop( 2 ); // Remove last ", "
127  }
128 
129  json += QLatin1String( "], " );
130  }
131  }
132  if ( json.endsWith( QLatin1String( ", " ) ) )
133  {
134  json.chop( 2 ); // Remove last ", "
135  }
136  json += QLatin1String( "] }" );
137  return json;
138 }
139 
141 {
142  if ( !qgsgeometry_cast<QgsPolygon *>( g ) )
143  {
144  delete g;
145  return false;
146  }
147 
148  if ( mGeometries.empty() )
149  {
151  }
152  if ( is3D() && !g->is3D() )
153  g->addZValue();
154  else if ( !is3D() && g->is3D() )
155  g->dropZValue();
156  if ( isMeasure() && !g->isMeasure() )
157  g->addMValue();
158  else if ( !isMeasure() && g->isMeasure() )
159  g->dropMValue();
160 
161  return QgsGeometryCollection::addGeometry( g ); // clazy:exclude=skipped-base-method
162 }
163 
165 {
166  if ( !g || !qgsgeometry_cast< QgsPolygon * >( g ) )
167  {
168  delete g;
169  return false;
170  }
171 
172  return QgsMultiSurface::insertGeometry( g, index );
173 }
174 
176 {
177  QgsMultiSurface *multiSurface = new QgsMultiSurface();
178  for ( int i = 0; i < mGeometries.size(); ++i )
179  {
180  multiSurface->addGeometry( mGeometries.at( i )->clone() );
181  }
182  return multiSurface;
183 }
184 
186 {
187  std::unique_ptr< QgsMultiLineString > multiLine( new QgsMultiLineString() );
188  for ( int i = 0; i < mGeometries.size(); ++i )
189  {
190  if ( QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometries.at( i ) ) )
191  {
192  QgsAbstractGeometry *polygonBoundary = polygon->boundary();
193 
194  if ( QgsLineString *lineStringBoundary = qgsgeometry_cast< QgsLineString * >( polygonBoundary ) )
195  {
196  multiLine->addGeometry( lineStringBoundary );
197  }
198  else if ( QgsMultiLineString *multiLineStringBoundary = qgsgeometry_cast< QgsMultiLineString * >( polygonBoundary ) )
199  {
200  for ( int j = 0; j < multiLineStringBoundary->numGeometries(); ++j )
201  {
202  multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() );
203  }
204  delete multiLineStringBoundary;
205  }
206  else
207  {
208  delete polygonBoundary;
209  }
210  }
211  }
212  if ( multiLine->numGeometries() == 0 )
213  {
214  return nullptr;
215  }
216  return multiLine.release();
217 }
218 
220 {
221  return true;
222 }
bool isMeasure() const
Returns true if the geometry contains m values.
const QgsCurve * interiorRing(int i) const
static QString pointsToJSON(const QgsPointSequence &points, int precision)
Returns a geoJSON coordinates string.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML3 representation of the geometry.
Multi line string geometry collection.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
QgsMultiPolygon * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership...
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
void clear() override
Clears the geometry, ie reset it to a null geometry.
Multi surface geometry collection.
QgsWkbTypes::Type mWkbType
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
QgsMultiSurface * toCurveType() const override
Returns the geometry converted to the more generic curve type QgsMultiSurface.
bool isEmpty() const override
Returns true if the geometry is empty.
int numInteriorRings() const
QgsMultiPolygon * clone() const override
Clones the geometry by performing a deep copy.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
QString geometryType() const override
Returns a unique string representing the geometry type.
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
QString asJson(int precision=17) const override
Returns a GeoJSON representation of the geometry.
Abstract base class for all geometries.
const QgsCurve * exteriorRing() const
bool fromCollectionWkt(const QString &wkt, const QVector< QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
bool wktOmitChildType() const override
Returns whether child type names are omitted from Wkt representations of the collection.
QVector< QgsPoint > QgsPointSequence
QVector< QgsAbstractGeometry *> mGeometries
Multi polygon geometry collection.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
Line string geometry type, with support for z-dimension and m-values.
Definition: qgslinestring.h:41
virtual QgsLineString * 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...
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml") const override
Returns a GML2 representation of the geometry.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
Polygon geometry type.
Definition: qgspolygon.h:31
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.