Skip to content
Permalink
Browse files

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)
  • Loading branch information
nyalldawson committed Jun 11, 2020
1 parent db8fa4f commit 47fba106dd9d057e6691dcca392efacbe31ad9ff
@@ -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.
@@ -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.

0 comments on commit 47fba10

Please sign in to comment.
You can’t perform that action at this time.