QGIS API Documentation 4.0.0-Norrköping (1ddcee3d0e4)
Loading...
Searching...
No Matches
qgsmultipoint.h
Go to the documentation of this file.
1/***************************************************************************
2 qgsmultipoint.h
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#ifndef QGSMULTIPOINT_H
17#define QGSMULTIPOINT_H
18
19#include "qgis_core.h"
20#include "qgis_sip.h"
22
23#include <QString>
24
25using namespace Qt::StringLiterals;
26
32class CORE_EXPORT QgsMultiPoint : public QgsGeometryCollection
33{
34 public:
35 // clang-format off
40 // clang-format on
41
42#ifndef SIP_RUN
43
51 QgsMultiPoint( const QVector<QgsPoint> &points );
52
62 QgsMultiPoint( const QVector<QgsPoint *> &points );
63
70 QgsMultiPoint( const QVector<QgsPointXY> &points );
71#else
72// clang-format off
73
81 QgsMultiPoint( SIP_PYOBJECT points SIP_TYPEHINT( Sequence[Union[QgsPoint, QgsPointXY, Sequence[float]]] ) ) SIP_HOLDGIL [( const QVector<QgsPoint> &points )];
82 % MethodCode
83 if ( !PySequence_Check( a0 ) )
84 {
85 PyErr_SetString( PyExc_TypeError, u"A sequence of QgsPoint, QgsPointXY or array of floats is expected"_s.toUtf8().constData() );
86 sipIsErr = 1;
87 }
88 else
89 {
90 int state;
91 const int size = PySequence_Size( a0 );
92 QVector< QgsPoint * > pointList;
93 pointList.reserve( size );
94
95 sipIsErr = 0;
96 for ( int i = 0; i < size; ++i )
97 {
98 PyObject *value = PySequence_GetItem( a0, i );
99 if ( !value )
100 {
101 qDeleteAll( pointList );
102 pointList.clear();
103 PyErr_SetString( PyExc_TypeError, u"Invalid type at index %1."_s.arg( i ) .toUtf8().constData() );
104 sipIsErr = 1;
105 break;
106 }
107
108 if ( PySequence_Check( value ) )
109 {
110 const int elementSize = PySequence_Size( value );
111 if ( elementSize < 2 || elementSize > 4 )
112 {
113 qDeleteAll( pointList );
114 pointList.clear();
115 sipIsErr = 1;
116 PyErr_SetString( PyExc_TypeError, u"Invalid sequence size at index %1. Expected an array of 2-4 float values, got %2."_s.arg( i ).arg( elementSize ).toUtf8().constData() );
117 Py_DECREF( value );
118 break;
119 }
120 else
121 {
122 sipIsErr = 0;
123
124 PyObject *element = PySequence_GetItem( value, 0 );
125 if ( !element )
126 {
127 qDeleteAll( pointList );
128 pointList.clear();
129 PyErr_SetString( PyExc_TypeError, u"Invalid type at index %1."_s.arg( i ) .toUtf8().constData() );
130 sipIsErr = 1;
131 break;
132 }
133
134 PyErr_Clear();
135 const double x = PyFloat_AsDouble( element );
136 Py_DECREF( element );
137 if ( PyErr_Occurred() )
138 {
139 qDeleteAll( pointList );
140 pointList.clear();
141 Py_DECREF( value );
142 sipIsErr = 1;
143 break;
144 }
145
146 element = PySequence_GetItem( value, 1 );
147 if ( !element )
148 {
149 qDeleteAll( pointList );
150 pointList.clear();
151 Py_DECREF( value );
152 PyErr_SetString( PyExc_TypeError, u"Invalid type at index %1."_s.arg( i ) .toUtf8().constData() );
153 sipIsErr = 1;
154 break;
155 }
156
157 PyErr_Clear();
158 const double y = PyFloat_AsDouble( element );
159 Py_DECREF( element );
160 if ( PyErr_Occurred() )
161 {
162 qDeleteAll( pointList );
163 pointList.clear();
164 Py_DECREF( value );
165 sipIsErr = 1;
166 break;
167 }
168
169 auto point = std::make_unique< QgsPoint >( x, y );
170 if ( elementSize > 2 )
171 {
172 element = PySequence_GetItem( value, 2 );
173 if ( !element )
174 {
175 qDeleteAll( pointList );
176 pointList.clear();
177 Py_DECREF( value );
178 PyErr_SetString( PyExc_TypeError, u"Invalid type at index %1."_s.arg( i ) .toUtf8().constData() );
179 sipIsErr = 1;
180 break;
181 }
182
183 PyErr_Clear();
184 const double z = PyFloat_AsDouble( element );
185 Py_DECREF( element );
186 if ( PyErr_Occurred() )
187 {
188 qDeleteAll( pointList );
189 pointList.clear();
190 Py_DECREF( value );
191 sipIsErr = 1;
192 break;
193 }
194 point->addZValue( z );
195 }
196 if ( elementSize > 3 )
197 {
198 element = PySequence_GetItem( value, 3 );
199 if ( !element )
200 {
201 qDeleteAll( pointList );
202 pointList.clear();
203 Py_DECREF( value );
204 PyErr_SetString( PyExc_TypeError, u"Invalid type at index %1."_s.arg( i ) .toUtf8().constData() );
205 sipIsErr = 1;
206 break;
207 }
208
209 PyErr_Clear();
210 const double m = PyFloat_AsDouble( element );
211 Py_DECREF( element );
212 if ( PyErr_Occurred() )
213 {
214 qDeleteAll( pointList );
215 pointList.clear();
216 Py_DECREF( value );
217 sipIsErr = 1;
218 break;
219 }
220 point->addMValue( m );
221 }
222 pointList.append( point.release() );
223
224 Py_DECREF( value );
225 if ( sipIsErr )
226 {
227 qDeleteAll( pointList );
228 pointList.clear();
229 break;
230 }
231 }
232 }
233 else
234 {
235 if ( sipCanConvertToType( value, sipType_QgsPointXY, SIP_NOT_NONE ) )
236 {
237 sipIsErr = 0;
238 QgsPointXY *p = reinterpret_cast<QgsPointXY *>( sipConvertToType( value, sipType_QgsPointXY, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
239 if ( !sipIsErr )
240 {
241 pointList.append( new QgsPoint( p->x(), p->y() ) );
242 }
243 sipReleaseType( p, sipType_QgsPointXY, state );
244 }
245 else if ( sipCanConvertToType( value, sipType_QgsPoint, SIP_NOT_NONE ) )
246 {
247 sipIsErr = 0;
248 QgsPoint *p = reinterpret_cast<QgsPoint *>( sipConvertToType( value, sipType_QgsPoint, 0, SIP_NOT_NONE, &state, &sipIsErr ) );
249 if ( !sipIsErr )
250 {
251 pointList.append( p->clone() );
252 }
253 sipReleaseType( p, sipType_QgsPoint, state );
254 }
255 else
256 {
257 sipIsErr = 1;
258 }
259
260 Py_DECREF( value );
261
262 if ( sipIsErr )
263 {
264 qDeleteAll( pointList );
265 pointList.clear();
266 // couldn't convert the sequence value to a QgsPoint or QgsPointXY
267 PyErr_SetString( PyExc_TypeError, u"Invalid type at index %1. Expected QgsPoint, QgsPointXY or array of floats."_s.arg( i ) .toUtf8().constData() );
268 break;
269 }
270 }
271 }
272 if ( sipIsErr == 0 )
273 sipCpp = new sipQgsMultiPoint( QgsMultiPoint( pointList ) );
274 }
275 % End
276// clang-format on
277#endif
278
290 QgsMultiPoint( const QVector<double> &x, const QVector<double> &y,
291 const QVector<double> &z = QVector<double>(),
292 const QVector<double> &m = QVector<double>() ) SIP_HOLDGIL;
293
294#ifndef SIP_RUN
295
301 QgsPoint *pointN( int index );
302#else
303// clang-format off
304
312 SIP_PYOBJECT pointN( int index ) SIP_TYPEHINT( QgsPoint );
313 % MethodCode
314 if ( a0 < 0 || a0 >= sipCpp->numGeometries() )
315 {
316 PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
317 sipIsErr = 1;
318 }
319 else
320 {
321 return sipConvertFromType( sipCpp->pointN( a0 ), sipType_QgsPoint, NULL );
322 }
323 % End
324// clang-format on
325#endif
326
327#ifndef SIP_RUN
328
336 const QgsPoint *pointN( int index ) const;
337#endif
338
339 QString geometryType() const override;
340 QgsMultiPoint *clone() const override SIP_FACTORY;
341 QgsMultiPoint *toCurveType() const override SIP_FACTORY;
342 bool fromWkt( const QString &wkt ) override;
343 void clear() override;
344 QDomElement asGml2( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
345 QDomElement asGml3( QDomDocument &doc, int precision = 17, const QString &ns = "gml", QgsAbstractGeometry::AxisOrder axisOrder = QgsAbstractGeometry::AxisOrder::XY ) const override;
346 json asJsonObject( int precision = 17 ) const override SIP_SKIP;
347 int nCoordinates() const override SIP_HOLDGIL;
348 bool addGeometry( QgsAbstractGeometry *g SIP_TRANSFER ) override;
349 bool addGeometries( const QVector< QgsAbstractGeometry * > &geometries SIP_TRANSFER ) final;
350 bool insertGeometry( QgsAbstractGeometry *g SIP_TRANSFER, int index ) override;
351 QgsAbstractGeometry *boundary() const override SIP_FACTORY;
352 int vertexNumberFromVertexId( QgsVertexId id ) const override;
353 double segmentLength( QgsVertexId startVertex ) const override;
354 bool isValid( QString &error SIP_OUT, Qgis::GeometryValidityFlags flags = Qgis::GeometryValidityFlags() ) const override SIP_HOLDGIL;
355 QgsMultiPoint *simplifyByDistance( double tolerance ) const override SIP_FACTORY;
356
357#ifndef SIP_RUN
358 void filterVertices( const std::function< bool( const QgsPoint & ) > &filter ) override;
359
368 inline static const QgsMultiPoint *cast( const QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
369 {
370 if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == Qgis::WkbType::MultiPoint )
371 return static_cast<const QgsMultiPoint *>( geom );
372 return nullptr;
373 }
374
383 inline static QgsMultiPoint *cast( QgsAbstractGeometry *geom ) // cppcheck-suppress duplInheritedMember
384 {
385 if ( geom && QgsWkbTypes::flatType( geom->wkbType() ) == Qgis::WkbType::MultiPoint )
386 return static_cast<QgsMultiPoint *>( geom );
387 return nullptr;
388 }
389#endif
390
392
393#ifdef SIP_RUN
394// clang-format off
395 SIP_PYOBJECT __repr__();
396 % MethodCode
397 QString wkt = sipCpp->asWkt();
398 if ( wkt.length() > 1000 )
399 wkt = wkt.left( 1000 ) + u"..."_s;
400 QString str = u"<QgsMultiPoint: %1>"_s.arg( wkt );
401 sipRes = PyUnicode_FromString( str.toUtf8().constData() );
402 % End
403// clang-format on
404#endif
405
406 protected:
407
408 bool wktOmitChildType() const override;
409
410};
411
412// clazy:excludeall=qstring-allocations
413
414#endif // QGSMULTIPOINT_H
QFlags< GeometryValidityFlag > GeometryValidityFlags
Geometry validity flags.
Definition qgis.h:2155
@ MultiPoint
MultiPoint.
Definition qgis.h:300
AxisOrder
Axis order for GML generation.
@ XY
X comes before Y (or lon before lat).
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
QgsAbstractGeometry()=default
QgsGeometryCollection * toCurveType() const override
Returns the geometry converted to the more generic curve type.
json asJsonObject(int precision=17) const override
Returns a json object representation of the geometry.
bool fromWkt(const QString &wkt) override
Sets the geometry from a WKT string.
void clear() override
Clears the geometry, ie reset it to a null geometry.
QString geometryType() const override
Returns a unique string representing the geometry type.
virtual bool insertGeometry(QgsAbstractGeometry *g, int index)
Inserts a geometry before a specified index and takes ownership.
int vertexNumberFromVertexId(QgsVertexId id) const override
Returns the vertex number corresponding to a vertex id.
QgsGeometryCollection * simplifyByDistance(double tolerance) const override
Simplifies the geometry by applying the Douglas Peucker simplification by distance algorithm.
QgsGeometryCollection()
Constructor for an empty geometry collection.
QgsAbstractGeometry * boundary() const override
Returns the closure of the combinatorial boundary of the geometry (ie the topological boundary of the...
bool isValid(QString &error, Qgis::GeometryValidityFlags flags=Qgis::GeometryValidityFlags()) const override
Checks validity of the geometry, and returns true if the geometry is valid.
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...
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.
int nCoordinates() const override
Returns the number of nodes contained in the geometry.
QgsGeometryCollection * clone() const override
Clones the geometry by performing a deep copy.
virtual bool addGeometries(const QVector< QgsAbstractGeometry * > &geometries)
Adds a list of geometries to the collection, transferring ownership to the collection.
QgsGeometryCollection * createEmptyWithSameType() const override
Creates a new geometry with the same class and same WKB type as the original and transfers ownership.
virtual bool addGeometry(QgsAbstractGeometry *g)
Adds a geometry and takes ownership. Returns true in case of success.
virtual bool wktOmitChildType() const
Returns whether child type names are omitted from Wkt representations of the collection.
double segmentLength(QgsVertexId startVertex) const override
Returns the length of the segment of the geometry which begins at startVertex.
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.
Multi point geometry collection.
static QgsMultiPoint * cast(QgsAbstractGeometry *geom)
Cast the geom to a QgsLineString.
QgsPoint * pointN(int index)
Returns the point with the specified index.
QgsMultiPoint()
Constructor for an empty multipoint geometry.
static const QgsMultiPoint * cast(const QgsAbstractGeometry *geom)
Cast the geom to a QgsLineString.
Represents a 2D point.
Definition qgspointxy.h:62
double y
Definition qgspointxy.h:66
double x
Definition qgspointxy.h:65
Point geometry type, with support for z-dimension and m-values.
Definition qgspoint.h:53
QgsPoint * clone() const override
Clones the geometry by performing a deep copy.
Definition qgspoint.cpp:138
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
#define SIP_TYPEHINT(type)
Definition qgis_sip.h:239
#define SIP_SKIP
Definition qgis_sip.h:133
#define SIP_TRANSFER
Definition qgis_sip.h:35
#define SIP_OUT
Definition qgis_sip.h:57
#define SIP_HOLDGIL
Definition qgis_sip.h:178
#define SIP_FACTORY
Definition qgis_sip.h:83
Utility class for identifying a unique vertex within a geometry.
Definition qgsvertexid.h:34