QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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
33{
34 return qgsgeometry_cast< QgsPoint * >( geometryN( index ) );
35}
36
37const QgsPoint *QgsMultiPoint::pointN( int index ) const
38{
39 return qgsgeometry_cast< const QgsPoint * >( geometryN( index ) );
40}
41
43{
44 return QStringLiteral( "MultiPoint" );
45}
46
48{
49 auto result = std::make_unique< QgsMultiPoint >();
50 result->mWkbType = mWkbType;
51 return result.release();
52}
53
55{
56 return new QgsMultiPoint( *this );
57}
58
60{
61 return clone();
62}
63
64bool QgsMultiPoint::fromWkt( const QString &wkt )
65{
66 QString collectionWkt( wkt );
67 //test for non-standard MultiPoint(x1 y1, x2 y2) format
68 const thread_local QRegularExpression regex( QStringLiteral( "^\\s*MultiPoint\\s*[ZM]*\\s*\\(\\s*[-\\d]" ), QRegularExpression::CaseInsensitiveOption );
69 const QRegularExpressionMatch match = regex.match( collectionWkt );
70 if ( match.hasMatch() )
71 {
72 //alternate style without extra brackets, upgrade to standard
73 collectionWkt.replace( '(', QLatin1String( "((" ) ).replace( ')', QLatin1String( "))" ) ).replace( ',', QLatin1String( "),(" ) );
74 }
75
76 return fromCollectionWkt( collectionWkt, QVector<QgsAbstractGeometry *>() << new QgsPoint, QStringLiteral( "Point" ) );
77}
78
80{
83}
84
85QDomElement QgsMultiPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
86{
87 QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
88
89 if ( isEmpty() )
90 return elemMultiPoint;
91
92 for ( const QgsAbstractGeometry *geom : mGeometries )
93 {
94 if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
95 {
96 QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
97 elemPointMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
98 elemMultiPoint.appendChild( elemPointMember );
99 }
100 }
101
102 return elemMultiPoint;
103}
104
105QDomElement QgsMultiPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
106{
107 QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
108
109 if ( isEmpty() )
110 return elemMultiPoint;
111
112 for ( const QgsAbstractGeometry *geom : mGeometries )
113 {
114 if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
115 {
116 QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
117 elemPointMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
118 elemMultiPoint.appendChild( elemPointMember );
119 }
120 }
121
122 return elemMultiPoint;
123}
124
126{
127 json j
128 {
129 { "type", "MultiPoint" },
130 { "coordinates", json::array() },
131 };
132 for ( const QgsAbstractGeometry *geom : std::as_const( mGeometries ) )
133 {
134 const QgsPoint *point = static_cast<const QgsPoint *>( geom );
135 if ( point->is3D() )
136 j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ), qgsRound( point->z(), precision ) } );
137 else
138 j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ) } );
139 }
140 return j;
141}
142
143
145{
146 return mGeometries.size();
147}
148
150{
151 if ( !qgsgeometry_cast<QgsPoint *>( g ) )
152 {
153 delete g;
154 return false;
155 }
156 if ( mGeometries.empty() )
157 {
159 }
160 if ( is3D() && !g->is3D() )
161 g->addZValue();
162 else if ( !is3D() && g->is3D() )
163 g->dropZValue();
164 if ( isMeasure() && !g->isMeasure() )
165 g->addMValue();
166 else if ( !isMeasure() && g->isMeasure() )
167 g->dropMValue();
168
170}
171
173{
174 if ( !g || QgsWkbTypes::flatType( g->wkbType() ) != QgsWkbTypes::Point )
175 {
176 delete g;
177 return false;
178 }
179
180 return QgsGeometryCollection::insertGeometry( g, index );
181}
182
184{
185 return nullptr;
186}
187
189{
190 if ( id.part < 0 || id.part >= mGeometries.count() || id.vertex != 0 || id.ring != 0 )
191 return -1;
192
193 return id.part; // can shortcut the calculation, since each part will have 1 vertex
194}
195
197{
198 return 0.0;
199}
200
201bool QgsMultiPoint::isValid( QString &, Qgis::GeometryValidityFlags ) const
202{
203 return true;
204}
205
206void QgsMultiPoint::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
207{
208 mGeometries.erase( std::remove_if( mGeometries.begin(), mGeometries.end(), // clazy:exclude=detaching-member
209 [&filter]( const QgsAbstractGeometry * part )
210 {
211 if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( part ) )
212 {
213 if ( !filter( *point ) )
214 {
215 delete point;
216 return true;
217 }
218 else
219 {
220 return false;
221 }
222 }
223 else
224 {
225 delete part;
226 return true;
227 }
228 } ), mGeometries.end() ); // clazy:exclude=detaching-member
229}
230
232{
233 return true;
234}
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 is3D() const SIP_HOLDGIL
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.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
QgsWkbTypes::Type mWkbType
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
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.
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:30
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.
int nCoordinates() const override SIP_HOLDGIL
Returns the number of nodes contained in the geometry.
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override SIP_HOLDGIL
Checks validity of the geometry, and returns true if the geometry is valid.
QgsMultiPoint() SIP_HOLDGIL
Constructor for an empty multipoint geometry.
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...
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
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 * 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.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:49
Q_GADGET double x
Definition: qgspoint.h:52
double z
Definition: qgspoint.h:54
double y
Definition: qgspoint.h:53
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:732
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:2581
int precision
Utility class for identifying a unique vertex within a geometry.
Definition: qgsvertexid.h:31