QGIS API Documentation 3.39.0-Master (d0dedde5474)
Searching...
No Matches
qgsmultipolygon.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmultipolygon.cpp
3 -------------------------------------------------------------------
4Date : 28 Oct 2014
5Copyright : (C) 2014 by Marco Hugentobler
6email : marco.hugentobler at sourcepole dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
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 "qgsgeometryutils.h"
18#include "qgslinestring.h"
19#include "qgspolygon.h"
20#include "qgscurvepolygon.h"
21#include "qgsmultilinestring.h"
22
23#include <QJsonObject>
24#include <nlohmann/json.hpp>
25
30
31QgsMultiPolygon::QgsMultiPolygon( const QList<QgsPolygon> &polygons )
32{
33 if ( polygons.empty() )
34 return;
35
36 mGeometries.reserve( polygons.size() );
37 for ( const QgsPolygon &poly : polygons )
38 {
39 mGeometries.append( poly.clone() );
40 }
41
43}
44
45QgsMultiPolygon::QgsMultiPolygon( const QList<QgsPolygon *> &polygons )
46{
47 if ( polygons.empty() )
48 return;
49
50 mGeometries.reserve( polygons.size() );
51 for ( QgsPolygon *poly : polygons )
52 {
53 mGeometries.append( poly );
54 }
55
57}
58
60{
61 return qgsgeometry_cast< QgsPolygon * >( geometryN( index ) );
62}
63
64const QgsPolygon *QgsMultiPolygon::polygonN( int index ) const
65{
66 return qgsgeometry_cast< const QgsPolygon * >( geometryN( index ) );
67}
68
70{
71 return QStringLiteral( "MultiPolygon" );
72}
73
79
81{
82 auto result = std::make_unique< QgsMultiPolygon >();
83 result->mWkbType = mWkbType;
84 return result.release();
85}
86
88{
89 return new QgsMultiPolygon( *this );
90}
91
92bool QgsMultiPolygon::fromWkt( const QString &wkt )
93{
94 return fromCollectionWkt( wkt, QVector<QgsAbstractGeometry *>() << new QgsPolygon, QStringLiteral( "Polygon" ) );
95}
96
97QDomElement QgsMultiPolygon::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
98{
99 // GML2 does not support curves
100 QDomElement elemMultiPolygon = doc.createElementNS( ns, QStringLiteral( "MultiPolygon" ) );
101
102 if ( isEmpty() )
103 return elemMultiPolygon;
104
105 for ( const QgsAbstractGeometry *geom : mGeometries )
106 {
107 if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
108 {
109 QDomElement elemPolygonMember = doc.createElementNS( ns, QStringLiteral( "polygonMember" ) );
110 elemPolygonMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
111 elemMultiPolygon.appendChild( elemPolygonMember );
112 }
113 }
114
115 return elemMultiPolygon;
116}
117
118QDomElement QgsMultiPolygon::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
119{
120 QDomElement elemMultiSurface = doc.createElementNS( ns, QStringLiteral( "MultiSurface" ) );
121
122 if ( isEmpty() )
123 return elemMultiSurface;
124
125 for ( const QgsAbstractGeometry *geom : mGeometries )
126 {
127 if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
128 {
129 QDomElement elemSurfaceMember = doc.createElementNS( ns, QStringLiteral( "surfaceMember" ) );
130 elemSurfaceMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
131 elemMultiSurface.appendChild( elemSurfaceMember );
132 }
133 }
134
135 return elemMultiSurface;
136}
137
139{
140 json polygons( json::array( ) );
141 for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) )
142 {
143 if ( qgsgeometry_cast<const QgsPolygon *>( geom ) )
144 {
145 json coordinates( json::array( ) );
146 const QgsPolygon *polygon = static_cast<const QgsPolygon *>( geom );
147
148 std::unique_ptr< QgsLineString > exteriorLineString( polygon->exteriorRing()->curveToLine() );
149 QgsPointSequence exteriorPts;
150 exteriorLineString->points( exteriorPts );
151 coordinates.push_back( QgsGeometryUtils::pointsToJson( exteriorPts, precision ) );
152
153 std::unique_ptr< QgsLineString > interiorLineString;
154 for ( int i = 0, n = polygon->numInteriorRings(); i < n; ++i )
155 {
156 interiorLineString.reset( polygon->interiorRing( i )->curveToLine() );
157 QgsPointSequence interiorPts;
158 interiorLineString->points( interiorPts );
159 coordinates.push_back( QgsGeometryUtils::pointsToJson( interiorPts, precision ) );
160 }
161 polygons.push_back( coordinates );
162 }
163 }
164 return
165 {
166 { "type", "MultiPolygon" },
167 { "coordinates", polygons }
168 };
169}
170
172{
173 if ( !qgsgeometry_cast<QgsPolygon *>( g ) )
174 {
175 delete g;
176 return false;
177 }
178
179 if ( mGeometries.empty() )
180 {
182 }
183 if ( is3D() && !g->is3D() )
185 else if ( !is3D() && g->is3D() )
186 g->dropZValue();
187 if ( isMeasure() && !g->isMeasure() )
189 else if ( !isMeasure() && g->isMeasure() )
190 g->dropMValue();
191
192 return QgsGeometryCollection::addGeometry( g ); // NOLINT(bugprone-parent-virtual-call) clazy:exclude=skipped-base-method
193}
194
195bool QgsMultiPolygon::addGeometries( const QVector<QgsAbstractGeometry *> &geometries )
196{
197 for ( QgsAbstractGeometry *g : geometries )
198 {
199 if ( !qgsgeometry_cast<QgsPolygon *>( g ) )
200 {
201 qDeleteAll( geometries );
202 return false;
203 }
204 }
205
206 if ( mGeometries.empty() && !geometries.empty() )
207 {
209 }
210 mGeometries.reserve( mGeometries.size() + geometries.size() );
211 for ( QgsAbstractGeometry *g : geometries )
212 {
213 if ( is3D() && !g->is3D() )
215 else if ( !is3D() && g->is3D() )
216 g->dropZValue();
217 if ( isMeasure() && !g->isMeasure() )
219 else if ( !isMeasure() && g->isMeasure() )
220 g->dropMValue();
221 mGeometries.append( g );
222 }
223
224 clearCache();
225 return true;
226}
227
229{
230 if ( !g || !qgsgeometry_cast< QgsPolygon * >( g ) )
231 {
232 delete g;
233 return false;
234 }
235
236 return QgsMultiSurface::insertGeometry( g, index );
237}
238
240{
241 std::unique_ptr< QgsMultiPolygon > res = std::make_unique< QgsMultiPolygon >();
242 res->reserve( mGeometries.size() );
243 for ( int i = 0; i < mGeometries.size(); ++i )
244 {
245 res->addGeometry( mGeometries.at( i )->simplifyByDistance( tolerance ) );
246 }
247 return res.release();
248}
249
251{
252 QgsMultiSurface *multiSurface = new QgsMultiSurface();
253 multiSurface->reserve( mGeometries.size() );
254 for ( int i = 0; i < mGeometries.size(); ++i )
255 {
256 multiSurface->addGeometry( mGeometries.at( i )->clone() );
257 }
258 return multiSurface;
259}
260
262{
263 std::unique_ptr< QgsMultiLineString > multiLine( new QgsMultiLineString() );
264 multiLine->reserve( mGeometries.size() );
265 for ( int i = 0; i < mGeometries.size(); ++i )
266 {
267 if ( QgsPolygon *polygon = qgsgeometry_cast<QgsPolygon *>( mGeometries.at( i ) ) )
268 {
269 QgsAbstractGeometry *polygonBoundary = polygon->boundary();
270
271 if ( QgsLineString *lineStringBoundary = qgsgeometry_cast< QgsLineString * >( polygonBoundary ) )
272 {
274 }
275 else if ( QgsMultiLineString *multiLineStringBoundary = qgsgeometry_cast< QgsMultiLineString * >( polygonBoundary ) )
276 {
277 for ( int j = 0; j < multiLineStringBoundary->numGeometries(); ++j )
278 {
279 multiLine->addGeometry( multiLineStringBoundary->geometryN( j )->clone() );
280 }
281 delete multiLineStringBoundary;
282 }
283 else
284 {
285 delete polygonBoundary;
286 }
287 }
288 }
289 if ( multiLine->numGeometries() == 0 )
290 {
291 return nullptr;
292 }
293 return multiLine.release();
294}
295
297{
298 return true;
299}
@ MultiPolygon
MultiPolygon.
Abstract base class for all geometries.
Adds a z-dimension to the geometry, initialized to a preset value.
virtual QgsAbstractGeometry * boundary() const =0
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
bool isMeasure() const
Returns true if the geometry contains m values.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
AxisOrder
Axis order for GML generation.
Adds a measure to the geometry, initialized to a preset value.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, Qgis::WkbType baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
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.
QVector< QgsAbstractGeometry * > mGeometries
void reserve(int size)
Attempts to allocate memory for at least size geometries.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
bool isEmpty() const override
Returns true if the geometry is empty.
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.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
static json pointsToJson(const QgsPointSequence &points, int precision)
Returns coordinates as json object.
Line string geometry type, with support for z-dimension and m-values.
Multi line string geometry collection.
Multi polygon geometry collection.
bool wktOmitChildType() const override
Returns whether child type names are omitted from Wkt representations of the collection.
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
QgsMultiSurface * toCurveType() const override
Returns the geometry converted to the more generic curve type QgsMultiSurface.
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.
QgsMultiPolygon * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
bool addGeometries(const QVector< QgsAbstractGeometry * > &geometries) final
Adds a list of geometries to the collection, transferring ownership to the collection.
void clear() override
Clears the geometry, ie reset it to a null geometry.
QgsMultiPolygon()
Constructor for an empty multipolygon geometry.
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.
QString geometryType() const override
Returns a unique string representing the geometry type.
QgsMultiPolygon * clone() const override
Clones the geometry by performing a deep copy.
Adds a geometry and takes ownership. Returns true in case of success.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
QgsPolygon * polygonN(int index)
Returns the polygon with the specified index.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
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...
Multi surface geometry collection.
QgsMultiSurface()
Constructor for an empty multisurface geometry.