QGIS API Documentation  3.17.0-Master (3b262f2a79)
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 <nlohmann/json.hpp>
25 
27 {
29 }
30 
32 {
33  return qgsgeometry_cast< QgsPoint * >( geometryN( index ) );
34 }
35 
36 const QgsPoint *QgsMultiPoint::pointN( int index ) const
37 {
38  return qgsgeometry_cast< const QgsPoint * >( geometryN( index ) );
39 }
40 
42 {
43  return QStringLiteral( "MultiPoint" );
44 }
45 
47 {
48  auto result = qgis::make_unique< QgsMultiPoint >();
49  result->mWkbType = mWkbType;
50  return result.release();
51 }
52 
54 {
55  return new QgsMultiPoint( *this );
56 }
57 
59 {
60  return clone();
61 }
62 
63 bool QgsMultiPoint::fromWkt( const QString &wkt )
64 {
65  QString collectionWkt( wkt );
66  //test for non-standard MultiPoint(x1 y1, x2 y2) format
67  QRegExp regex( "^\\s*MultiPoint\\s*[ZM]*\\s*\\(\\s*[-\\d]" );
68  regex.setCaseSensitivity( Qt::CaseInsensitive );
69  if ( regex.indexIn( collectionWkt ) >= 0 )
70  {
71  //alternate style without extra brackets, upgrade to standard
72  collectionWkt.replace( '(', QLatin1String( "((" ) ).replace( ')', QLatin1String( "))" ) ).replace( ',', QLatin1String( "),(" ) );
73  }
74 
75  return fromCollectionWkt( collectionWkt, QVector<QgsAbstractGeometry *>() << new QgsPoint, QStringLiteral( "Point" ) );
76 }
77 
79 {
82 }
83 
84 QDomElement QgsMultiPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
85 {
86  QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
87 
88  if ( isEmpty() )
89  return elemMultiPoint;
90 
91  for ( const QgsAbstractGeometry *geom : mGeometries )
92  {
93  if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
94  {
95  QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
96  elemPointMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
97  elemMultiPoint.appendChild( elemPointMember );
98  }
99  }
100 
101  return elemMultiPoint;
102 }
103 
104 QDomElement QgsMultiPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
105 {
106  QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
107 
108  if ( isEmpty() )
109  return elemMultiPoint;
110 
111  for ( const QgsAbstractGeometry *geom : mGeometries )
112  {
113  if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
114  {
115  QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
116  elemPointMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
117  elemMultiPoint.appendChild( elemPointMember );
118  }
119  }
120 
121  return elemMultiPoint;
122 }
123 
125 {
126  json j
127  {
128  { "type", "MultiPoint" },
129  { "coordinates", json::array() },
130  };
131  for ( const QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
132  {
133  const QgsPoint *point = static_cast<const QgsPoint *>( geom );
134  if ( point->is3D() )
135  j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ), qgsRound( point->z(), precision ) } );
136  else
137  j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ) } );
138  }
139  return j;
140 }
141 
142 
144 {
145  return mGeometries.size();
146 }
147 
149 {
150  if ( !qgsgeometry_cast<QgsPoint *>( g ) )
151  {
152  delete g;
153  return false;
154  }
155  if ( mGeometries.empty() )
156  {
158  }
159  if ( is3D() && !g->is3D() )
160  g->addZValue();
161  else if ( !is3D() && g->is3D() )
162  g->dropZValue();
163  if ( isMeasure() && !g->isMeasure() )
164  g->addMValue();
165  else if ( !isMeasure() && g->isMeasure() )
166  g->dropMValue();
167 
169 }
170 
172 {
173  if ( !g || QgsWkbTypes::flatType( g->wkbType() ) != QgsWkbTypes::Point )
174  {
175  delete g;
176  return false;
177  }
178 
179  return QgsGeometryCollection::insertGeometry( g, index );
180 }
181 
183 {
184  return nullptr;
185 }
186 
188 {
189  if ( id.part < 0 || id.part >= mGeometries.count() || id.vertex != 0 || id.ring != 0 )
190  return -1;
191 
192  return id.part; // can shortcut the calculation, since each part will have 1 vertex
193 }
194 
196 {
197  return 0.0;
198 }
199 
200 bool QgsMultiPoint::isValid( QString &, int ) const
201 {
202  return true;
203 }
204 
205 void QgsMultiPoint::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
206 {
207  mGeometries.erase( std::remove_if( mGeometries.begin(), mGeometries.end(), // clazy:exclude=detaching-member
208  [&filter]( const QgsAbstractGeometry * part )
209  {
210  if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( part ) )
211  {
212  if ( !filter( *point ) )
213  {
214  delete point;
215  return true;
216  }
217  else
218  {
219  return false;
220  }
221  }
222  else
223  {
224  delete part;
225  return true;
226  }
227  } ), mGeometries.end() ); // clazy:exclude=detaching-member
228 }
229 
231 {
232  return true;
233 }
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
int precision
double y
Definition: qgspoint.h:42
QgsMultiPoint * clone() const override
Clones the geometry by performing a deep copy.
void clear() override
Clears the geometry, ie reset it to a null geometry.
QgsPoint * pointN(int index)
Returns the point with the specified index.
bool insertGeometry(QgsAbstractGeometry *g, int index) override
Inserts a geometry before a specified index and takes ownership.
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...
Multi point geometry collection.
Definition: qgsmultipoint.h:29
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
static Type flatType(Type type) SIP_HOLDGIL
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:702
virtual bool addMValue(double mValue=0)=0
Adds a measure to the geometry, initialized to a preset value.
QgsWkbTypes::Type mWkbType
virtual bool insertGeometry(QgsAbstractGeometry *g, int index)
Inserts a geometry before a specified index and takes ownership.
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.
Utility class for identifying a unique vertex within a geometry.
QgsMultiPoint() SIP_HOLDGIL
Constructor for an empty multipoint geometry.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
T qgsgeometry_cast(const QgsAbstractGeometry *geom)
bool isValid(QString &error, int flags=0) const override SIP_HOLDGIL
Checks validity of the geometry, and returns true if the geometry is valid.
bool isEmpty() const override SIP_HOLDGIL
Returns true if the geometry is empty.
Abstract base class for all geometries.
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:37
bool fromCollectionWkt(const QString &wkt, const QVector< QgsAbstractGeometry *> &subtypes, const QString &defaultChildWkbType=QString())
Reads a collection from a WKT string.
AxisOrder
Axis order for GML generation.
QgsMultiPoint * toCurveType() const override
Returns the geometry converted to the more generic curve type.
bool addGeometry(QgsAbstractGeometry *g) override
Adds a geometry and takes ownership. Returns true in case of success.
QVector< QgsAbstractGeometry *> mGeometries
bool isMeasure() const SIP_HOLDGIL
Returns true if the geometry contains m values.
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places...
Definition: qgis.h:364
bool is3D() const SIP_HOLDGIL
Returns true if the geometry is 3D and contains a z-value.
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
int nCoordinates() const override SIP_HOLDGIL
Returns the number of nodes contained in the geometry.
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns the WKB type of the geometry.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
bool wktOmitChildType() const override
Returns whether child type names are omitted from Wkt representations of the collection.
double z
Definition: qgspoint.h:43
QgsMultiPoint * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership...
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
virtual bool dropMValue()=0
Drops any measure values which exist in the geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
virtual bool dropZValue()=0
Drops any z-dimensions which exist in the geometry.
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.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
void clear() override
Clears the geometry, ie reset it to a null geometry.
double x
Definition: qgspoint.h:41