Improve method for calculation of rectangle centers (#37092)

More numerically stable in the case of massive rectangles.

This is the ultimate cause behind #36898 -- during rendering of the
worldwide layer in Winkel Tripel the inverse transform fails, so
the renderer sets a "maximal" filter extent for the layer (+/- double
max). The previous method for calculating the rectangles center would
fail, because it would overflow. The new method handles this case
and correctly returns 0,0.

Fixes bounding boxes show incorrectly when simplication is enabled
for a layer in certain projections.

Fixes #36898
Refs #30686 (partial fix -- this report includes two different bugs)
This commit is contained in:
Nyall Dawson 2020-06-11 13:53:20 +10:00 committed by GitHub
parent db8fa4f664
commit 47fba106dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 19 additions and 1 deletions

View File

@ -227,7 +227,7 @@ class CORE_EXPORT QgsRectangle
/**
* Returns the center point of the rectangle.
*/
QgsPointXY center() const { return QgsPointXY( mXmin + width() / 2, mYmin + height() / 2 ); }
QgsPointXY center() const { return QgsPointXY( mXmax * 0.5 + mXmin * 0.5, mYmin * 0.5 + mYmax * 0.5 ); }
/**
* Scale the rectangle around its center point.

View File

@ -43,6 +43,7 @@ class TestQgsRectangle: public QObject
void scale();
void snappedToGrid();
void distanceToPoint();
void center();
};
void TestQgsRectangle::isEmpty()
@ -404,5 +405,22 @@ void TestQgsRectangle::distanceToPoint()
QGSCOMPARENEAR( rect.distance( QgsPointXY( 25, 115 ) ), 7.071068, 0.00001 );
}
void TestQgsRectangle::center()
{
QgsRectangle rect( 10, 100, 20, 110 );
QCOMPARE( rect.center().x(), 15.0 );
QCOMPARE( rect.center().y(), 105.0 );
rect = QgsRectangle( 10, 100, 10, 100 );
QCOMPARE( rect.center().x(), 10.0 );
QCOMPARE( rect.center().y(), 100.0 );
rect = QgsRectangle( -10, -100, 10, 100 );
QCOMPARE( rect.center().x(), 0.0 );
QCOMPARE( rect.center().y(), 0.0 );
// a "maximal" rect
rect = QgsRectangle( std::numeric_limits<double>::lowest(), std::numeric_limits<double>::lowest(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max() );
QCOMPARE( rect.center().x(), 0.0 );
QCOMPARE( rect.center().y(), 0.0 );
}
QGSTEST_MAIN( TestQgsRectangle )
#include "testqgsrectangle.moc"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 18 KiB