From 3fbb14e1d8f805284592a271297d1c85980676c0 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Fri, 22 May 2020 16:38:07 +1000 Subject: [PATCH] Fix oriented minimum bounding box calculation is wrong in some cases Fixes #36632 --- .../testdata/expected/mbg_rect_field.gml | 24 ++++---- .../testdata/expected/oriented_bounds.gml | 56 +++++++++---------- src/core/geometry/qgsgeometry.cpp | 10 ++-- tests/src/core/testqgsgeometry.cpp | 4 +- tests/src/python/test_qgsgeometry.py | 12 ++-- 5 files changed, 53 insertions(+), 53 deletions(-) diff --git a/python/plugins/processing/tests/testdata/expected/mbg_rect_field.gml b/python/plugins/processing/tests/testdata/expected/mbg_rect_field.gml index 07a223afb66d..d80ebb4f3e22 100644 --- a/python/plugins/processing/tests/testdata/expected/mbg_rect_field.gml +++ b/python/plugins/processing/tests/testdata/expected/mbg_rect_field.gml @@ -7,7 +7,7 @@ -2.056603773584904-3 - 9.1629558541266826.489909219550769 + 9.1629558541266826.088675623800386 @@ -25,26 +25,26 @@ - 5.24145873320538,-1.05451055662188 6.24145873320538,-2.05451055662188 7.24145873320538,-1.05451055662188 6.24145873320538,-0.054510556621882 5.24145873320538,-1.05451055662188 + 7.24145873320538,-1.05451055662188 7.24145873320538,-0.054510556621881 5.24145873320538,-0.054510556621881 5.24145873320538,-1.05451055662188 7.24145873320538,-1.05451055662188 1 dd - 1.414214 - 1.414214 - 45.000000 + 1.000000 + 2.000000 + 90.000000 2.000000 - 5.656854 + 6.000000 - 5.34748915030878,4.7278689643513 5.06593031585745,6.48990921955077 1.84418704183259,5.97510243323637 2.12574587628392,4.2130621780369 5.34748915030878,4.7278689643513 + 5.17255278310941,4.42360844529751 5.17255278310941,6.08867562380039 2.0,6.08867562380039 2.0,4.4236084452975 5.17255278310941,4.42360844529751 2 bb - 1.784394 - 3.262615 - 80.921378 - 5.821790 - 10.094017 + 1.665067 + 3.172553 + 90.000000 + 5.282514 + 9.675240 diff --git a/python/plugins/processing/tests/testdata/expected/oriented_bounds.gml b/python/plugins/processing/tests/testdata/expected/oriented_bounds.gml index 9381e504923a..1cacb2b0c9bb 100644 --- a/python/plugins/processing/tests/testdata/expected/oriented_bounds.gml +++ b/python/plugins/processing/tests/testdata/expected/oriented_bounds.gml @@ -6,35 +6,35 @@ xmlns:gml="http://www.opengis.net/gml"> - -1-3.270344827586211 - 10.04413793103456.468552677345371 + -1-3.270344827586206 + 10.044137931034486.494117647058823 - + - 6.0,-3.0 7.69811320754717,0.056603773584905 3.80943396226415,2.21698113207547 2.11132075471698,-0.839622641509436 6.0,-3.0 + 3.8,2.2 2.11847133757962,-0.882802547770694 6.0,-3.0 7.68152866242039,0.082802547770697 3.8,2.2 120 -100291.43213 - 3.496629 - 4.448489 - 119.054604 - 15.554717 - 15.890237 + 3.511582 + 4.421401 + 118.610460 + 15.526115 + 15.865967 - 5.6332734,5.0792647 3.84029,4.4700214 4.2070166,3.3907567 6,4 5.6332734,5.0792647 + 4.0,4.0 4.67567567567567,3.05405405405406 6.07567567567567,4.05405405405405 5.4,5.0 4.0,4.0 -33 0 Aaaaa - 1.893665 - 1.139869 - 161.232595 - 2.158529 - 6.067067 + 1.162476 + 1.720465 + 54.462322 + 2.000000 + 5.765883 @@ -52,7 +52,7 @@ - 6.4,-3 9.6441379,-3.2703448 10.0441379,1.5296552 6.8,1.8 6.4,-3 + 6.4,-3.0 9.64413793103449,-3.27034482758621 10.0441379310345,1.52965517241379 6.8,1.8 6.4,-3.0 0 ASDF @@ -65,28 +65,28 @@ - 1.1679275,5.4220069 1.6,4.8 3.1065959,5.8465458 2.6745233,6.4685527 1.1679275,5.4220069 + 3.0,6.0 2.57647058823529,6.49411764705882 1.17647058823529,5.29411764705882 1.6,4.8 3.0,6.0 0.123 bbaaa - 0.757350 - 1.834418 - 55.214507 - 1.389297 - 5.183536 + 0.650791 + 1.843909 + 49.398705 + 1.200000 + 4.989401 - 6.0,-3.0 7.69811320754717,0.056603773584905 3.80943396226415,2.21698113207547 2.11132075471698,-0.839622641509436 6.0,-3.0 + 3.8,2.2 2.11847133757962,-0.882802547770694 6.0,-3.0 7.68152866242039,0.082802547770697 3.8,2.2 2 3.33 elim - 3.496629 - 4.448489 - 119.054604 - 15.554717 - 15.890237 + 3.511582 + 4.421401 + 118.610460 + 15.526115 + 15.865967 diff --git a/src/core/geometry/qgsgeometry.cpp b/src/core/geometry/qgsgeometry.cpp index 03ae4403f2f3..1fcf44fc29e4 100644 --- a/src/core/geometry/qgsgeometry.cpp +++ b/src/core/geometry/qgsgeometry.cpp @@ -976,12 +976,12 @@ QgsGeometry QgsGeometry::orientedMinimumBoundingBox( double &area, double &angle // get first point hull.constGet()->nextVertex( vertexId, pt0 ); pt1 = pt0; - double prevAngle = 0.0; + double totalRotation = 0; while ( hull.constGet()->nextVertex( vertexId, pt2 ) ) { double currentAngle = QgsGeometryUtils::lineAngle( pt1.x(), pt1.y(), pt2.x(), pt2.y() ); - double rotateAngle = 180.0 / M_PI * ( currentAngle - prevAngle ); - prevAngle = currentAngle; + double rotateAngle = 180.0 / M_PI * currentAngle; + totalRotation += rotateAngle; QTransform t = QTransform::fromTranslate( pt0.x(), pt0.y() ); t.rotate( rotateAngle ); @@ -995,12 +995,12 @@ QgsGeometry QgsGeometry::orientedMinimumBoundingBox( double &area, double &angle { minRect = bounds; area = currentArea; - angle = 180.0 / M_PI * currentAngle; + angle = totalRotation; width = bounds.width(); height = bounds.height(); } - pt1 = pt2; + pt1 = hull.constGet()->vertexAt( vertexId ); } QgsGeometry minBounds = QgsGeometry::fromRect( minRect ); diff --git a/tests/src/core/testqgsgeometry.cpp b/tests/src/core/testqgsgeometry.cpp index b45b40fba04b..42e3be0d07f4 100644 --- a/tests/src/core/testqgsgeometry.cpp +++ b/tests/src/core/testqgsgeometry.cpp @@ -17571,8 +17571,8 @@ void TestQgsGeometry::orientedMinimumBoundingBox() // Issue https://github.com/qgis/QGIS/issues/33532 geomTest = QgsGeometry::fromWkt( QStringLiteral( " Polygon ((264 -525, 248 -521, 244 -519, 233 -508, 231 -504, 210 -445, 196 -396, 180 -332, 178 -322, 176 -310, 174 -296, 174 -261, 176 -257, 178 -255, 183 -251, 193 -245, 197 -243, 413 -176, 439 -168, 447 -166, 465 -164, 548 -164, 552 -166, 561 -175, 567 -187, 602 -304, 618 -379, 618 -400, 616 -406, 612 -414, 606 -420, 587 -430, 575 -436, 547 -446, 451 -474, 437 -478, 321 -511, 283 -521, 275 -523, 266 -525, 264 -525)) " ) ); result = geomTest.orientedMinimumBoundingBox( ); - QString resultTestWKT = QStringLiteral( "Polygon ((153.56814721430669124 -251.04910547836090018, 236.58928384252226351 -536.38483199428605985, 635.81698325140541783 -420.2257453523852746, 552.79584662318995925 -134.89001883646011493, 153.56814721430669124 -251.04910547836090018))" ); - QCOMPARE( result.asWkt(), resultTestWKT ); + QString resultTestWKT = QStringLiteral( "Polygon ((635.86 -420.08, 552.66 -134.85, 153.5 -251.27, 236.69 -536.51, 635.86 -420.08))" ); + QCOMPARE( result.asWkt( 2 ), resultTestWKT ); } void TestQgsGeometry::minimalEnclosingCircle() diff --git a/tests/src/python/test_qgsgeometry.py b/tests/src/python/test_qgsgeometry.py index 709290305e84..f1b2edcbae31 100644 --- a/tests/src/python/test_qgsgeometry.py +++ b/tests/src/python/test_qgsgeometry.py @@ -4714,15 +4714,15 @@ def testMinimumOrientedBoundingBox(self): # polygon polygon = QgsGeometry.fromWkt('Polygon((-0.1 -1.3, 2.1 1, 3 2.8, 6.7 0.2, 3 -1.8, 0.3 -2.7, -0.1 -1.3))') bbox, area, angle, width, height = polygon.orientedMinimumBoundingBox() - exp = 'Polygon ((2.63653329463248109 -4.65542585423934607, 6.70000000000000284 0.19999999999999485, 3.24436595086289614 3.09199224252241889, -0.81910075450462605 -1.76343361171692159, 2.63653329463248109 -4.65542585423934607))' + exp = 'Polygon ((-0.628 -1.9983, 2.9769 -4.724, 6.7 0.2, 3.095 2.9257, -0.628 -1.9983))' - result = bbox.asWkt() + result = bbox.asWkt(4) self.assertTrue(compareWkt(result, exp, 0.00001), "Oriented MBBR: mismatch Expected:\n{}\nGot:\n{}\n".format(exp, result)) - self.assertAlmostEqual(area, 28.5300, places=3) - self.assertAlmostEqual(angle, 129.9257, places=3) - self.assertAlmostEqual(width, 6.3314, places=3) - self.assertAlmostEqual(height, 4.5061, places=3) + self.assertAlmostEqual(area, 27.89886071158214, places=3) + self.assertAlmostEqual(angle, 37.09283729704157, places=3) + self.assertAlmostEqual(width, 4.519421040409892, places=3) + self.assertAlmostEqual(height, 6.173105019896937, places=3) def testOrthogonalize(self): empty = QgsGeometry()