QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 QStringLiteral( "MultiPoint" );
34 }
35 
37 {
38  auto result = qgis::make_unique< QgsMultiPoint >();
39  result->mWkbType = mWkbType;
40  return result.release();
41 }
42 
44 {
45  return new QgsMultiPoint( *this );
46 }
47 
49 {
50  return clone();
51 }
52 
53 bool QgsMultiPoint::fromWkt( const QString &wkt )
54 {
55  QString collectionWkt( wkt );
56  //test for non-standard MultiPoint(x1 y1, x2 y2) format
57  QRegExp regex( "^\\s*MultiPoint\\s*[ZM]*\\s*\\(\\s*[-\\d]" );
58  regex.setCaseSensitivity( Qt::CaseInsensitive );
59  if ( regex.indexIn( collectionWkt ) >= 0 )
60  {
61  //alternate style without extra brackets, upgrade to standard
62  collectionWkt.replace( '(', QLatin1String( "((" ) ).replace( ')', QLatin1String( "))" ) ).replace( ',', QLatin1String( "),(" ) );
63  }
64 
65  return fromCollectionWkt( collectionWkt, QVector<QgsAbstractGeometry *>() << new QgsPoint, QStringLiteral( "Point" ) );
66 }
67 
69 {
72 }
73 
74 QDomElement QgsMultiPoint::asGml2( QDomDocument &doc, int precision, const QString &ns, const AxisOrder axisOrder ) const
75 {
76  QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
77 
78  if ( isEmpty() )
79  return elemMultiPoint;
80 
81  for ( const QgsAbstractGeometry *geom : mGeometries )
82  {
83  if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
84  {
85  QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
86  elemPointMember.appendChild( geom->asGml2( doc, precision, ns, axisOrder ) );
87  elemMultiPoint.appendChild( elemPointMember );
88  }
89  }
90 
91  return elemMultiPoint;
92 }
93 
94 QDomElement QgsMultiPoint::asGml3( QDomDocument &doc, int precision, const QString &ns, const QgsAbstractGeometry::AxisOrder axisOrder ) const
95 {
96  QDomElement elemMultiPoint = doc.createElementNS( ns, QStringLiteral( "MultiPoint" ) );
97 
98  if ( isEmpty() )
99  return elemMultiPoint;
100 
101  for ( const QgsAbstractGeometry *geom : mGeometries )
102  {
103  if ( qgsgeometry_cast<const QgsPoint *>( geom ) )
104  {
105  QDomElement elemPointMember = doc.createElementNS( ns, QStringLiteral( "pointMember" ) );
106  elemPointMember.appendChild( geom->asGml3( doc, precision, ns, axisOrder ) );
107  elemMultiPoint.appendChild( elemPointMember );
108  }
109  }
110 
111  return elemMultiPoint;
112 }
113 
115 {
116  json j
117  {
118  { "type", "MultiPoint" },
119  { "coordinates", json::array() },
120  };
121  for ( const QgsAbstractGeometry *geom : qgis::as_const( mGeometries ) )
122  {
123  const QgsPoint *point = static_cast<const QgsPoint *>( geom );
124  if ( point->is3D() )
125  j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ), qgsRound( point->z(), precision ) } );
126  else
127  j[ "coordinates" ].push_back( { qgsRound( point->x(), precision ), qgsRound( point->y(), precision ) } );
128  }
129  return j;
130 }
131 
132 
134 {
135  return mGeometries.size();
136 }
137 
139 {
140  if ( !qgsgeometry_cast<QgsPoint *>( g ) )
141  {
142  delete g;
143  return false;
144  }
145  if ( mGeometries.empty() )
146  {
148  }
149  if ( is3D() && !g->is3D() )
150  g->addZValue();
151  else if ( !is3D() && g->is3D() )
152  g->dropZValue();
153  if ( isMeasure() && !g->isMeasure() )
154  g->addMValue();
155  else if ( !isMeasure() && g->isMeasure() )
156  g->dropMValue();
157 
159 }
160 
162 {
163  if ( !g || QgsWkbTypes::flatType( g->wkbType() ) != QgsWkbTypes::Point )
164  {
165  delete g;
166  return false;
167  }
168 
169  return QgsGeometryCollection::insertGeometry( g, index );
170 }
171 
173 {
174  return nullptr;
175 }
176 
178 {
179  if ( id.part < 0 || id.part >= mGeometries.count() || id.vertex != 0 || id.ring != 0 )
180  return -1;
181 
182  return id.part; // can shortcut the calculation, since each part will have 1 vertex
183 }
184 
186 {
187  return 0.0;
188 }
189 
190 bool QgsMultiPoint::isValid( QString &, int ) const
191 {
192  return true;
193 }
194 
195 void QgsMultiPoint::filterVertices( const std::function<bool ( const QgsPoint & )> &filter )
196 {
197  mGeometries.erase( std::remove_if( mGeometries.begin(), mGeometries.end(), // clazy:exclude=detaching-member
198  [&filter]( const QgsAbstractGeometry * part )
199  {
200  if ( const QgsPoint *point = qgsgeometry_cast< const QgsPoint * >( part ) )
201  {
202  if ( !filter( *point ) )
203  {
204  delete point;
205  return true;
206  }
207  else
208  {
209  return false;
210  }
211  }
212  else
213  {
214  delete part;
215  return true;
216  }
217  } ), mGeometries.end() ); // clazy:exclude=detaching-member
218 }
219 
221 {
222  return true;
223 }
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
bool isMeasure() const
Returns true if the geometry contains m values.
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.
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...
bool isValid(QString &error, int flags=0) const override
Checks validity of the geometry, and returns true if the geometry is valid.
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.
bool isEmpty() const override
Returns true if the geometry is empty.
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.
void setZMTypeFromSubGeometry(const QgsAbstractGeometry *subggeom, QgsWkbTypes::Type baseGeomType)
Updates the geometry type based on whether sub geometries contain z or m values.
Abstract base class for all geometries.
QgsWkbTypes::Type wkbType() const
Returns the WKB type of the geometry.
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
double qgsRound(double number, int places)
Returns a double number, rounded (as close as possible) to the specified number of places...
Definition: qgis.h:328
virtual bool addZValue(double zValue=0)=0
Adds a z-dimension to the geometry, initialized to a preset value.
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
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.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
static Type flatType(Type type)
Returns the flat type for a WKB type.
Definition: qgswkbtypes.h:576
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
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