Skip to content
Permalink
Browse files

[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)
  • Loading branch information
nyalldawson committed Nov 26, 2018
1 parent cf41040 commit 6e847565ec1b6d2756f06cf83fe4dd1aeaa5d16d
@@ -101,6 +101,20 @@ Returns a list of points within the curve.
Returns the number of points in the curve.
%End

int __len__() const;
%Docstring
Returns the number of points in the curve.
%End
%MethodCode
sipRes = sipCpp->numPoints();
%End

//! Ensures that bool(obj) returns true (otherwise __len__() would be used)
int __bool__() const;
%MethodCode
sipRes = true;
%End

virtual void sumUpArea( double &sum /Out/ ) const = 0;
%Docstring
Sums up the area of the curve by iterating over the vertices (shoelace formula).
@@ -81,17 +81,52 @@ Construct a linestring from a single 2d line segment.
virtual bool equals( const QgsCurve &other ) const;


QgsPoint pointN( int i ) const;
SIP_PYOBJECT pointN( int i ) const;
%Docstring
Returns the specified point from inside the line string.

:param i: index of point, starting at 0 for the first point
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
std::unique_ptr< QgsPoint > p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
}
%End

virtual double xAt( int index ) const;

%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyFloat_FromDouble( sipCpp->xAt( a0 ) );
}
%End

virtual double yAt( int index ) const;

%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyFloat_FromDouble( sipCpp->yAt( a0 ) );
}
%End



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

.. seealso:: :py:func:`setZAt`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyFloat_FromDouble( sipCpp->zAt( a0 ) );
}
%End

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

.. seealso:: :py:func:`setMAt`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
return PyFloat_FromDouble( sipCpp->mAt( a0 ) );
}
%End

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

.. seealso:: :py:func:`xAt`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setXAt( a0, a1 );
}
%End

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

.. seealso:: :py:func:`yAt`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setYAt( a0, a1 );
}
%End

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

.. seealso:: :py:func:`zAt`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setZAt( a0, a1 );
}
%End

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

.. seealso:: :py:func:`mAt`
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setMAt( a0, a1 );
}
%End

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

SIP_PYOBJECT __getitem__( int index );
%Docstring
Returns the point at the specified ``index``. An IndexError will be raised if no point with the specified ``index`` exists.

.. versionadded:: 3.6
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
std::unique_ptr< QgsPoint > p = qgis::make_unique< QgsPoint >( sipCpp->pointN( a0 ) );
sipRes = sipConvertFromType( p.release(), sipType_QgsPoint, Py_None );
}
%End

void __setitem__( int index, const QgsPoint &point );
%Docstring
Sets the point at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.

.. versionadded:: 3.6
%End
%MethodCode
if ( a0 < 0 || a0 >= sipCpp->numPoints() )
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
else
{
sipCpp->setXAt( a0, a1->x() );
sipCpp->setYAt( a0, a1->y() );
if ( sipCpp->isMeasure() )
sipCpp->setMAt( a0, a1->m() );
if ( sipCpp->is3D() )
sipCpp->setZAt( a0, a1->z() );
}
%End

void __delitem__( int index );
%Docstring
Deletes the vertex at the specified ``index``. A point at the ``index`` must already exist or an IndexError will be raised.

.. versionadded:: 3.6
%End
%MethodCode
if ( a0 >= 0 && a0 < sipCpp->numPoints() )
sipCpp->deleteVertex( QgsVertexId( -1, -1, a0 ) );
else
{
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
sipIsErr = 1;
}
%End


protected:

virtual QgsRectangle calculateBoundingBox() const;
@@ -520,14 +520,14 @@ sub detect_non_method_member{
}

# do not process SIP code %XXXCode
if ( $SIP_RUN == 1 && $LINE =~ m/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/ ){
if ( $SIP_RUN == 1 && $LINE =~ m/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode|Docstring)(.*)?$/ ){
$LINE = "%$1$2";
$COMMENT = '';
dbg_info("do not process SIP code");
while ( $LINE !~ m/^ *% *End/ ){
write_output("COD", $LINE."\n");
$LINE = read_line();
$LINE =~ s/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode)(.*)?$/%$1$2/;
$LINE =~ s/^ *% *(VirtualErrorHandler|MappedType|Type(?:Header)?Code|Module(?:Header)?Code|Convert(?:From|To)(?:Type|SubClass)Code|MethodCode|Docstring)(.*)?$/%$1$2/;
$LINE =~ s/^\s*SIP_END(.*)$/%End$1/;
}
$LINE =~ s/^\s*% End/%End/;
@@ -106,6 +106,22 @@ class CORE_EXPORT QgsCurve: public QgsAbstractGeometry
*/
virtual int numPoints() const = 0;

#ifdef SIP_RUN
int __len__() const;
% Docstring
Returns the number of points in the curve.
% End
% MethodCode
sipRes = sipCpp->numPoints();
% End

//! Ensures that bool(obj) returns true (otherwise __len__() would be used)
int __bool__() const;
% MethodCode
sipRes = true;
% End
#endif

/**
* Sums up the area of the curve by iterating over the vertices (shoelace formula).
*/

0 comments on commit 6e84756

Please sign in to comment.
You can’t perform that action at this time.