QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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  multiSurface->reserve( mGeometries.size() );
174  for ( int i = 0; i < mGeometries.size(); ++i )
175  {
176  multiSurface->addGeometry( mGeometries.at( i )->clone() );
177  }
178  return multiSurface;
179 }
180 
182 {
183  std::unique_ptr< QgsMultiLineString > multiLine( new QgsMultiLineString() );
184  multiLine->reserve( mGeometries.size() );
185  for ( int i = 0; i < mGeometries.size(); ++i )
186  {
187  if ( QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometries.at( i ) ) )
188  {
189  QgsAbstractGeometry *polygonBoundary = polygon->boundary();
190 
191  if ( QgsLineString *lineStringBoundary = qgsgeometry_cast< QgsLineString * >( polygonBoundary ) )
192  {
193  multiLine->addGeometry( lineStringBoundary );
194  }
195  else if ( QgsMultiLineString *multiLineStringBoundary = qgsgeometry_cast< QgsMultiLineString * >( polygonBoundary ) )
196  {
197  for ( int j = 0; j < multiLineStringBoundary->numGeometries(); ++j )
198  {
199  multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() );
200  }
201  delete multiLineStringBoundary;
202  }
203  else
204  {
205  delete polygonBoundary;
206  }
207  }
208  }
209  if ( multiLine->numGeometries() == 0 )
210  {
211  return nullptr;
212  }
213  return multiLine.release();
214 }
215 
217 {
218  return true;
219 }
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.
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
void reserve(int size)
Attempts to allocate memory for at least size geometries.
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.