QGIS API Documentation  3.8.0-Zanzibar (11aff65)
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 
25 #include <QJsonObject>
26 #include <nlohmann/json.hpp>
27 
29 {
31 }
32 
34 {
35  return QStringLiteral( "MultiPolygon" );
36 }
37 
39 {
42 }
43 
45 {
46  auto result = qgis::make_unique< QgsMultiPolygon >();
47  result->mWkbType = mWkbType;
48  return result.release();
49 }
50 
52 {
53  return new QgsMultiPolygon( *this );
54 }
55 
56 bool QgsMultiPolygon::fromWkt( const QString &wkt )
57 {
58  return fromCollectionWkt( wkt, QVector<QgsAbstractGeometry *>() << new QgsPolygon, QStringLiteral( "Polygon" ) );
59 }
60 
61 QDomElement QgsMultiPolygon::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
62 {
63  // GML2 does not support curves
64  QDomElement elemMultiPolygon = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) );
65 
66  if ( isEmpty() )
67  return elemMultiPolygon;
68 
69  for ( const QgsAbstractGeometry *geom : mGeometries )
70  {
71  if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
72  {
73  QDomElement elemPolygonMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) );
74  elemPolygonMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
75  elemMultiPolygon.appendChild( elemPolygonMember );
76  }
77  }
78 
79  return elemMultiPolygon;
80 }
81 
82 QDomElement QgsMultiPolygon::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
83 {
84  QDomElement elemMultiSurface = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) );
85 
86  if ( isEmpty() )
87  return elemMultiSurface;
88 
89  for ( const QgsAbstractGeometry *geom : mGeometries )
90  {
91  if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
92  {
93  QDomElement elemSurfaceMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) );
94  elemSurfaceMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
95  elemMultiSurface.appendChild( elemSurfaceMember );
96  }
97  }
98 
99  return elemMultiSurface;
100 }
101 
103 {
104  json polygons( json::array( ) );
105  for ( const QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
106  {
107  if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
108  {
109  json coordinates( json::array( ) );
110  const QgsPolygon *polygon = static_cast<const QgsPolygon *>( geom );
111 
112  std::unique_ptr< QgsLineString > exteriorLineString( polygon->exteriorRing()->curveToLine() );
113  QgsPointSequence exteriorPts;
114  exteriorLineString->points( exteriorPts );
115  coordinates.push_back( QgsGeometryUtils::pointsToJson( exteriorPts, precision ) );
116 
117  std::unique_ptr< QgsLineString > interiorLineString;
118  for ( int i = 0, n = polygon->numInteriorRings(); i < n; ++i )
119  {
120  interiorLineString.reset( polygon->interiorRing( i )->curveToLine() );
121  QgsPointSequence interiorPts;
122  interiorLineString->points( interiorPts );
123  coordinates.push_back( QgsGeometryUtils::pointsToJson( interiorPts, precision ) );
124  }
125  polygons.push_back( coordinates );
126  }
127  }
128  return
129  {
130  { "type", "MultiPolygon" },
131  { "coordinates", polygons }
132  };
133 }
134 
136 {
137  if ( !qgsgeometry_cast<QgsPolygon *>( g ) )
138  {
139  delete g;
140  return false;
141  }
142 
143  if ( mGeometries.empty() )
144  {
146  }
147  if ( is3D() && !g->is3D() )
148  g->addZValue();
149  else if ( !is3D() && g->is3D() )
150  g->dropZValue();
151  if ( isMeasure() && !g->isMeasure() )
152  g->addMValue();
153  else if ( !isMeasure() && g->isMeasure() )
154  g->dropMValue();
155 
156  return QgsGeometryCollection::addGeometry( g ); // clazy:exclude=skipped-base-method
157 }
158 
160 {
161  if ( !g || !qgsgeometry_cast< QgsPolygon * >( g ) )
162  {
163  delete g;
164  return false;
165  }
166 
167  return QgsMultiSurface::insertGeometry( g, index );
168 }
169 
171 {
172  QgsMultiSurface *multiSurface = new QgsMultiSurface();
173  for ( int i = 0; i < mGeometries.size(); ++i )
174  {
175  multiSurface->addGeometry( mGeometries.at( i )->clone() );
176  }
177  return multiSurface;
178 }
179 
181 {
182  std::unique_ptr< QgsMultiLineString > multiLine( new QgsMultiLineString() );
183  for ( int i = 0; i < mGeometries.size(); ++i )
184  {
185  if ( QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometries.at( i ) ) )
186  {
187  QgsAbstractGeometry *polygonBoundary = polygon->boundary();
188 
189  if ( QgsLineString *lineStringBoundary = qgsgeometry_cast< QgsLineString * >( polygonBoundary ) )
190  {
191  multiLine->addGeometry( lineStringBoundary );
192  }
193  else if ( QgsMultiLineString *multiLineStringBoundary = qgsgeometry_cast< QgsMultiLineString * >( polygonBoundary ) )
194  {
195  for ( int j = 0; j < multiLineStringBoundary->numGeometries(); ++j )
196  {
197  multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() );
198  }
199  delete multiLineStringBoundary;
200  }
201  else
202  {
203  delete polygonBoundary;
204  }
205  }
206  }
207  if ( multiLine->numGeometries() == 0 )
208  {
209  return nullptr;
210  }
211  return multiLine.release();
212 }
213 
215 {
216  return true;
217 }
bool isMeasure() const
Returns true if the geometry contains m values.
int precision
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
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.
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.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
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.
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.
Abstract base class for all geometries.
bool fromCollectionWkt(const QString &wkt, const QVector< QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
AxisOrder
Axis order for GML generation.
nlohmann::json json
Definition: qgsjsonutils.h:27
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
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
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...
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
Polygon geometry type.
Definition: qgspolygon.h:31
const QgsCurve * exteriorRing() const
Returns the curve polygon&#39;s exterior ring.
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.