QGIS API Documentation  3.4.15-Madeira (e83d02e274)
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 AxisOrder axisOrder ) 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, axisOrder ) );
72  elemMultiPolygon.appendChild( elemPolygonMember );
73  }
74  }
75 
76  return elemMultiPolygon;
77 }
78 
79 QDomElement QgsMultiPolygon::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) 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, axisOrder ) );
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 }
const QgsCurve * exteriorRing() const
Returns the curve polygon&#39;s exterior ring.
static QString pointsToJSON(const QgsPointSequence &points, int precision)
Returns a geoJSON coordinates string.
int precision
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
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
QDomElement asGml2(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML2 representation of the geometry.
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.
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.
bool isMeasure() const
Returns true if the geometry contains m values.
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.
QDomElement asGml3(QDomDocument &doc, int precision=17, const QString &ns="gml", QgsAbstractGeometry::AxisOrder axisOrder=QgsAbstractGeometry::AxisOrder::XY) const override
Returns a GML3 representation of the geometry.
QString asJson(int precision=17) const override
Returns a GeoJSON representation of the geometry.
Abstract base class for all geometries.
AxisOrder
Axis order for GML generation.
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:43
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
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...
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
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.
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.
bool fromCollectionWkt(const QString &wkt, const QVector< QgsAbstractGeometry * > &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.