QGIS API Documentation  3.21.0-Master (56b4176581)
qgsmultipoint.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsmultipoint.cpp
3  -------------------------------------------------------------------
4 Date : 29 Oct 2014
5 Copyright : (C) 2014 by Marco Hugentobler
6 email : 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 
37 const 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 
64 bool 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 
85 QDomElement 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 
105 QDomElement 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 
201 bool QgsMultiPoint::isValid( QString &, Qgis::GeometryValidityFlags ) const
202 {
203  return true;
204 }
205 
206 void 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.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
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.
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:702
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places.
Definition: qgis.h:1187
int precision
Utility class for identifying a unique vertex within a geometry.