Skip to content

Commit 6e84756

Browse files
committedJan 6, 2019
[API] Backport some nice PyQGIS methods and exceptions to QgsLineString
- len(QgsCurve) returns number of points in curve - raise IndexErrors when calling pointN, xAt, yAt, zAt, mAt, setXAt, setYAt, setMAt, setZAt with invalid vertex indices - Add [] getter for retrieving specific vertices, eg. ls[0] returns QgsPoint(...) - Add [] setter for setting specific (existing) vertices, e.g. ls[1] = QgsPoint(1,2) - Add del support for removing vertices, e.g. del ls[1] removes the second vertex (cherry picked from commit 1e54799)
1 parent cf41040 commit 6e84756

File tree

6 files changed

+511
-3
lines changed

6 files changed

+511
-3
lines changed
 

‎python/core/auto_generated/geometry/qgscurve.sip.in

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,20 @@ Returns a list of points within the curve.
101101
Returns the number of points in the curve.
102102
%End
103103

104+
int __len__() const;
105+
%Docstring
106+
Returns the number of points in the curve.
107+
%End
108+
%MethodCode
109+
sipRes = sipCpp->numPoints();
110+
%End
111+
112+
//! Ensures that bool(obj) returns true (otherwise __len__() would be used)
113+
int __bool__() const;
114+
%MethodCode
115+
sipRes = true;
116+
%End
117+
104118
virtual void sumUpArea( double &sum /Out/ ) const = 0;
105119
%Docstring
106120
Sums up the area of the curve by iterating over the vertices (shoelace formula).

‎python/core/auto_generated/geometry/qgslinestring.sip.in

Lines changed: 161 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,52 @@ Construct a linestring from a single 2d line segment.
8181
virtual bool equals( const QgsCurve &other ) const;
8282

8383

84-
QgsPoint pointN( int i ) const;
84+
SIP_PYOBJECT pointN( int i ) const;
8585
%Docstring
8686
Returns the specified point from inside the line string.
8787

8888
:param i: index of point, starting at 0 for the first point
89+
%End
90+
%MethodCode
91+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
92+
{
93+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
94+
sipIsErr = 1;
95+
}
96+
else
97+
{
98+
std::unique_ptr< QgsPoint > p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
99+
sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
100+
}
89101
%End
90102

91103
virtual double xAt( int index ) const;
92104

105+
%MethodCode
106+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
107+
{
108+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
109+
sipIsErr = 1;
110+
}
111+
else
112+
{
113+
return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
114+
}
115+
%End
116+
93117
virtual double yAt( int index ) const;
94118

119+
%MethodCode
120+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
121+
{
122+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
123+
sipIsErr = 1;
124+
}
125+
else
126+
{
127+
return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
128+
}
129+
%End
95130

96131

97132

@@ -107,6 +142,17 @@ Returns the z-coordinate of the specified node in the line string.
107142
does not have a z dimension
108143

109144
.. seealso:: :py:func:`setZAt`
145+
%End
146+
%MethodCode
147+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
148+
{
149+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
150+
sipIsErr = 1;
151+
}
152+
else
153+
{
154+
return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
155+
}
110156
%End
111157

112158
double mAt( int index ) const;
@@ -119,6 +165,17 @@ Returns the m value of the specified node in the line string.
119165
does not have m values
120166

121167
.. seealso:: :py:func:`setMAt`
168+
%End
169+
%MethodCode
170+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
171+
{
172+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
173+
sipIsErr = 1;
174+
}
175+
else
176+
{
177+
return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
178+
}
122179
%End
123180

124181
void setXAt( int index, double x );
@@ -130,6 +187,17 @@ Sets the x-coordinate of the specified node in the line string.
130187
:param x: x-coordinate of node
131188

132189
.. seealso:: :py:func:`xAt`
190+
%End
191+
%MethodCode
192+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
193+
{
194+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
195+
sipIsErr = 1;
196+
}
197+
else
198+
{
199+
sipCpp->setXAt( a0, a1 );
200+
}
133201
%End
134202

135203
void setYAt( int index, double y );
@@ -141,6 +209,17 @@ Sets the y-coordinate of the specified node in the line string.
141209
:param y: y-coordinate of node
142210

143211
.. seealso:: :py:func:`yAt`
212+
%End
213+
%MethodCode
214+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
215+
{
216+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
217+
sipIsErr = 1;
218+
}
219+
else
220+
{
221+
sipCpp->setYAt( a0, a1 );
222+
}
144223
%End
145224

