Skip to content

Commit

Permalink
Improve method for calculation of rectangle centers (#37092)
Browse files Browse the repository at this point in the history
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 47fba10
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/core/geometry/qgsrectangle.h
Expand Up @@ -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.
Expand Down
18 changes: 18 additions & 0 deletions tests/src/core/testqgsrectangle.cpp
Expand Up @@ -43,6 +43,7 @@ class TestQgsRectangle: public QObject
void scale();
void snappedToGrid();
void distanceToPoint();
void center();
};

void TestQgsRectangle::isEmpty()
Expand Down Expand Up @@ -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"
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 47fba10

Please sign in to comment.