Skip to content

Commit

Permalink
Improve method for calculation of rectangle centers
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 qgis#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 qgis#36898
Refs qgis#30686 (partial fix -- this report includes two different bugs)
  • Loading branch information
nyalldawson committed Jun 11, 2020
1 parent f1e3f82 commit 754375f
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 1 deletion.
2 changes: 1 addition & 1 deletion src/core/geometry/qgsrectangle.h
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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"

0 comments on commit 754375f

Please sign in to comment.