146225
void setZAt( int index, double z );
@@ -152,6 +231,17 @@ Sets the z-coordinate of the specified node in the line string.
152231
:param z: z-coordinate of node
153232

154233
.. seealso:: :py:func:`zAt`
234+
%End
235+
%MethodCode
236+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
237+
{
238+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
239+
sipIsErr = 1;
240+
}
241+
else
242+
{
243+
sipCpp->setZAt( a0, a1 );
244+
}
155245
%End
156246

157247
void setMAt( int index, double m );
@@ -163,6 +253,17 @@ Sets the m value of the specified node in the line string.
163253
:param m: m value of node
164254

165255
.. seealso:: :py:func:`mAt`
256+
%End
257+
%MethodCode
258+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
259+
{
260+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
261+
sipIsErr = 1;
262+
}
263+
else
264+
{
265+
sipCpp->setMAt( a0, a1 );
266+
}
166267
%End
167268

168269
void setPoints( const QgsPointSequence &points );
@@ -336,6 +437,65 @@ of the curve.
336437
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
337438
%End
338439

440+
SIP_PYOBJECT __getitem__( int index );
441+
%Docstring
442+
Returns the point at the specified ``index``. An IndexError will be raised if no point with the specified ``index`` exists.
443+
444+
.. versionadded:: 3.6
445+
%End
446+
%MethodCode
447+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
448+
{
449+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
450+
sipIsErr = 1;
451+
}
452+
else
453+
{
454+
std::unique_ptr< QgsPoint > p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
455+
sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
456+
}
457+
%End
458+
459+
void __setitem__( int index, const QgsPoint &point );
460+
%Docstring
461+
Sets the point at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.
462+
463+
.. versionadded:: 3.6
464+
%End
465+
%MethodCode
466+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
467+
{
468+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
469+
sipIsErr = 1;
470+
}
471+
else
472+
{
473+
sipCpp->setXAt( a0, a1->x() );
474+
sipCpp->setYAt( a0, a1->y() );
475+
if ( sipCpp->isMeasure() )
476+
sipCpp->setMAt( a0, a1->m() );
477+
if ( sipCpp->is3D() )
478+
sipCpp->setZAt( a0, a1->z() );
479+
}
480+
%End
481+
482+
void __delitem__( int index );
483+
%Docstring
484+
Deletes the vertex at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.
485+
486+
.. versionadded:: 3.6
487+
%End
488+
%MethodCode
489+
if ( a0 >= 0 && a0 < sipCpp->numPoints() )
490+
sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
491+
else
492+
{
493+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
494+
sipIsErr = 1;
495+
}
496+
%End
497+
498+
339499
protected:
340500

341501
virtual QgsRectangle calculateBoundingBox() const;

‎scripts/sipify.pl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -520,14 +520,14 @@ sub detect_non_method_member{
520520
}
521521

522522
# do not process SIP code %XXXCode
523-
if ( $SIP_RUN == 1 && $LINE =~ m/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/ ){
523+
if ( $SIP_RUN == 1 && $LINE =~ m/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode|Docstring)(.*)?$/ ){
524524
$LINE = "%$1$2";
525525
$COMMENT = '';
526526
dbg_info("do not process SIP code");
527527
while ( $LINE !~ m/^ *% *End/ ){
528528
write_output("COD", $LINE."\n");
529529
$LINE = read_line();
530-
$LINE =~ s/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/%$1$2/;
530+
$LINE =~ s/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode|Docstring)(.*)?$/%$1$2/;
531531
$LINE =~ s/^\s*SIP_END(.*)$/%End$1/;
532532
}
533533
$LINE =~ s/^\s*% End/%End/;

‎src/core/geometry/qgscurve.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,22 @@ class CORE_EXPORT QgsCurve: public QgsAbstractGeometry
106106
*/
107107
virtual int numPoints() const = 0;
108108

109+
#ifdef SIP_RUN
110+
int __len__() const;
111+
% Docstring
112+
Returns the number of points in the curve.
113+
% End
114+
% MethodCode
115+
sipRes = sipCpp->numPoints();
116+
% End
117+
118+
//! Ensures that bool(obj) returns true (otherwise __len__() would be used)
119+
int __bool__() const;
120+
% MethodCode
121+
sipRes = true;
122+
% End
123+
#endif
124+
109125
/**
110126
* Sums up the area of the curve by iterating over the vertices (shoelace formula).
111127
*/

