QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
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 "qgsapplication.h"
18#include "qgsgeometryutils.h"
19#include "qgspoint.h"
20#include "qgswkbptr.h"
21
22#include <QJsonArray>
23#include <QJsonObject>
24#include <QRegularExpression>
25#include <nlohmann/json.hpp>
26
28{
30}
31
32QgsMultiPoint::QgsMultiPoint( const QVector<QgsPoint> &points )
33{
34 if ( points.isEmpty() )
35 {
37 return;
38 }
39
40 const Qgis::WkbType ptType = points.at( 0 ).wkbType();
42 const int pointCount = points.size();
43 mGeometries.resize( pointCount );
44
45 const QgsPoint *pointIn = points.data();
46 for ( int i = 0; i < pointCount; ++i, ++pointIn )
47 {
48 mGeometries[ i ] = pointIn->clone();
49 }
50}
51
52QgsMultiPoint::QgsMultiPoint( const QVector<QgsPoint *> &points )
53{
54 if ( points.isEmpty() )
55 {
57 return;
58 }
59
60 const Qgis::WkbType ptType = points.at( 0 )->wkbType();
62 const int pointCount = points.size();
63 mGeometries.resize( pointCount );
64
65 for ( int i = 0; i < pointCount; ++i )
66 {
67 mGeometries[ i ] = points[i];
68 }
69}
70
71QgsMultiPoint::QgsMultiPoint( const QVector<QgsPointXY> &points )
72{
74 const int pointCount = points.size();
75 mGeometries.resize( pointCount );
76
77 const QgsPointXY *pointIn = points.data();
78 for ( int i = 0; i < pointCount; ++i, ++pointIn )
79 {
80 mGeometries[ i ] = new QgsPoint( pointIn->x(), pointIn->y() );
81 }
82}
83
84QgsMultiPoint::QgsMultiPoint( const QVector<double> &x, const QVector<double> &y, const QVector<double> &z, const QVector<double> &m )
85{
87 const int pointCount = std::min( x.size(), y.size() );
88 mGeometries.resize( pointCount );
89
90 const double *xIn = x.data();
91 const double *yIn = y.data();
92 const double *zIn = nullptr;
93 const double *mIn = nullptr;
94 if ( !z.isEmpty() && z.count() >= pointCount )
95 {
97 zIn = z.data();
98 }
99 if ( !m.isEmpty() && m.count() >= pointCount )
100 {
102 mIn = m.data();
103 }
104
105 for ( int i = 0; i < pointCount; ++i )
106 {
107 mGeometries[ i ] = new QgsPoint( *xIn++, *yIn++, zIn ? *zIn++ : std::numeric_limits< double >::quiet_NaN(), mIn ? *mIn++ : std::numeric_limits< double >::quiet_NaN() );
108 }
109}
110
112{
113 return qgsgeometry_cast< QgsPoint * >( geometryN( index ) );
114}
115
116const QgsPoint *QgsMultiPoint::pointN( int index ) const
117{
118 return qgsgeometry_cast< const QgsPoint * >( geometryN( index ) );
119}
120
122{
123 return QStringLiteral( "MultiPoint" );
124}
125
127{
128 auto result = std::make_unique< QgsMultiPoint >();
129 result->mWkbType = mWkbType;
130 return result.release();
131}
132
134{
135 return new QgsMultiPoint( *this );
136}
137
139{
140 return clone();
141}
142
143bool QgsMultiPoint::fromWkt( const QString &wkt )
144{
145 QString collectionWkt( wkt );
146 //test for non-standard MultiPoint(x1 y1, x2 y2) format
147 const thread_local QRegularExpression regex( QStringLiteral( "^\\s*MultiPoint\\s*[ZM]*\\s*\\(\\s*[-\\d]" ), QRegularExpression::CaseInsensitiveOption );
148 const QRegularExpressionMatch match = regex.match( collectionWkt );
149 if ( match.hasMatch() )
150 {
151 //alternate style without extra brackets, upgrade to standard
152 collectionWkt.replace( '(', QLatin1String( "((" ) ).replace( ')', QLatin1String( "))" ) ).replace( ',', QLatin1String( "),(" ) );
153 }
154
155 return fromCollectionWkt( collectionWkt, QVector<QgsAbstractGeometry *>() << new QgsPoint, QStringLiteral( "Point" ) );
156}
157
159{
162}
163
164QDomElement QgsMultiPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
165{
166 QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
167
168 if ( isEmpty() )
169 return elemMultiPoint;
170
171 for ( const QgsAbstractGeometry *geom : mGeometries )
172 {
173 if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
174 {
175 QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
176 elemPointMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
177 elemMultiPoint.appendChild( elemPointMember );
178 }
179 }
180
181 return elemMultiPoint;
182}
183
184QDomElement QgsMultiPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
185{
186 QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
187
188 if ( isEmpty() )
189 return elemMultiPoint;
190
191 for ( const QgsAbstractGeometry *geom : mGeometries )
192 {
193 if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
194 {
195 QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
196 elemPointMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
197 elemMultiPoint.appendChild( elemPointMember );
198 }
199 }
200
201 return elemMultiPoint;
202}
203
205{
206 json j
207 {
208 { "type", "MultiPoint" },
209 { "coordinates", json::array() },
210 };
211 for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) )
212 {
213 const QgsPoint *point = static_cast<const QgsPoint *>( geom );
214 if ( point->is3D() )
215 j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ), qgsRound( point->z(), precision ) } );
216 else
217 j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ) } );
218 }
219 return j;
220}
221
222
224{
225 return mGeometries.size();
226}
227
229{
230 if ( !qgsgeometry_cast<QgsPoint *>( g ) )
231 {
232 delete g;
233 return false;
234 }
235 if ( mGeometries.empty() )
236 {
238 }
239 if ( is3D() && !g->is3D() )
240 g->addZValue();
241 else if ( !is3D() && g->is3D() )
242 g->dropZValue();
243 if ( isMeasure() && !g->isMeasure() )
244 g->addMValue();
245 else if ( !isMeasure() && g->isMeasure() )
246 g->dropMValue();
247
249}
250
252{
254 {
255 delete g;
256 return false;
257 }
258
259 return QgsGeometryCollection::insertGeometry( g, index );
260}
261
263{
264 return nullptr;
265}
266
268{
269 if ( id.part < 0 || id.part >= mGeometries.count() || id.vertex != 0 || id.ring != 0 )
270 return -1;
271
272 return id.part; // can shortcut the calculation, since each part will have 1 vertex
273}
274
276{
277 return 0.0;
278}
279
281{
282 return true;
283}
284
285void QgsMultiPoint::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
286{
287 mGeometries.erase( std::remove_if( mGeometries.begin(), mGeometries.end(), // clazy:exclude=detaching-member
288 [&filter]( const QgsAbstractGeometry * part )
289 {
290 if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( part ) )
291 {
292 if ( !filter( *point ) )
293 {
294 delete point;
295 return true;
296 }
297 else
298 {
299 return false;
300 }
301 }
302 else
303 {
304 delete part;
305 return true;
306 }
307 } ), mGeometries.end() ); // clazy:exclude=detaching-member
308}
309
311{
312 return true;
313}
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
Definition: qgis.h:1648
WkbType
The WKB type describes the number of dimensions a geometry has.
Definition: qgis.h:182
@ 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
void clear() override
Clears the geometry, ie reset it to a null geometry.
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.
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.
Multi point geometry collection.
Definition: qgsmultipoint.h:29
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.
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.
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.
A class to represent a 2D point.
Definition: qgspointxy.h:60
double y
Definition: qgspointxy.h:64
Q_GADGET double x
Definition: qgspointxy.h:63
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition: qgspoint.cpp:105
double z
Definition: qgspoint.h:54
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.
Definition: qgswkbtypes.h:727
static Qgis::WkbType addM(Qgis::WkbType type)
Adds the m dimension to a WKB type and returns the new type.
Definition: qgswkbtypes.h:1092
static bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:973
static bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1023
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:628
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:5248
int precision
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:30