From 2265eb90ec62e6e6116d94c206cef9c2078b004c Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Tue, 16 Feb 2016 12:09:16 +1100 Subject: [PATCH] "Fix" QgsDistanceArea test on OSX Test has revealed that the current algorithm used for ellipsoidal calculations is unstable when measuring small very areas (eg < 1m2) For now, modify the test to use larger areas --- ci/travis/osx/script.sh | 2 +- tests/src/core/testqgsdistancearea.cpp | 94 ++++++++++++++++++++++++ tests/src/python/test_qgsdistancearea.py | 13 +++- 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/ci/travis/osx/script.sh b/ci/travis/osx/script.sh index 76a4cb276cc..084b71c01af 100755 --- a/ci/travis/osx/script.sh +++ b/ci/travis/osx/script.sh @@ -1,2 +1,2 @@ -ctest -V -E 'qgis_openstreetmaptest|qgis_wcsprovidertest|PyQgsServer|PyQgsDistanceArea' -S ./qgis-test-travis.ctest --output-on-failure +ctest -V -E 'qgis_openstreetmaptest|qgis_wcsprovidertest|PyQgsServer' -S ./qgis-test-travis.ctest --output-on-failure diff --git a/tests/src/core/testqgsdistancearea.cpp b/tests/src/core/testqgsdistancearea.cpp index edee9afb95e..db44e2e2829 100644 --- a/tests/src/core/testqgsdistancearea.cpp +++ b/tests/src/core/testqgsdistancearea.cpp @@ -41,6 +41,8 @@ class TestQgsDistanceArea: public QObject void regression13601(); void collections(); void measureUnits(); + void measureAreaAndUnits(); + }; void TestQgsDistanceArea::initTestCase() @@ -250,6 +252,98 @@ void TestQgsDistanceArea::measureUnits() QVERIFY( qgsDoubleNear( result, 2328.0988253106957, 0.001 ) ); } +void TestQgsDistanceArea::measureAreaAndUnits() +{ + QgsDistanceArea da; + da.setSourceCrs( 3452 ); + da.setEllipsoidalMode( false ); + da.setEllipsoid( "NONE" ); + QgsCoordinateReferenceSystem daCRS; + daCRS.createFromSrsId( da.sourceCrsId() ); + QgsPolyline ring; + ring << QgsPoint( 0, 0 ) + << QgsPoint( 1, 0 ) + << QgsPoint( 1, 1 ) + << QgsPoint( 2, 1 ) + << QgsPoint( 2, 2 ) + << QgsPoint( 0, 2 ) + << QgsPoint( 0, 0 ); + QgsPolygon poly; + poly << ring; + + QScopedPointer< QgsGeometry > polygon( QgsGeometry::fromPolygon( poly ) ); + + // We check both the measured area AND the units, in case the logic regarding + // ellipsoids and units changes in future + double area = da.measureArea( polygon.data() ); + QgsUnitTypes::AreaUnit units = da.areaUnits(); + + QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); + + QVERIFY(( qgsDoubleNear( area, 3.0, 0.00000001 ) && units == QgsUnitTypes::SquareDegrees ) + || ( qgsDoubleNear( area, 37176087091.5, 0.1 ) && units == QgsUnitTypes::SquareMeters ) ); + + da.setEllipsoid( "WGS84" ); + area = da.measureArea( polygon.data() ); + units = da.areaUnits(); + + QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); + QVERIFY(( qgsDoubleNear( area, 3.0, 0.00000001 ) && units == QgsUnitTypes::SquareDegrees ) + || ( qgsDoubleNear( area, 37176087091.5, 0.1 ) && units == QgsUnitTypes::SquareMeters ) ); + + da.setEllipsoidalMode( true ); + area = da.measureArea( polygon.data() ); + units = da.areaUnits(); + + QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); + // should always be in Meters Squared + QVERIFY( qgsDoubleNear( area, 37416879192.9, 0.1 ) ); + QCOMPARE( units, QgsUnitTypes::SquareMeters ); + + // test converting the resultant area + area = da.convertAreaMeasurement( area, QgsUnitTypes::SquareMiles ); + QVERIFY( qgsDoubleNear( area, 14446.7378, 0.001 ) ); + + // now try with a source CRS which is in feet + ring.clear(); + ring << QgsPoint( 1850000, 4423000 ) + << QgsPoint( 1851000, 4423000 ) + << QgsPoint( 1851000, 4424000 ) + << QgsPoint( 1852000, 4424000 ) + << QgsPoint( 1852000, 4425000 ) + << QgsPoint( 1851000, 4425000 ) + << QgsPoint( 1850000, 4423000 ); + poly.clear(); + poly << ring; + polygon.reset( QgsGeometry::fromPolygon( poly ) ); + + da.setSourceCrs( 27469 ); + da.setEllipsoidalMode( false ); + // measurement should be in square feet + area = da.measureArea( polygon.data() ); + units = da.areaUnits(); + QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); + QVERIFY( qgsDoubleNear( area, 2000000, 0.001 ) ); + QCOMPARE( units, QgsUnitTypes::SquareFeet ); + + // test converting the resultant area + area = da.convertAreaMeasurement( area, QgsUnitTypes::SquareYards ); + QVERIFY( qgsDoubleNear( area, 222222.2222, 0.001 ) ); + + da.setEllipsoidalMode( true ); + // now should be in Square Meters again + area = da.measureArea( polygon.data() ); + units = da.areaUnits(); + QgsDebugMsg( QString( "measured %1 in %2" ).arg( area ).arg( QgsUnitTypes::toString( units ) ) ); + QVERIFY( qgsDoubleNear( area, 184149.37309564, 0.00001 ) ); + QCOMPARE( units, QgsUnitTypes::SquareMeters ); + + // test converting the resultant area + area = da.convertAreaMeasurement( area, QgsUnitTypes::SquareYards ); + QgsDebugMsg( QString( "measured %1 in sq yrds" ).arg( area ) ); + QVERIFY( qgsDoubleNear( area, 220240.8172549, 0.00001 ) ); +} + QTEST_MAIN( TestQgsDistanceArea ) #include "testqgsdistancearea.moc" diff --git a/tests/src/python/test_qgsdistancearea.py b/tests/src/python/test_qgsdistancearea.py index ecdb5008dd1..08a47b7b444 100644 --- a/tests/src/python/test_qgsdistancearea.py +++ b/tests/src/python/test_qgsdistancearea.py @@ -270,30 +270,35 @@ class TestQgsDistanceArea(unittest.TestCase): self.assertAlmostEqual(area, 14446.7378, delta=0.001) # now try with a source CRS which is in feet + polygon = QgsGeometry.fromPolygon( + [[ + QgsPoint(1850000, 4423000), QgsPoint(1851000, 4423000), QgsPoint(1851000, 4424000), QgsPoint(1852000, 4424000), QgsPoint(1852000, 4425000), QgsPoint(1851000, 4425000), QgsPoint(1850000, 4423000) + ]] + ) da.setSourceCrs(27469) da.setEllipsoidalMode(False) # measurement should be in square feet area = da.measureArea(polygon) units = da.areaUnits() print "measured {} in {}".format(area, QgsUnitTypes.toString(units)) - self.assertAlmostEqual(area, 3.0, delta=0.000001) + self.assertAlmostEqual(area, 2000000, delta=0.001) self.assertEqual(units, QgsUnitTypes.SquareFeet) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareYards) - self.assertAlmostEqual(area, 0.333333, delta=0.001) + self.assertAlmostEqual(area, 222222.2222, delta=0.001) da.setEllipsoidalMode(True) # now should be in Square Meters again area = da.measureArea(polygon) units = da.areaUnits() print "measured {} in {}".format(area, QgsUnitTypes.toString(units)) - self.assertAlmostEqual(area, 0.256102704082, delta=0.000001) + self.assertAlmostEqual(area, 184149.37309564, delta=0.000001) self.assertEqual(units, QgsUnitTypes.SquareMeters) # test converting the resultant area area = da.convertAreaMeasurement(area, QgsUnitTypes.SquareYards) - self.assertAlmostEqual(area, 0.30629, delta=0.0001) + self.assertAlmostEqual(area, 220240.8172549, delta=0.0001) if __name__ == '__main__': unittest.main()