‎src/core/geometry/qgslinestring.h

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,53 @@ class CORE_EXPORT QgsLineString: public QgsCurve
9898
* Returns the specified point from inside the line string.
9999
* \param i index of point, starting at 0 for the first point
100100
*/
101+
#ifndef SIP_RUN
101102
QgsPoint pointN( int i ) const;
103+
#else
104+
SIP_PYOBJECT pointN( int i ) const;
105+
% MethodCode
106+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
107+
{
108+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
109+
sipIsErr = 1;
110+
}
111+
else
112+
{
113+
std::unique_ptr< QgsPoint > p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
114+
sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
115+
}
116+
% End
117+
#endif
102118

103119
double xAt( int index ) const override;
120+
#ifdef SIP_RUN
121+
% MethodCode
122+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
123+
{
124+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
125+
sipIsErr = 1;
126+
}
127+
else
128+
{
129+
return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
130+
}
131+
% End
132+
#endif
133+
104134
double yAt( int index ) const override;
135+
#ifdef SIP_RUN
136+
% MethodCode
137+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
138+
{
139+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
140+
sipIsErr = 1;
141+
}
142+
else
143+
{
144+
return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
145+
}
146+
% End
147+
#endif
105148

106149
/**
107150
* Returns a const pointer to the x vertex data.
@@ -171,6 +214,19 @@ class CORE_EXPORT QgsLineString: public QgsCurve
171214
else
172215
return std::numeric_limits<double>::quiet_NaN();
173216
}
217+
#ifdef SIP_RUN
218+
% MethodCode
219+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
220+
{
221+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
222+
sipIsErr = 1;
223+
}
224+
else
225+
{
226+
return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
227+
}
228+
% End
229+
#endif
174230

175231
/**
176232
* Returns the m value of the specified node in the line string.
@@ -186,6 +242,19 @@ class CORE_EXPORT QgsLineString: public QgsCurve
186242
else
187243
return std::numeric_limits<double>::quiet_NaN();
188244
}
245+
#ifdef SIP_RUN
246+
% MethodCode
247+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
248+
{
249+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
250+
sipIsErr = 1;
251+
}
252+
else
253+
{
254+
return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
255+
}
256+
% End
257+
#endif
189258

190259
/**
191260
* Sets the x-coordinate of the specified node in the line string.
@@ -195,6 +264,19 @@ class CORE_EXPORT QgsLineString: public QgsCurve
195264
* \see xAt()
196265
*/
197266
void setXAt( int index, double x );
267+
#ifdef SIP_RUN
268+
% MethodCode
269+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
270+
{
271+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
272+
sipIsErr = 1;
273+
}
274+
else
275+
{
276+
sipCpp->setXAt( a0, a1 );
277+
}
278+
% End
279+
#endif
198280

199281
/**
200282
* Sets the y-coordinate of the specified node in the line string.
@@ -204,6 +286,19 @@ class CORE_EXPORT QgsLineString: public QgsCurve
204286
* \see yAt()
205287
*/
206288
void setYAt( int index, double y );
289+
#ifdef SIP_RUN
290+
% MethodCode
291+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
292+
{
293+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
294+
sipIsErr = 1;
295+
}
296+
else
297+
{
298+
sipCpp->setYAt( a0, a1 );
299+
}
300+
% End
301+
#endif
207302

