Skip to content

Commit

Permalink
remove PyNames for QgsGeometry::compare methods
Browse files Browse the repository at this point in the history
single python method with some MethodCode to dispatch to proper cpp methods.
  • Loading branch information
3nids committed Apr 30, 2017
1 parent b0d4a4c commit a86f5ea
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 51 deletions.
146 changes: 112 additions & 34 deletions python/core/geometry/qgsgeometry.sip
Expand Up @@ -1185,45 +1185,123 @@ Ring 0 is outer ring and can't be deleted.
:rtype: QgsPolygon
%End

static bool compare( const QgsPolyline &p1, const QgsPolyline &p2,
double epsilon = 4 * DBL_EPSILON ) /PyName=comparePolylines/;
%Docstring
Compares two polylines for equality within a specified tolerance.
\param p1 first polyline
\param p2 second polyline
\param epsilon maximum difference for coordinates between the polylines
:return: true if polylines have the same number of points and all
points are equal within the specified tolerance
.. versionadded:: 2.9
:rtype: bool
%End

static bool compare( const QgsPolygon &p1, const QgsPolygon &p2,
double epsilon = 4 * DBL_EPSILON ) /PyName=comparePolygons/;
%Docstring
Compares two polygons for equality within a specified tolerance.
\param p1 first polygon
\param p2 second polygon
\param epsilon maximum difference for coordinates between the polygons
:return: true if polygons have the same number of rings, and each ring has the same
number of points and all points are equal within the specified tolerance
.. versionadded:: 2.9
:rtype: bool
%End

