From a86f5ea52d75862c190105d1ceb23c47a61bba4e Mon Sep 17 00:00:00 2001 From: Denis Rouzaud Date: Sun, 30 Apr 2017 11:17:13 +0200 Subject: [PATCH] remove PyNames for QgsGeometry::compare methods single python method with some MethodCode to dispatch to proper cpp methods. --- python/core/geometry/qgsgeometry.sip | 144 ++++++++++++++++----- scripts/sipify_all.sh | 2 +- src/core/geometry/qgsgeometry.h | 125 +++++++++++++++++- tests/src/python/providertestbase.py | 2 +- tests/src/python/test_provider_ogr_gpkg.py | 4 +- tests/src/python/test_provider_wfs.py | 10 +- tests/src/python/test_qgsgeometry.py | 25 +++- 7 files changed, 262 insertions(+), 50 deletions(-) diff --git a/python/core/geometry/qgsgeometry.sip b/python/core/geometry/qgsgeometry.sip index a67e8b16b0f..c0050c55ef9 100644 --- a/python/core/geometry/qgsgeometry.sip +++ b/python/core/geometry/qgsgeometry.sip @@ -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/; + static bool compare( PyObject *obj1, PyObject *obj2, double epsilon = 4 * DBL_EPSILON ); %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 + 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( sipConvertToType( a0, sipType_QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) ); + p1 = reinterpret_cast( 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( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) ); + p1 = reinterpret_cast( 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( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) ); + p1 = reinterpret_cast( 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; diff --git a/scripts/sipify_all.sh b/scripts/sipify_all.sh index c40d1b160f9..7dca02e5914 100755 --- a/scripts/sipify_all.sh +++ b/scripts/sipify_all.sh @@ -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!" diff --git a/src/core/geometry/qgsgeometry.h b/src/core/geometry/qgsgeometry.h index 24e31270141..958b19805d2 100644 --- a/src/core/geometry/qgsgeometry.h +++ b/src/core/geometry/qgsgeometry.h @@ -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 @@ -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::epsilon() SIP_PYARGDEFAULT( 4 * DBL_EPSILON ) ) SIP_PYNAME( comparePolylines ); + double epsilon = 4 * std::numeric_limits::epsilon() ); /** Compares two polygons for equality within a specified tolerance. * \param p1 first polygon @@ -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::epsilon() SIP_PYARGDEFAULT( 4 * DBL_EPSILON ) ) SIP_PYNAME( comparePolygons ); + double epsilon = 4 * std::numeric_limits::epsilon() ); /** Compares two multipolygons for equality within a specified tolerance. * \param p1 first multipolygon @@ -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::epsilon() SIP_PYARGDEFAULT( 4 * DBL_EPSILON ) ) SIP_PYNAME( compareMultiPolygons ); + double epsilon = 4 * std::numeric_limits::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( sipConvertToType( a0, sipType_QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) ); + p1 = reinterpret_cast( 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( sipConvertToType( a0, sipType_QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) ); + p1 = reinterpret_cast( 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( sipConvertToType( a0, sipType_QVector_0600QVector_0600QVector_0100QgsPoint, 0, SIP_NOT_NONE, &state0, &sipIsErr ) ); + p1 = reinterpret_cast( 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. diff --git a/tests/src/python/providertestbase.py b/tests/src/python/providertestbase.py index 35b410dcc1b..5c5e3674c80 100644 --- a/tests/src/python/providertestbase.py +++ b/tests/src/python/providertestbase.py @@ -711,7 +711,7 @@ class ProviderTestCase(object): 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])) diff --git a/tests/src/python/test_provider_ogr_gpkg.py b/tests/src/python/test_provider_ogr_gpkg.py index 77105bd073c..7f6cff00251 100644 --- a/tests/src/python/test_provider_ogr_gpkg.py +++ b/tests/src/python/test_provider_ogr_gpkg.py @@ -191,7 +191,7 @@ class TestPyQgsOGRProviderGpkg(unittest.TestCase): 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 @@ -200,7 +200,7 @@ class TestPyQgsOGRProviderGpkg(unittest.TestCase): 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): diff --git a/tests/src/python/test_provider_wfs.py b/tests/src/python/test_provider_wfs.py index 25f73e75bf2..24f944f6c54 100644 --- a/tests/src/python/test_provider_wfs.py +++ b/tests/src/python/test_provider_wfs.py @@ -408,7 +408,7 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase): self.assertEqual(vl.featureCount(), 0) reference = QgsGeometry.fromRect(QgsRectangle(400000.0, 5400000.0, 450000.0, 5500000.0)) vl_extent = QgsGeometry.fromRect(vl.extent()) - assert QgsGeometry.comparePolylines(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) + assert QgsGeometry.compare(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) with open(sanitize(endpoint, '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:32631'), 'wb') as f: f.write(""" @@ -651,7 +651,7 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase): reference = QgsGeometry.fromRect(QgsRectangle(399999.9999999680439942, 5399338.9090830031782389, 449999.9999999987776391, 5500658.0448500607162714)) vl_extent = QgsGeometry.fromRect(vl.extent()) - assert QgsGeometry.comparePolylines(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) + assert QgsGeometry.compare(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) def testWFST10(self): """Test WFS-T 1.0 (read-write)""" @@ -2016,7 +2016,7 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase): reference = QgsGeometry.fromRect(QgsRectangle(2, 49, 2, 49)) vl_extent = QgsGeometry.fromRect(vl.extent()) - assert QgsGeometry.comparePolylines(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) + assert QgsGeometry.compare(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) # Same with restrictToRequestBBOX=1 vl = QgsVectorLayer("url='http://" + endpoint + "' typename='my:typename' version='2.0.0' restrictToRequestBBOX=1", 'test', 'WFS') @@ -2157,7 +2157,7 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase): # Extent before downloading features reference = QgsGeometry.fromRect(QgsRectangle(243900.3520259926444851, 4427769.1559739429503679, 1525592.3040170343592763, 5607994.6020106188952923)) vl_extent = QgsGeometry.fromRect(vl.extent()) - assert QgsGeometry.comparePolylines(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) + assert QgsGeometry.compare(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) # Download all features features = [f for f in vl.getFeatures()] @@ -2165,7 +2165,7 @@ class TestPyQgsWFSProvider(unittest.TestCase, ProviderTestCase): reference = QgsGeometry.fromRect(QgsRectangle(500000, 4500000, 510000, 4510000)) vl_extent = QgsGeometry.fromRect(vl.extent()) - assert QgsGeometry.comparePolylines(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) + assert QgsGeometry.compare(vl_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001), 'Expected {}, got {}'.format(reference.exportToWkt(), vl_extent.exportToWkt()) self.assertEqual(features[0]['intfield'], 1) self.assertEqual(features[1]['intfield'], 2) diff --git a/tests/src/python/test_qgsgeometry.py b/tests/src/python/test_qgsgeometry.py index 6d92b016770..aece0fb128e 100644 --- a/tests/src/python/test_qgsgeometry.py +++ b/tests/src/python/test_qgsgeometry.py @@ -340,7 +340,7 @@ class TestQgsGeometry(unittest.TestCase): """Test we can simplify a complex geometry. Note: there is a ticket related to this issue here: - https://issues.qgis.org/issues/4189 + http://hub.qgis.org/issues/4189 Backstory: Ole Nielson pointed out an issue to me (Tim Sutton) where simplify ftools was dropping @@ -1671,7 +1671,7 @@ class TestQgsGeometry(unittest.TestCase): assert compareWkt(expWkt, wkt), "convertToType failed: from multiline to polygon. Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt) def testRegression13053(self): - """ See https://issues.qgis.org/issues/13053 """ + """ See http://hub.qgis.org/issues/13053 """ p = QgsGeometry.fromWkt('MULTIPOLYGON(((62.0 18.0, 62.0 19.0, 63.0 19.0, 63.0 18.0, 62.0 18.0)), ((63.0 19.0, 63.0 20.0, 64.0 20.0, 64.0 19.0, 63.0 19.0)))') assert p is not None @@ -1680,7 +1680,7 @@ class TestQgsGeometry(unittest.TestCase): assert compareWkt(expWkt, wkt), "testRegression13053 failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt) def testRegression13055(self): - """ See https://issues.qgis.org/issues/13055 + """ See http://hub.qgis.org/issues/13055 Testing that invalid WKT with z values but not using PolygonZ is still parsed by QGIS. """ @@ -1692,7 +1692,7 @@ class TestQgsGeometry(unittest.TestCase): assert compareWkt(expWkt, wkt), "testRegression13055 failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt) def testRegression13274(self): - """ See https://issues.qgis.org/issues/13274 + """ See http://hub.qgis.org/issues/13274 Testing that two combined linestrings produce another line string if possible """ a = QgsGeometry.fromWkt('LineString (0 0, 1 0)') @@ -1711,7 +1711,7 @@ class TestQgsGeometry(unittest.TestCase): wkt = g.exportToWkt() assert compareWkt(expWkt, wkt), "testReshape failed: mismatch Expected:\n%s\nGot:\n%s\n" % (expWkt, wkt) - # Test reshape a geometry involving the first/last vertex (https://issues.qgis.org/issues/14443) + # Test reshape a geometry involving the first/last vertex (http://hub.qgis.org/issues/14443) g.reshapeGeometry([QgsPoint(0.5, 1), QgsPoint(0, 0.5)]) expWkt = 'Polygon ((0 0.5, 0 0, 1 0, 1 0.5, 0.5 1, 0 0.5))' @@ -4114,6 +4114,21 @@ class TestQgsGeometry(unittest.TestCase): self.assertTrue(compareWkt(result, exp, 0.00001), "centroid: mismatch using QgsAbstractGeometry methods Input {} \n Expected:\n{}\nGot:\n{}\n".format(t[0], exp, result)) + def testCompare(self): + lp = [QgsPoint(1, 1), QgsPoint(2, 2), QgsPoint(1, 2), QgsPoint(1, 1)] + lp2 = [QgsPoint(1, 1.0000001), QgsPoint(2, 2), QgsPoint(1, 2), QgsPoint(1, 1)] + self.assertTrue(QgsGeometry.compare(lp, lp)) # line-line + self.assertTrue(QgsGeometry.compare([lp], [lp])) # pylygon-polygon + self.assertTrue(QgsGeometry.compare([[lp]], [[lp]])) # multipyolygon-multipolygon + # handling empty values + self.assertFalse(QgsGeometry.compare(None, None)) + self.assertFalse(QgsGeometry.compare(lp, [])) # line-line + self.assertFalse(QgsGeometry.compare([lp], [[]])) # pylygon-polygon + self.assertFalse(QgsGeometry.compare([[lp]], [[[]]])) # multipolygon-multipolygon + # tolerance + self.assertFalse(QgsGeometry.compare(lp, lp2)) + self.assertTrue(QgsGeometry.compare(lp, lp2, 1e-6)) + if __name__ == '__main__': unittest.main()