208303
/**
209304
* Sets the z-coordinate of the specified node in the line string.
@@ -217,6 +312,19 @@ class CORE_EXPORT QgsLineString: public QgsCurve
217312
if ( index >= 0 && index < mZ.size() )
218313
mZ[ index ] = z;
219314
}
315+
#ifdef SIP_RUN
316+
% MethodCode
317+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
318+
{
319+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
320+
sipIsErr = 1;
321+
}
322+
else
323+
{
324+
sipCpp->setZAt( a0, a1 );
325+
}
326+
% End
327+
#endif
220328

221329
/**
222330
* Sets the m value of the specified node in the line string.
@@ -230,6 +338,19 @@ class CORE_EXPORT QgsLineString: public QgsCurve
230338
if ( index >= 0 && index < mM.size() )
231339
mM[ index ] = m;
232340
}
341+
#ifdef SIP_RUN
342+
% MethodCode
343+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
344+
{
345+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
346+
sipIsErr = 1;
347+
}
348+
else
349+
{
350+
sipCpp->setMAt( a0, a1 );
351+
}
352+
% End
353+
#endif
233354

234355
/**
235356
* Resets the line string to match the specified list of points. The line string will
@@ -365,6 +486,65 @@ class CORE_EXPORT QgsLineString: public QgsCurve
365486
QString str = QStringLiteral( "<QgsLineString: %1>" ).arg( wkt );
366487
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
367488
% End
489+
490+
SIP_PYOBJECT __getitem__( int index );
491+
% Docstring
492+
Returns the point at the specified ``index``. An IndexError will be raised if no point with the specified ``index`` exists.
493+
494+
.. versionadded:: 3.6
495+
% End
496+
% MethodCode
497+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
498+
{
499+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
500+
sipIsErr = 1;
501+
}
502+
else
503+
{
504+
std::unique_ptr< QgsPoint > p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
505+
sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
506+
}
507+
% End
508+
509+
void __setitem__( int index, const QgsPoint &point );
510+
% Docstring
511+
Sets the point at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.
512+
513+
.. versionadded:: 3.6
514+
% End
515+
% MethodCode
516+
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
517+
{
518+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
519+
sipIsErr = 1;
520+
}
521+
else
522+
{
523+
sipCpp->setXAt( a0, a1->x() );
524+
sipCpp->setYAt( a0, a1->y() );
525+
if ( sipCpp->isMeasure() )
526+
sipCpp->setMAt( a0, a1->m() );
527+
if ( sipCpp->is3D() )
528+
sipCpp->setZAt( a0, a1->z() );
529+
}
530+
% End
531+
532+
void __delitem__( int index );
533+
% Docstring
534+
Deletes the vertex at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.
535+
536+
.. versionadded:: 3.6
537+
% End
538+
% MethodCode
539+
if ( a0 >= 0 && a0 < sipCpp->numPoints() )
540+
sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
541+
else
542+
{
543+
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
544+
sipIsErr = 1;
545+
}
546+
% End
547+
368548
#endif
369549

370550
protected:

‎tests/src/python/test_qgsgeometry.py

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,144 @@ def testPointXY(self):
310310
with self.assertRaises(ValueError):
311311
QgsGeometry().asPolygon()
312312

313+
def testLineStringPythonAdditions(self):
314+
"""
315+
Tests Python specific additions to the QgsLineString API
316+
"""
317+
ls = QgsLineString()
318+
self.assertTrue(bool(ls))
319+
self.assertEqual(len(ls), 0)
320+
ls = QgsLineString([QgsPoint(1, 2), QgsPoint(11, 12)])
321+
self.assertTrue(bool(ls))
322+
self.assertEqual(len(ls), 2)
323+
324+
# pointN
325+
with self.assertRaises(IndexError):
326+
ls.pointN(-1)
327+
with self.assertRaises(IndexError):
328+
ls.pointN(2)
329+
self.assertEqual(ls.pointN(0), QgsPoint(1, 2))
330+
self.assertEqual(ls.pointN(1), QgsPoint(11, 12))
331+
332+
# xAt
333+
with self.assertRaises(IndexError):
334+
ls.xAt(-1)
335+
with self.assertRaises(IndexError):
336+
ls.xAt(2)
337+
self.assertEqual(ls.xAt(0), 1)
338+
self.assertEqual(ls.xAt(1), 11)
339+
340+
# yAt
341+
with self.assertRaises(IndexError):
342+
ls.yAt(-1)
343+
with self.assertRaises(IndexError):
344+
ls.yAt(2)
345+
self.assertEqual(ls.yAt(0), 2)
346+
self.assertEqual(ls.yAt(1), 12)
347+
348+
# zAt
349+
with self.assertRaises(IndexError):
350+
ls.zAt(-1)
351+
with self.assertRaises(IndexError):
352+
ls.zAt(2)
353+
354+
# mAt
355+
with self.assertRaises(IndexError):
356+
ls.mAt(-1)
357+
with self.assertRaises(IndexError):
358+
ls.mAt(2)
359+
360+
ls = QgsLineString([QgsPoint(1, 2, 3, 4), QgsPoint(11, 12, 13, 14)])
361+
self.assertEqual(ls.zAt(0), 3)
362+
self.assertEqual(ls.zAt(1), 13)
363+
self.assertEqual(ls.mAt(0), 4)
364+
self.assertEqual(ls.mAt(1), 14)
365+
366+
# setXAt
367+
with self.assertRaises(IndexError):
368+
ls.setXAt(-1, 55)
369+
with self.assertRaises(IndexError):
370+
ls.setXAt(2, 55)
371+
ls.setXAt(0, 5)
372+
ls.setXAt(1, 15)
373+
self.assertEqual(ls.xAt(0), 5)
374+
self.assertEqual(ls.xAt(1), 15)
375+
376+
# setYAt
377+
with self.assertRaises(IndexError):
378+
ls.setYAt(-1, 66)
379+
with self.assertRaises(IndexError):
380+
ls.setYAt(2, 66)
381+
ls.setYAt(0, 6)
382+
ls.setYAt(1, 16)
383+
self.assertEqual(ls.yAt(0), 6)
384+
self.assertEqual(ls.yAt(1), 16)
385+
386+
# setZAt
387+
with self.assertRaises(IndexError):
388+
ls.setZAt(-1, 77)
389+
with self.assertRaises(IndexError):
390+
ls.setZAt(2, 77)
391+
ls.setZAt(0, 7)
392+
ls.setZAt(1, 17)
393+
self.assertEqual(ls.zAt(0), 7)
394+
self.assertEqual(ls.zAt(1), 17)
395+
396+
# setMAt
397+
with self.assertRaises(IndexError):
398+
ls.setMAt(-1, 88)
399+
with self.assertRaises(IndexError):
400+
ls.setMAt(2, 88)
401+
ls.setMAt(0, 8)
402+
ls.setMAt(1, 18)
403+
self.assertEqual(ls.mAt(0), 8)
404+
self.assertEqual(ls.mAt(1), 18)
405+
406+
# get item
407+
with self.assertRaises(IndexError):
408+
ls[-1]
409+
with self.assertRaises(IndexError):
410+
ls[2]
411+
self.assertEqual(ls[0], QgsPoint(5, 6, 7, 8))
412+
self.assertEqual(ls[1], QgsPoint(15, 16, 17, 18))
413+
414+
# set item
415+
with self.assertRaises(IndexError):
416+
ls[-1] = QgsPoint(33, 34)
417+
with self.assertRaises(IndexError):
418+
ls[2] = QgsPoint(33, 34)
419+
ls[0] = QgsPoint(33, 34, 35, 36)
420+
ls[1] = QgsPoint(43, 44, 45, 46)
421+
self.assertEqual(ls[0], QgsPoint(33, 34, 35, 36))
422+
self.assertEqual(ls[1], QgsPoint(43, 44, 45, 46))
423+
424+
# set item, z/m handling
425+
ls[0] = QgsPoint(66, 67)
426+
self.assertEqual(ls[0], QgsPoint(66, 67, None, None, QgsWkbTypes.PointZM))
427+
ls[0] = QgsPoint(77, 78, 79)
428+
self.assertEqual(ls[0], QgsPoint(77, 78, 79, None, QgsWkbTypes.PointZM))
429+
ls[0] = QgsPoint(77, 78, None, 80, QgsWkbTypes.PointZM)
430+
self.assertEqual(ls[0], QgsPoint(77, 78, None, 80, QgsWkbTypes.PointZM))
431+
432+
ls = QgsLineString([QgsPoint(1, 2), QgsPoint(11, 12)])
433+
ls[0] = QgsPoint(66, 67)
434+
self.assertEqual(ls[0], QgsPoint(66, 67))
435+
ls[0] = QgsPoint(86, 87, 89, 90)
436+
self.assertEqual(ls[0], QgsPoint(86, 87))
437+
438+
# del item
439+
ls = QgsLineString([QgsPoint(1, 2), QgsPoint(11, 12), QgsPoint(33, 34)])
440+
with self.assertRaises(IndexError):
441+
del ls[-1]
442+
with self.assertRaises(IndexError):
443+
del ls[3]
444+
del ls[1]
445+
self.assertEqual(len(ls), 2)
446+
self.assertEqual(ls[0], QgsPoint(1, 2))
447+
self.assertEqual(ls[1], QgsPoint(33, 34))
448+
with self.assertRaises(IndexError):
449+
del ls[2]
450+
313451
def testReferenceGeometry(self):
314452
""" Test parsing a whole range of valid reference wkt formats and variants, and checking
315453
expected values such as length, area, centroids, bounding boxes, etc of the resultant geometry.

0 commit comments

Comments
 (0)
Please sign in to comment.