mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-27 00:03:38 -04:00
[API] Throw IndexError on some QgsCurvePolygon methods when invalid
interior ring index is requested
This commit is contained in:
parent
a49bf9f68f
commit
44fbb89450
python/core/auto_generated/geometry
src/core/geometry
tests/src/python
@ -70,11 +70,43 @@ Curve polygon geometry type
|
||||
virtual bool removeDuplicateNodes( double epsilon = 4 * DBL_EPSILON, bool useZValues = false );
|
||||
|
||||
|
||||
|
||||
int numInteriorRings() const;
|
||||
%Docstring
|
||||
Returns the number of interior rings contained with the curve polygon.
|
||||
|
||||
.. seealso:: :py:func:`interiorRing`
|
||||
%End
|
||||
|
||||
const QgsCurve *exteriorRing() const;
|
||||
%Docstring
|
||||
Returns the curve polygon's exterior ring.
|
||||
|
||||
const QgsCurve *interiorRing( int i ) const;
|
||||
.. seealso:: :py:func:`interiorRing`
|
||||
%End
|
||||
|
||||
|
||||
SIP_PYOBJECT interiorRing( int i ) /TypeHint="QgsCurve"/;
|
||||
%Docstring
|
||||
Retrieves an interior ring from the curve polygon. The first interior ring has index 0.
|
||||
|
||||
An IndexError will be raised if no interior ring with the specified index exists.
|
||||
|
||||
.. seealso:: :py:func:`numInteriorRings`
|
||||
|
||||
.. seealso:: :py:func:`exteriorRing`
|
||||
%End
|
||||
%MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
|
||||
{
|
||||
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return sipConvertFromType( const_cast< QgsCurve * >( sipCpp->interiorRing( a0 ) ), sipType_QgsCurve, NULL );
|
||||
}
|
||||
%End
|
||||
|
||||
virtual QgsPolygon *toPolygon( double tolerance = M_PI_2 / 90, SegmentationToleranceType toleranceType = MaximumAngle ) const /Factory/;
|
||||
%Docstring
|
||||
@ -107,13 +139,27 @@ Sets all interior rings (takes ownership)
|
||||
Adds an interior ring to the geometry (takes ownership)
|
||||
%End
|
||||
|
||||
bool removeInteriorRing( int ringIndex );
|
||||
|
||||
bool removeInteriorRing( int i );
|
||||
%Docstring
|
||||
Removes an interior ring from the polygon. The first interior ring has index 0.
|
||||
The corresponding ring is removed from the polygon and deleted. If a ring was successfully removed
|
||||
the function will return true. It is not possible to remove the exterior ring using this method.
|
||||
The corresponding ring is removed from the polygon and deleted.
|
||||
It is not possible to remove the exterior ring using this method.
|
||||
|
||||
An IndexError will be raised if no interior ring with the specified index exists.
|
||||
|
||||
.. seealso:: :py:func:`removeInteriorRings`
|
||||
%End
|
||||
%MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
|
||||
{
|
||||
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PyBool_FromLong( sipCpp->removeInteriorRing( a0 ) );
|
||||
}
|
||||
%End
|
||||
|
||||
void removeInteriorRings( double minimumAllowedArea = -1 );
|
||||
@ -136,7 +182,6 @@ For example, this removes unclosed rings and rings with less than 4 vertices.
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
|
||||
void forceRHR();
|
||||
%Docstring
|
||||
Forces the geometry to respect the Right-Hand-Rule, in which the area that is
|
||||
|
@ -58,11 +58,12 @@ Returns the number of geometries within the collection.
|
||||
|
||||
|
||||
|
||||
|
||||
SIP_PYOBJECT geometryN( int n ) /TypeHint="QgsAbstractGeometry"/;
|
||||
%Docstring
|
||||
Returns a geometry from within the collection.
|
||||
|
||||
:param n: index of geometry to return
|
||||
:param n: index of geometry to return. An IndexError will be raised if no geometry with the specified index exists.
|
||||
%End
|
||||
%MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->numGeometries() )
|
||||
@ -127,7 +128,7 @@ An IndexError will be raised if no geometry with the specified index exists.
|
||||
}
|
||||
else
|
||||
{
|
||||
sipCpp->removeGeometry( a0 );
|
||||
return PyBool_FromLong( sipCpp->removeGeometry( a0 ) );
|
||||
}
|
||||
%End
|
||||
|
||||
|
@ -66,16 +66,35 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
||||
bool removeDuplicateNodes( double epsilon = 4 * std::numeric_limits<double>::epsilon(), bool useZValues = false ) override;
|
||||
|
||||
//curve polygon interface
|
||||
|
||||
/**
|
||||
* Returns the number of interior rings contained with the curve polygon.
|
||||
*
|
||||
* \see interiorRing()
|
||||
*/
|
||||
int numInteriorRings() const
|
||||
{
|
||||
return mInteriorRings.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the curve polygon's exterior ring.
|
||||
*
|
||||
* \see interiorRing()
|
||||
*/
|
||||
const QgsCurve *exteriorRing() const
|
||||
{
|
||||
return mExteriorRing.get();
|
||||
}
|
||||
|
||||
#ifndef SIP_RUN
|
||||
|
||||
/**
|
||||
* Retrieves an interior ring from the curve polygon. The first interior ring has index 0.
|
||||
*
|
||||
* \see numInteriorRings()
|
||||
* \see exteriorRing()
|
||||
*/
|
||||
const QgsCurve *interiorRing( int i ) const
|
||||
{
|
||||
if ( i < 0 || i >= mInteriorRings.size() )
|
||||
@ -84,6 +103,29 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
||||
}
|
||||
return mInteriorRings.at( i );
|
||||
}
|
||||
#else
|
||||
|
||||
/**
|
||||
* Retrieves an interior ring from the curve polygon. The first interior ring has index 0.
|
||||
*
|
||||
* An IndexError will be raised if no interior ring with the specified index exists.
|
||||
*
|
||||
* \see numInteriorRings()
|
||||
* \see exteriorRing()
|
||||
*/
|
||||
SIP_PYOBJECT interiorRing( int i ) SIP_TYPEHINT( QgsCurve );
|
||||
% MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
|
||||
{
|
||||
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return sipConvertFromType( const_cast< QgsCurve * >( sipCpp->interiorRing( a0 ) ), sipType_QgsCurve, NULL );
|
||||
}
|
||||
% End
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns a new polygon geometry corresponding to a segmentized approximation
|
||||
@ -107,6 +149,8 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
||||
//! Adds an interior ring to the geometry (takes ownership)
|
||||
virtual void addInteriorRing( QgsCurve *ring SIP_TRANSFER );
|
||||
|
||||
#ifndef SIP_RUN
|
||||
|
||||
/**
|
||||
* Removes an interior ring from the polygon. The first interior ring has index 0.
|
||||
* The corresponding ring is removed from the polygon and deleted. If a ring was successfully removed
|
||||
@ -114,6 +158,30 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
||||
* \see removeInteriorRings()
|
||||
*/
|
||||
bool removeInteriorRing( int ringIndex );
|
||||
#else
|
||||
|
||||
/**
|
||||
* Removes an interior ring from the polygon. The first interior ring has index 0.
|
||||
* The corresponding ring is removed from the polygon and deleted.
|
||||
* It is not possible to remove the exterior ring using this method.
|
||||
*
|
||||
* An IndexError will be raised if no interior ring with the specified index exists.
|
||||
*
|
||||
* \see removeInteriorRings()
|
||||
*/
|
||||
bool removeInteriorRing( int i );
|
||||
% MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->numInteriorRings() )
|
||||
{
|
||||
PyErr_SetString( PyExc_IndexError, QByteArray::number( a0 ) );
|
||||
sipIsErr = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PyBool_FromLong( sipCpp->removeInteriorRing( a0 ) );
|
||||
}
|
||||
% End
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Removes the interior rings from the polygon. If the minimumAllowedArea
|
||||
@ -133,7 +201,6 @@ class CORE_EXPORT QgsCurvePolygon: public QgsSurface
|
||||
*/
|
||||
void removeInvalidRings();
|
||||
|
||||
|
||||
/**
|
||||
* Forces the geometry to respect the Right-Hand-Rule, in which the area that is
|
||||
* bounded by the polygon is to the right of the boundary. In particular, the exterior
|
||||
|
@ -81,13 +81,19 @@ class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
|
||||
return mGeometries.value( n );
|
||||
}
|
||||
|
||||
#ifndef SIP_RUN
|
||||
|
||||
/**
|
||||
* Returns a geometry from within the collection.
|
||||
* \param n index of geometry to return
|
||||
*/
|
||||
#ifndef SIP_RUN
|
||||
QgsAbstractGeometry *geometryN( int n );
|
||||
#else
|
||||
|
||||
/**
|
||||
* Returns a geometry from within the collection.
|
||||
* \param n index of geometry to return. An IndexError will be raised if no geometry with the specified index exists.
|
||||
*/
|
||||
SIP_PYOBJECT geometryN( int n ) SIP_TYPEHINT( QgsAbstractGeometry );
|
||||
% MethodCode
|
||||
if ( a0 < 0 || a0 >= sipCpp->numGeometries() )
|
||||
@ -151,7 +157,7 @@ class CORE_EXPORT QgsGeometryCollection: public QgsAbstractGeometry
|
||||
}
|
||||
else
|
||||
{
|
||||
sipCpp->removeGeometry( a0 );
|
||||
return PyBool_FromLong( sipCpp->removeGeometry( a0 ) );
|
||||
}
|
||||
% End
|
||||
#endif
|
||||
|
@ -504,6 +504,48 @@ class TestQgsGeometry(unittest.TestCase):
|
||||
g.fromWkt('GeometryCollection( Point(1 2), Point(11 12), LineString(33 34, 44 45))')
|
||||
self.assertEqual([p.asWkt() for p in g], ['Point (1 2)', 'Point (11 12)', 'LineString (33 34, 44 45)'])
|
||||
|
||||
def testCurvePolygonPythonAdditions(self):
|
||||
"""
|
||||
Tests Python specific additions to the QgsCurvePolygon API
|
||||
"""
|
||||
# interiorRing
|
||||
g = QgsPolygon()
|
||||
with self.assertRaises(IndexError):
|
||||
g.interiorRing(-1)
|
||||
with self.assertRaises(IndexError):
|
||||
g.interiorRing(0)
|
||||
|
||||
g.fromWkt('Polygon((0 0, 1 0, 1 1, 0 0),(0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1),(0.8 0.8, 0.9 0.8, 0.9 0.9, 0.8 0.8))')
|
||||
with self.assertRaises(IndexError):
|
||||
g.interiorRing(-1)
|
||||
with self.assertRaises(IndexError):
|
||||
g.interiorRing(2)
|
||||
self.assertEqual(g.interiorRing(0).asWkt(1), 'LineString (0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1)')
|
||||
self.assertEqual(g.interiorRing(1).asWkt(1), 'LineString (0.8 0.8, 0.9 0.8, 0.9 0.9, 0.8 0.8)')
|
||||
|
||||
# removeInteriorRing
|
||||
g = QgsPolygon()
|
||||
with self.assertRaises(IndexError):
|
||||
g.removeInteriorRing(-1)
|
||||
with self.assertRaises(IndexError):
|
||||
g.removeInteriorRing(0)
|
||||
|
||||
g.fromWkt(
|
||||
'Polygon((0 0, 1 0, 1 1, 0 0),(0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1),(0.8 0.8, 0.9 0.8, 0.9 0.9, 0.8 0.8))')
|
||||
with self.assertRaises(IndexError):
|
||||
g.removeInteriorRing(-1)
|
||||
with self.assertRaises(IndexError):
|
||||
g.removeInteriorRing(2)
|
||||
|
||||
g.removeInteriorRing(1)
|
||||
self.assertEqual(g.asWkt(1), 'Polygon ((0 0, 1 0, 1 1, 0 0),(0.1 0.1, 0.2 0.1, 0.2 0.2, 0.1 0.1))')
|
||||
with self.assertRaises(IndexError):
|
||||
g.removeInteriorRing(1)
|
||||
g.removeInteriorRing(0)
|
||||
self.assertEqual(g.asWkt(1), 'Polygon ((0 0, 1 0, 1 1, 0 0))')
|
||||
with self.assertRaises(IndexError):
|
||||
g.removeInteriorRing(0)
|
||||
|
||||
def testReferenceGeometry(self):
|
||||
""" Test parsing a whole range of valid reference wkt formats and variants, and checking
|
||||
expected values such as length, area, centroids, bounding boxes, etc of the resultant geometry.
|
||||
|
Loading…
x
Reference in New Issue
Block a user