Fix regression in transforming bounding box involving web mercator

...and geographic CRS when a reversible coordinate operation is
in effect.

Follow up https://github.com/qgis/QGIS/pull/46939
This commit is contained in:
Nyall Dawson 2025-08-22 11:15:49 +10:00
parent 88d6e0d808
commit 1addba59cb
2 changed files with 86 additions and 2 deletions

View File

@ -617,8 +617,7 @@ QgsRectangle QgsCoordinateTransform::transformBoundingBox( const QgsRectangle &r
double yMin = rect.yMinimum();
double yMax = rect.yMaximum();
if ( d->mGeographicToWebMercator &&
( ( direction == Qgis::TransformDirection::Forward && !d->mIsReversed ) ||
( direction == Qgis::TransformDirection::Reverse && d->mIsReversed ) ) )
( direction == Qgis::TransformDirection::Forward ) )
{
// Latitudes close to 90 degree project to infinite northing in theory.
// We limit to 90 - 1e-1 which reproject to northing of ~ 44e6 m (about twice

View File

@ -395,6 +395,91 @@ class TestQgsCoordinateTransform(QgisTestCase):
self.assertAlmostEqual(transformedExtent.xMaximum(), 20037508.343, delta=1e-3)
self.assertAlmostEqual(transformedExtent.yMaximum(), 44927335.427, delta=1e-3)
round_trip_extent = transform.transformBoundingBox(
transformedExtent, Qgis.TransformDirection.Reverse
)
self.assertAlmostEqual(round_trip_extent.xMinimum(), -180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMinimum(), -89.9, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.xMaximum(), 180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMaximum(), 89.9, delta=1e-3)
# test opposite transform
transform = QgsCoordinateTransform(
QgsCoordinateReferenceSystem("EPSG:3857"),
QgsCoordinateReferenceSystem("EPSG:4326"),
QgsProject.instance(),
)
transformedExtent = transform.transformBoundingBox(
extent, Qgis.TransformDirection.Reverse
)
self.assertAlmostEqual(transformedExtent.xMinimum(), -20037508.343, delta=1e-3)
self.assertAlmostEqual(
transformedExtent.yMinimum(), -242528680.9437, delta=1e-3
)
self.assertAlmostEqual(transformedExtent.xMaximum(), 20037508.343, delta=1e-3)
self.assertAlmostEqual(transformedExtent.yMaximum(), 242528680.9437, delta=1e-3)
round_trip_extent = transform.transformBoundingBox(
transformedExtent, Qgis.TransformDirection.Forward
)
self.assertAlmostEqual(round_trip_extent.xMinimum(), -180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMinimum(), -90.0, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.xMaximum(), 180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMaximum(), 90.0, delta=1e-3)
def testTransformBoundingBoxFullWorldToWebMercator7844(self):
extent = QgsRectangle(-180, -90, 180, 90)
context = QgsCoordinateTransformContext()
context.addCoordinateOperation(
QgsCoordinateReferenceSystem("EPSG:3857"),
QgsCoordinateReferenceSystem("EPSG:7844"),
"+proj=pipeline +step +inv +proj=webmerc +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +step +proj=unitconvert +xy_in=rad +xy_out=deg",
)
transform = QgsCoordinateTransform(
QgsCoordinateReferenceSystem("EPSG:7844"),
QgsCoordinateReferenceSystem("EPSG:3857"),
context,
)
transformedExtent = transform.transformBoundingBox(extent)
self.assertAlmostEqual(transformedExtent.xMinimum(), -20037508.343, delta=1e-3)
self.assertAlmostEqual(transformedExtent.yMinimum(), -44927335.427, delta=1e-3)
self.assertAlmostEqual(transformedExtent.xMaximum(), 20037508.343, delta=1e-3)
self.assertAlmostEqual(transformedExtent.yMaximum(), 44927335.427, delta=1e-3)
round_trip_extent = transform.transformBoundingBox(
transformedExtent, Qgis.TransformDirection.Reverse
)
self.assertAlmostEqual(round_trip_extent.xMinimum(), -180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMinimum(), -89.9, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.xMaximum(), 180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMaximum(), 89.9, delta=1e-3)
# test opposite transform
transform = QgsCoordinateTransform(
QgsCoordinateReferenceSystem("EPSG:3857"),
QgsCoordinateReferenceSystem("EPSG:7844"),
QgsProject.instance(),
)
transformedExtent = transform.transformBoundingBox(
extent, Qgis.TransformDirection.Reverse
)
self.assertAlmostEqual(transformedExtent.xMinimum(), -20037508.343, delta=1e-3)
self.assertAlmostEqual(
transformedExtent.yMinimum(), -242528680.9437, delta=1e-3
)
self.assertAlmostEqual(transformedExtent.xMaximum(), 20037508.343, delta=1e-3)
self.assertAlmostEqual(transformedExtent.yMaximum(), 242528680.9437, delta=1e-3)
round_trip_extent = transform.transformBoundingBox(
transformedExtent, Qgis.TransformDirection.Forward
)
self.assertAlmostEqual(round_trip_extent.xMinimum(), -180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMinimum(), -90.0, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.xMaximum(), 180, delta=1e-3)
self.assertAlmostEqual(round_trip_extent.yMaximum(), 90.0, delta=1e-3)
def test_has_vertical_component(self):
transform = QgsCoordinateTransform()
self.assertFalse(transform.hasVerticalComponent())