QGIS API Documentation 4.3.0-Master (bf28115e945)
Loading...
Searching...
No Matches
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
18#include <nlohmann/json.hpp>
19
20#include "qgspoint.h"
21#include "qgsvertexid.h"
22
23#include <QJsonArray>
24#include <QJsonObject>
25#include <QRegularExpression>
26#include <QString>
27
28using namespace Qt::StringLiterals;
29
34
35QgsMultiPoint::QgsMultiPoint( const QVector<QgsPoint> &points )
36{
37 if ( points.isEmpty() )
38 {
40 return;
41 }
42
43 const Qgis::WkbType ptType = points.at( 0 ).wkbType();
45 const int pointCount = points.size();
46 mGeometries.resize( pointCount );
47
48 const QgsPoint *pointIn = points.data();
49 for ( int i = 0; i < pointCount; ++i, ++pointIn )
50 {
51 mGeometries[i] = pointIn->clone();
52 }
53}
54
55QgsMultiPoint::QgsMultiPoint( const QVector<QgsPoint *> &points )
56{
57 if ( points.isEmpty() )
58 {
60 return;
61 }
62
63 const Qgis::WkbType ptType = points.at( 0 )->wkbType();
65 const int pointCount = points.size();
66 mGeometries.resize( pointCount );
67
68 for ( int i = 0; i < pointCount; ++i )
69 {
70 mGeometries[i] = points[i];
71 }
72}
73
74QgsMultiPoint::QgsMultiPoint( const QVector<QgsPointXY> &points )
75{
77 const int pointCount = points.size();
78 mGeometries.resize( pointCount );
79
80 const QgsPointXY *pointIn = points.data();
81 for ( int i = 0; i < pointCount; ++i, ++pointIn )
82 {
83 mGeometries[i] = new QgsPoint( pointIn->x(), pointIn->y() );
84 }
85}
86
87QgsMultiPoint::QgsMultiPoint( const QVector<double> &x, const QVector<double> &y, const QVector<double> &z, const QVector<double> &m )
88{
90 const int pointCount = std::min( x.size(), y.size() );
91 mGeometries.resize( pointCount );
92
93 const double *xIn = x.data();
94 const double *yIn = y.data();
95 const double *zIn = nullptr;
96 const double *mIn = nullptr;
97 if ( !z.isEmpty() && z.count() >= pointCount )
98 {
100 zIn = z.data();
101 }
102 if ( !m.isEmpty() && m.count() >= pointCount )
103 {
105 mIn = m.data();
106 }
107
108 for ( int i = 0; i < pointCount; ++i )
109 {
110 mGeometries[i] = new QgsPoint( *xIn++, *yIn++, zIn ? *zIn++ : std::numeric_limits< double >::quiet_NaN(), mIn ? *mIn++ : std::numeric_limits< double >::quiet_NaN() );
111 }
112}
113
115{
116 return qgsgeometry_cast< QgsPoint * >( geometryN( index ) );
117}
118
119const QgsPoint *QgsMultiPoint::pointN( int index ) const
120{
122}
123
125{
126 return u"MultiPoint"_s;
127}
128
130{
131 auto result = std::make_unique< QgsMultiPoint >();
132 result->mWkbType = mWkbType;
133 return result.release();
134}
135
137{
138 return new QgsMultiPoint( *this );
139}
140
142{
143 return clone();
144}
145
146bool QgsMultiPoint::fromWkt( const QString &wkt )
147{
148 QString collectionWkt( wkt );
149 //test for non-standard MultiPoint(x1 y1, x2 y2) format
150 const thread_local QRegularExpression regex( u"^\\s*MultiPoint\\s*[ZM]*\\s*\\(\\s*[-\\d]"_s, QRegularExpression::CaseInsensitiveOption );
151 const QRegularExpressionMatch match = regex.match( collectionWkt );
152 if ( match.hasMatch() )
153 {
154 //alternate style without extra brackets, upgrade to standard
155 collectionWkt.replace( '(', "(("_L1 ).replace( ')', "))"_L1 ).replace( ',', "),("_L1 );
156 }
157
158 return fromCollectionWkt( collectionWkt, { Qgis::WkbType::Point }, u"Point"_s );
159}
160
166
167QDomElement QgsMultiPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
168{
169 QDomElement elemMultiPoint = doc.createElementNS( ns, u"MultiPoint"_s );
170
171 if ( isEmpty() )
172 return elemMultiPoint;
173
174 for ( const QgsAbstractGeometry *geom : mGeometries )
175 {
177 {
178 QDomElement elemPointMember = doc.createElementNS( ns, u"pointMember"_s );
179 elemPointMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
180 elemMultiPoint.appendChild( elemPointMember );
181 }
182 }
183
184 return elemMultiPoint;
185}
186
187QDomElement QgsMultiPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
188{
189 QDomElement elemMultiPoint = doc.createElementNS( ns, u"MultiPoint"_s );
190
191 if ( isEmpty() )
192 return elemMultiPoint;
193
194 for ( const QgsAbstractGeometry *geom : mGeometries )
195 {
197 {
198 QDomElement elemPointMember = doc.createElementNS( ns, u"pointMember"_s );
199 elemPointMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
200 elemMultiPoint.appendChild( elemPointMember );
201 }
202 }
203
204 return elemMultiPoint;
205}
206
207json QgsMultiPoint::asJsonObject( int precision, Qgis::GeoJsonProfile profile ) const
208{
209 json j {
210 { "type", "MultiPoint" },
211 { "coordinates", json::array() },
212 };
213 for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) )
214 {
215 const QgsPoint *point = static_cast<const QgsPoint *>( geom );
216 json coords = { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ) };
217 if ( point->is3D() )
218 {
219 coords.push_back( qgsRound( point->z(), precision ) );
220 }
221 if ( isMeasure() && ( profile == Qgis::GeoJsonProfile::JsonFg || profile == Qgis::GeoJsonProfile::JsonFgPlus ) )
222 {
223 coords.push_back( qgsRound( point->m(), precision ) );
224 }
225 j["coordinates"].push_back( coords );
226 }
227 return j;
228}
229
230
232{
233 return mGeometries.size();
234}
235
237{
239 {
240 delete g;
241 return false;
242 }
243 if ( mGeometries.empty() )
244 {
246 }
247 if ( is3D() && !g->is3D() )
248 g->addZValue();
249 else if ( !is3D() && g->is3D() )
250 g->dropZValue();
251 if ( isMeasure() && !g->isMeasure() )
252 g->addMValue();
253 else if ( !isMeasure() && g->isMeasure() )
254 g->dropMValue();
255
257}
258
259bool QgsMultiPoint::addGeometries( const QVector<QgsAbstractGeometry *> &geometries )
260{
261 for ( QgsAbstractGeometry *g : geometries )
262 {
264 {
265 qDeleteAll( geometries );
266 return false;
267 }
268 }
269
270 if ( mGeometries.empty() && !geometries.empty() )
271 {
273 }
274 mGeometries.reserve( mGeometries.size() + geometries.size() );
275 for ( QgsAbstractGeometry *g : geometries )
276 {
277 if ( is3D() && !g->is3D() )
278 g->addZValue();
279 else if ( !is3D() && g->is3D() )
280 g->dropZValue();
281 if ( isMeasure() && !g->isMeasure() )
282 g->addMValue();
283 else if ( !isMeasure() && g->isMeasure() )
284 g->dropMValue();
285 mGeometries.append( g );
286 }
287
288 clearCache();
289 return true;
290}
291
293{
295 {
296 delete g;
297 return false;
298 }
299
300 return QgsGeometryCollection::insertGeometry( g, index );
301}
302
304{
305 return nullptr;
306}
307
309{
310 if ( id.part < 0 || id.part >= mGeometries.count() || id.vertex != 0 || id.ring != 0 )
311 return -1;
312
313 return id.part; // can shortcut the calculation, since each part will have 1 vertex
314}
315
317{
318 return 0.0;
319}
320
322{
323 return true;
324}
325
327{
328 return clone();
329}
330
331void QgsMultiPoint::filterVertices( const std::function<bool( const QgsPoint & )> &filter )
332{
333 mGeometries.erase(
334 std::remove_if(
335 mGeometries.begin(),
336 mGeometries.end(), // clazy:exclude=detaching-member
337 [&filter]( const QgsAbstractGeometry *part ) {
338 if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( part ) )
339 {
340 if ( !filter( *point ) )
341 {
342 delete point;
343 return true;
344 }
345 else
346 {
347 return false;
348 }
349 }
350 else
351 {
352 delete part;
353 return true;
354 }
355 }
356 ),
357 mGeometries.end()
358 ); // clazy:exclude=detaching-member
359}
360
362{
363 return true;
364}
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
Definition qgis.h:2210
GeoJsonProfile
GeoJson export Profile according to OGC Features and Geometries JSON - Part 1: Core https://docs....
Definition qgis.h:5045
@ JsonFg
GeoJson profile from OGC Features and Geometries JSON Part 1: core "http://www.opengis....
Definition qgis.h:5048
@ JsonFgPlus
GeoJson profile from OGC Features and Geometries JSON Part 1: core "http://www.opengis....
Definition qgis.h:5049
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition qgis.h:294
@ MultiPointZ
MultiPointZ.
Definition qgis.h:317
@ Point
Point.
Definition qgis.h:296
@ MultiPoint
MultiPoint.
Definition qgis.h:300
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.
QgsAbstractGeometry()=default
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.
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.
json asJsonObject(int precision=17, Qgis::GeoJsonProfile profile=Qgis::GeoJsonProfile::Legacy) const override
Returns a json object representation of the geometry with the given precision and profile.
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.
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:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition qgspoint.cpp:138
double z
Definition qgspoint.h:58
double x
Definition qgspoint.h:56
double m
Definition qgspoint.h:59
double y
Definition qgspoint.h:57
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:7475
T qgsgeometry_cast(QgsAbstractGeometry *geom)
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:35