QGIS API Documentation 3.43.0-Master (8fc5848dca1)
qgsmultipoint.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsmultipoint.cpp
3 -------------------------------------------------------------------
4Date : 29 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 *
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 "qgsmultipoint.h"
17#include "qgspoint.h"
18#include "qgsvertexid.h"
19
20#include <QJsonArray>
21#include <QJsonObject>
22#include <QRegularExpression>
23#include <nlohmann/json.hpp>
24
29
30QgsMultiPoint::QgsMultiPoint( const QVector<QgsPoint> &points )
31{
32 if ( points.isEmpty() )
33 {
35 return;
36 }
37
38 const Qgis::WkbType ptType = points.at( 0 ).wkbType();
40 const int pointCount = points.size();
41 mGeometries.resize( pointCount );
42
43 const QgsPoint *pointIn = points.data();
44 for ( int i = 0; i < pointCount; ++i, ++pointIn )
45 {
46 mGeometries[ i ] = pointIn->clone();
47 }
48}
49
50QgsMultiPoint::QgsMultiPoint( const QVector<QgsPoint *> &points )
51{
52 if ( points.isEmpty() )
53 {
55 return;
56 }
57
58 const Qgis::WkbType ptType = points.at( 0 )->wkbType();
60 const int pointCount = points.size();
61 mGeometries.resize( pointCount );
62
63 for ( int i = 0; i < pointCount; ++i )
64 {
65 mGeometries[ i ] = points[i];
66 }
67}
68
69QgsMultiPoint::QgsMultiPoint( const QVector<QgsPointXY> &points )
70{
72 const int pointCount = points.size();
73 mGeometries.resize( pointCount );
74
75 const QgsPointXY *pointIn = points.data();
76 for ( int i = 0; i < pointCount; ++i, ++pointIn )
77 {
78 mGeometries[ i ] = new QgsPoint( pointIn->x(), pointIn->y() );
79 }
80}
81
82QgsMultiPoint::QgsMultiPoint( const QVector<double> &x, const QVector<double> &y, const QVector<double> &z, const QVector<double> &m )
83{
85 const int pointCount = std::min( x.size(), y.size() );
86 mGeometries.resize( pointCount );
87
88 const double *xIn = x.data();
89 const double *yIn = y.data();
90 const double *zIn = nullptr;
91 const double *mIn = nullptr;
92 if ( !z.isEmpty() && z.count() >= pointCount )
93 {
95 zIn = z.data();
96 }
97 if ( !m.isEmpty() && m.count() >= pointCount )
98 {
100 mIn = m.data();
101 }
102
103 for ( int i = 0; i < pointCount; ++i )
104 {
105 mGeometries[ i ] = new QgsPoint( *xIn++, *yIn++, zIn ? *zIn++ : std::numeric_limits< double >::quiet_NaN(), mIn ? *mIn++ : std::numeric_limits< double >::quiet_NaN() );
106 }
107}
108
110{
111 return qgsgeometry_cast< QgsPoint * >( geometryN( index ) );
112}
113
114const QgsPoint *QgsMultiPoint::pointN( int index ) const
115{
116 return qgsgeometry_cast< const QgsPoint * >( geometryN( index ) );
117}
118
120{
121 return QStringLiteral( "MultiPoint" );
122}
123
125{
126 auto result = std::make_unique< QgsMultiPoint >();
127 result->mWkbType = mWkbType;
128 return result.release();
129}
130
132{
133 return new QgsMultiPoint( *this );
134}
135
137{
138 return clone();
139}
140
141bool QgsMultiPoint::fromWkt( const QString &wkt )
142{
143 QString collectionWkt( wkt );
144 //test for non-standard MultiPoint(x1 y1, x2 y2) format
145 const thread_local QRegularExpression regex( QStringLiteral( "^\\s*MultiPoint\\s*[ZM]*\\s*\\(\\s*[-\\d]" ), QRegularExpression::CaseInsensitiveOption );
146 const QRegularExpressionMatch match = regex.match( collectionWkt );
147 if ( match.hasMatch() )
148 {
149 //alternate style without extra brackets, upgrade to standard
150 collectionWkt.replace( '(', QLatin1String( "((" ) ).replace( ')', QLatin1String( "))" ) ).replace( ',', QLatin1String( "),(" ) );
151 }
152
153 return fromCollectionWkt( collectionWkt, { Qgis::WkbType::Point }, QStringLiteral( "Point" ) );
154}
155
161
162QDomElement QgsMultiPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
163{
164 QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
165
166 if ( isEmpty() )
167 return elemMultiPoint;
168
169 for ( const QgsAbstractGeometry *geom : mGeometries )
170 {
171 if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
172 {
173 QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
174 elemPointMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
175 elemMultiPoint.appendChild( elemPointMember );
176 }
177 }
178
179 return elemMultiPoint;
180}
181
182QDomElement QgsMultiPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
183{
184 QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
185
186 if ( isEmpty() )
187 return elemMultiPoint;
188
189 for ( const QgsAbstractGeometry *geom : mGeometries )
190 {
191 if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
192 {
193 QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
194 elemPointMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
195 elemMultiPoint.appendChild( elemPointMember );
196 }
197 }
198
199 return elemMultiPoint;
200}
201
203{
204 json j
205 {
206 { "type", "MultiPoint" },
207 { "coordinates", json::array() },
208 };
209 for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) )
210 {
211 const QgsPoint *point = static_cast<const QgsPoint *>( geom );
212 if ( point->is3D() )
213 j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ), qgsRound( point->z(), precision ) } );
214 else
215 j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ) } );
216 }
217 return j;
218}
219
220
222{
223 return mGeometries.size();
224}
225
227{
228 if ( !qgsgeometry_cast<QgsPoint *>( g ) )
229 {
230 delete g;
231 return false;
232 }
233 if ( mGeometries.empty() )
234 {
236 }
237 if ( is3D() && !g->is3D() )
238 g->addZValue();
239 else if ( !is3D() && g->is3D() )
240 g->dropZValue();
241 if ( isMeasure() && !g->isMeasure() )
242 g->addMValue();
243 else if ( !isMeasure() && g->isMeasure() )
244 g->dropMValue();
245
247}
248
249bool QgsMultiPoint::addGeometries( const QVector<QgsAbstractGeometry *> &geometries )
250{
251 for ( QgsAbstractGeometry *g : geometries )
252 {
253 if ( !qgsgeometry_cast<QgsPoint *>( g ) )
254 {
255 qDeleteAll( geometries );
256 return false;
257 }
258 }
259
260 if ( mGeometries.empty() && !geometries.empty() )
261 {
263 }
264 mGeometries.reserve( mGeometries.size() + geometries.size() );
265 for ( QgsAbstractGeometry *g : geometries )
266 {
267 if ( is3D() && !g->is3D() )
268 g->addZValue();
269 else if ( !is3D() && g->is3D() )
270 g->dropZValue();
271 if ( isMeasure() && !g->isMeasure() )
272 g->addMValue();
273 else if ( !isMeasure() && g->isMeasure() )
274 g->dropMValue();
275 mGeometries.append( g );
276 }
277
278 clearCache();
279 return true;
280}
281
283{
285 {
286 delete g;
287 return false;
288 }
289
290 return QgsGeometryCollection::insertGeometry( g, index );
291}
292
294{
295 return nullptr;
296}
297
299{
300 if ( id.part < 0 || id.part >= mGeometries.count() || id.vertex != 0 || id.ring != 0 )
301 return -1;
302
303 return id.part; // can shortcut the calculation, since each part will have 1 vertex
304}
305
307{
308 return 0.0;
309}
310
312{
313 return true;
314}
315
317{
318 return clone();
319}
320
321void QgsMultiPoint::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
322{
323 mGeometries.erase( std::remove_if( mGeometries.begin(), mGeometries.end(), // clazy:exclude=detaching-member
324 [&filter]( const QgsAbstractGeometry * part )
325 {
326 if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( part ) )
327 {
328 if ( !filter( *point ) )
329 {
330 delete point;
331 return true;
332 }
333 else
334 {
335 return false;
336 }
337 }
338 else
339 {
340 delete part;
341 return true;
342 }
343 } ), mGeometries.end() ); // clazy:exclude=detaching-member
344}
345
347{
348 return true;
349}
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
Definition qgis.h:2038
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:256
@ MultiPointZ
MultiPointZ.
@ MultiPoint
MultiPoint.
Abstract base class for all geometries.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
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.
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
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.
QVector< QgsAbstractGeometry * > mGeometries
bool fromCollectionWkt(const QString &wkt, const QVector< Qgis::WkbType > &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
void clear() override
Clears the geometry, ie reset it to a null geometry.
void clearCache() const override
Clears any cached parameters associated with the geometry, e.g., bounding boxes.
virtual bool insertGeometry(QgsAbstractGeometry *g, int index)
Inserts a geometry before a specified index and takes ownership.
bool isEmpty() const override
Returns true if the geometry is empty.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
Multi point geometry collection.
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.
QgsMultiPoint * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
bool wktOmitChildType() const override
Returns whether child type names are omitted from Wkt representations of the collection.
QgsPoint * pointN(int index)
Returns the point with the specified index.
void filterVertices(const std::function< bool(const QgsPoint &) > &filter) override
Filters the vertices from the geometry in place, removing any which do not return true for the filter...
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
bool addGeometries(const QVector< QgsAbstractGeometry * > &geometries) final
Adds a list of geometries to the collection, transferring ownership to the collection.
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
QgsMultiPoint()
Constructor for an empty multipoint geometry.
QgsMultiPoint * toCurveType() const override
Returns the geometry converted to the more generic curve type.
QString geometryType() const override
Returns a unique string representing the geometry type.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
QgsMultiPoint * clone() const override
Clones the geometry by performing a deep copy.
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.
QgsMultiPoint * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
Represents a 2D point.
Definition qgspointxy.h:60
double y
Definition qgspointxy.h:64
double x
Definition qgspointxy.h:63
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:49
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition qgspoint.cpp:105
double z
Definition qgspoint.h:54
double x
Definition qgspoint.h:52
double y
Definition qgspoint.h:53
static Qgis::WkbType zmType(Qgis::WkbType type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition qgis.h:6408
int precision
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:30