static bool compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2,
double epsilon = 4 * DBL_EPSILON ) /PyName=compareMultiPolygons/;
%Docstring
Compares two multipolygons for equality within a specified tolerance.
\param p1 first multipolygon
\param p2 second multipolygon
\param epsilon maximum difference for coordinates between the multipolygons
:return: true if multipolygons have the same number of polygons, the polygons have the same number
of rings, and each ring has the same number of points and all points are equal within the specified
static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * DBL_EPSILON );
%Docstring
Compares two geometry objects for equality within a specified tolerance.
The objects can be of type QgsPolyline, QgsPolygon or QgsMultiPolygon.
The 2 types should match.
\param p1 first geometry object
\param p2 second geometry object
\param epsilon maximum difference for coordinates between the objects
:return: true if objects are
- polylines and have the same number of points and all
points are equal within the specified tolerance
- polygons and have the same number of points and all
points are equal within the specified tolerance
- multipolygons and have the same number of polygons, the polygons have the same number
of rings, and each ring has the same number of points and all points are equal
within the specified
tolerance
.. versionadded:: 2.9
:rtype: bool
%End
%MethodCode
{
sipRes = false;
int state0;
int state1;
int sipIsErr = 0;

if ( PyList_Check( a0 ) && PyList_Check( a1 ) &&
PyList_GET_SIZE( a0 ) && PyList_GET_SIZE( a1 ) )
{
PyObject *o0 = PyList_GetItem( a0, 0 );
PyObject *o1 = PyList_GetItem( a1, 0 );
if ( o0 && o1 )
{
// compare polyline - polyline
if ( sipCanConvertToType( o0, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( o1, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a0, sipType_QVector_0100QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a1, sipType_QVector_0100QgsPoint, SIP_NOT_NONE ) )
{
QgsPolyline *p0;
QgsPolyline *p1;
p0 = reinterpret_cast<QgsPolyline *>( sipConvertToType( a0, sipType_QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
p1 = reinterpret_cast<QgsPolyline *>( sipConvertToType( a1, sipType_QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p0, sipType_QVector_0100QgsPoint, state0 );
sipReleaseType( p1, sipType_QVector_0100QgsPoint, state1 );
}
else
{
sipRes = QgsGeometry::compare( *p0, *p1, a2 );
}
}
else if ( PyList_Check( o0 ) && PyList_Check( o1 ) &&
PyList_GET_SIZE( o0 ) && PyList_GET_SIZE( o1 ) )
{
PyObject *oo0 = PyList_GetItem( o0, 0 );
PyObject *oo1 = PyList_GetItem( o1, 0 );
if ( oo0 && oo1 )
{
// compare polygon - polygon
if ( sipCanConvertToType( oo0, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( oo1, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a0, sipType_QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a1, sipType_QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) )
{
QgsPolygon *p0;
QgsPolygon *p1;
p0 = reinterpret_cast<QgsPolygon *>( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
p1 = reinterpret_cast<QgsPolygon *>( sipConvertToType( a1, sipType_QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p0, sipType_QVector_0600QVector_0100QgsPoint, state0 );
sipReleaseType( p1, sipType_QVector_0600QVector_0100QgsPoint, state1 );
}
else
{
sipRes = QgsGeometry::compare( *p0, *p1, a2 );
}
}
else if ( PyList_Check( oo0 ) && PyList_Check( oo1 ) &&
PyList_GET_SIZE( oo0 ) && PyList_GET_SIZE( oo1 ) )
{
PyObject *ooo0 = PyList_GetItem( oo0, 0 );
PyObject *ooo1 = PyList_GetItem( oo1, 0 );
if ( ooo0 && ooo1 )
{
// compare multipolygon - multipolygon
if ( sipCanConvertToType( ooo0, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( ooo1, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) )
{
QgsMultiPolygon *p0;
QgsMultiPolygon *p1;
p0 = reinterpret_cast<QgsMultiPolygon *>( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
p1 = reinterpret_cast<QgsMultiPolygon *>( sipConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, state0 );
sipReleaseType( p1, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, state1 );
}
else
{
sipRes = QgsGeometry::compare( *p0, *p1, a2 );
}
}
}
}
}
}
}
}
}
%End

QgsGeometry smooth( const unsigned int iterations = 1, const double offset = 0.25,
double minimumDistance = -1.0, double maxAngle = 180.0 ) const;
Expand Down
2 changes: 1 addition & 1 deletion scripts/sipify_all.sh
Expand Up @@ -42,7 +42,7 @@ done < <(
${GP}sed -n -r 's/^%Include (.*\.sip)/core\/\1/p' python/core/core.sip
${GP}sed -n -r 's/^%Include (.*\.sip)/gui\/\1/p' python/gui/gui.sip
${GP}sed -n -r 's/^%Include (.*\.sip)/analysis\/\1/p' python/analysis/analysis.sip
${GP}sed -n -r 's/^%Include (.*\.sip)/server\/\1/p' python/analysis/server.sip
${GP}sed -n -r 's/^%Include (.*\.sip)/server\/\1/p' python/server/server.sip
)

echo " => $count files sipified!"
Expand Down
125 changes: 122 additions & 3 deletions src/core/geometry/qgsgeometry.h
Expand Up @@ -1042,6 +1042,8 @@ class CORE_EXPORT QgsGeometry
*/
static QgsPolygon createPolygonFromQPolygonF( const QPolygonF &polygon ) SIP_FACTORY;

#ifndef SIP_RUN

/** Compares two polylines for equality within a specified tolerance.
* \param p1 first polyline
* \param p2 second polyline
Expand All @@ -1051,7 +1053,7 @@ class CORE_EXPORT QgsGeometry
* \since QGIS 2.9
*/
static bool compare( const QgsPolyline &p1, const QgsPolyline &p2,
double epsilon = 4 * std::numeric_limits<double>::epsilon() SIP_PYARGDEFAULT( 4 * DBL_EPSILON ) ) SIP_PYNAME( comparePolylines );
double epsilon = 4 * std::numeric_limits<double>::epsilon() );

/** Compares two polygons for equality within a specified tolerance.
* \param p1 first polygon
Expand All @@ -1062,7 +1064,7 @@ class CORE_EXPORT QgsGeometry
* \since QGIS 2.9
*/
static bool compare( const QgsPolygon &p1, const QgsPolygon &p2,
double epsilon = 4 * std::numeric_limits<double>::epsilon() SIP_PYARGDEFAULT( 4 * DBL_EPSILON ) ) SIP_PYNAME( comparePolygons );
double epsilon = 4 * std::numeric_limits<double>::epsilon() );

/** Compares two multipolygons for equality within a specified tolerance.
* \param p1 first multipolygon
Expand All @@ -1074,7 +1076,124 @@ class CORE_EXPORT QgsGeometry
* \since QGIS 2.9
*/
static bool compare( const QgsMultiPolygon &p1, const QgsMultiPolygon &p2,
double epsilon = 4 * std::numeric_limits<double>::epsilon() SIP_PYARGDEFAULT( 4 * DBL_EPSILON ) ) SIP_PYNAME( compareMultiPolygons );
double epsilon = 4 * std::numeric_limits<double>::epsilon() );
#else

/** Compares two geometry objects for equality within a specified tolerance.
* The objects can be of type QgsPolyline, QgsPolygon or QgsMultiPolygon.
* The 2 types should match.
* \param p1 first geometry object
* \param p2 second geometry object
* \param epsilon maximum difference for coordinates between the objects
* \returns true if objects are
* - polylines and have the same number of points and all
* points are equal within the specified tolerance
* - polygons and have the same number of points and all
* points are equal within the specified tolerance
* - multipolygons and have the same number of polygons, the polygons have the same number
* of rings, and each ring has the same number of points and all points are equal
* within the specified
* tolerance
* \since QGIS 2.9
*/
static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * DBL_EPSILON );
% MethodCode
{
sipRes = false;
int state0;
int state1;
int sipIsErr = 0;

if ( PyList_Check( a0 ) && PyList_Check( a1 ) &&
PyList_GET_SIZE( a0 ) && PyList_GET_SIZE( a1 ) )
{
PyObject *o0 = PyList_GetItem( a0, 0 );
PyObject *o1 = PyList_GetItem( a1, 0 );
if ( o0 && o1 )
{
// compare polyline - polyline
if ( sipCanConvertToType( o0, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( o1, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a0, sipType_QVector_0100QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a1, sipType_QVector_0100QgsPoint, SIP_NOT_NONE ) )
{
QgsPolyline *p0;
QgsPolyline *p1;
p0 = reinterpret_cast<QgsPolyline *>( sipConvertToType( a0, sipType_QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
p1 = reinterpret_cast<QgsPolyline *>( sipConvertToType( a1, sipType_QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p0, sipType_QVector_0100QgsPoint, state0 );
sipReleaseType( p1, sipType_QVector_0100QgsPoint, state1 );
}
else
{
sipRes = QgsGeometry::compare( *p0, *p1, a2 );
}
}
else if ( PyList_Check( o0 ) && PyList_Check( o1 ) &&
PyList_GET_SIZE( o0 ) && PyList_GET_SIZE( o1 ) )
{
PyObject *oo0 = PyList_GetItem( o0, 0 );
PyObject *oo1 = PyList_GetItem( o1, 0 );
if ( oo0 && oo1 )
{
// compare polygon - polygon
if ( sipCanConvertToType( oo0, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( oo1, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a0, sipType_QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a1, sipType_QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) )
{
QgsPolygon *p0;
QgsPolygon *p1;
p0 = reinterpret_cast<QgsPolygon *>( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
p1 = reinterpret_cast<QgsPolygon *>( sipConvertToType( a1, sipType_QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p0, sipType_QVector_0600QVector_0100QgsPoint, state0 );
sipReleaseType( p1, sipType_QVector_0600QVector_0100QgsPoint, state1 );
}
else
{
sipRes = QgsGeometry::compare( *p0, *p1, a2 );
}
}
else if ( PyList_Check( oo0 ) && PyList_Check( oo1 ) &&
PyList_GET_SIZE( oo0 ) && PyList_GET_SIZE( oo1 ) )
{
PyObject *ooo0 = PyList_GetItem( oo0, 0 );
PyObject *ooo1 = PyList_GetItem( oo1, 0 );
if ( ooo0 && ooo1 )
{
// compare multipolygon - multipolygon
if ( sipCanConvertToType( ooo0, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( ooo1, sipType_QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) &&
sipCanConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, SIP_NOT_NONE ) )
{
QgsMultiPolygon *p0;
QgsMultiPolygon *p1;
p0 = reinterpret_cast<QgsMultiPolygon *>( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) );
p1 = reinterpret_cast<QgsMultiPolygon *>( sipConvertToType( a1, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state1, &sipIsErr ) );
if ( sipIsErr )
{
sipReleaseType( p0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, state0 );
sipReleaseType( p1, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, state1 );
}
else
{
sipRes = QgsGeometry::compare( *p0, *p1, a2 );
}
}
}
}
}
}
}
}
}
% End
#endif

/** Smooths a geometry by rounding off corners using the Chaikin algorithm. This operation
* roughly doubles the number of vertices in a geometry.
Expand Down
2 changes: 1 addition & 1 deletion tests/src/python/providertestbase.py
Expand Up @@ -711,7 +711,7 @@ def testExtent(self):
QgsRectangle(-71.123, 66.33, -65.32, 78.3))
provider_extent = QgsGeometry.fromRect(self.provider.extent())

self.assertTrue(QgsGeometry.comparePolylines(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001))
self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001))

def testUnique(self):
self.assertEqual(set(self.provider.uniqueValues(1)), set([-200, 100, 200, 300, 400]))
Expand Down
4 changes: 2 additions & 2 deletions tests/src/python/test_provider_ogr_gpkg.py
Expand Up @@ -191,7 +191,7 @@ def testGeopackageExtentUpdate(self):
self.assertTrue(vl.commitChanges())
reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 1.0))
provider_extent = QgsGeometry.fromRect(vl.extent())
self.assertTrue(QgsGeometry.comparePolylines(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001),
self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001),
provider_extent.asPolygon()[0])

# Test deleting a geometry that touches the bbox
Expand All @@ -200,7 +200,7 @@ def testGeopackageExtentUpdate(self):
self.assertTrue(vl.commitChanges())
reference = QgsGeometry.fromRect(QgsRectangle(0.5, 0.0, 1.0, 0.5))
provider_extent = QgsGeometry.fromRect(vl.extent())
self.assertTrue(QgsGeometry.comparePolylines(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001),
self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001),
provider_extent.asPolygon()[0])

def testSelectSubsetString(self):
Expand Down

0 comments on commit a86f5ea

Please sign in to comment.