-
Notifications
You must be signed in to change notification settings - Fork 28
Description
When requesting the xy_bbox property from a TileMatrixSet instance with cornerOfOrigin="bottomLeft", top and bottom of the bounding box are flipped. There is probably a bug in xy_bbox, since it does not consider the cornerOfOrigin. The following lines need to consider the right tile indices, depending on cornerOfOrigin:
https://github.com/developmentseed/morecantile/blob/main/morecantile/models.py#L1262-L1266
Here is a MWE with a walkthrough of the issues:
from morecantile.models import TileMatrixSet, Tile
import pyproj
extent = [-100_000, -100_000, 200_000, 200_000]
tms = TileMatrixSet.custom(
extent,
pyproj.CRS.from_epsg(3857),
minzoom=0,
maxzoom=1,
corner_of_origin="bottomLeft",
)The expected bounding box is BoundingBox(left=-100000.0, bottom=-100000.0, right=200000.0, top=200000.0), but the result is flipped in y:
tms.xy_bboxBoundingBox(left=-100000.0, bottom=200000.0, right=200000.0, top=-100000.0)
This is due to two reasons. First, tms._lr and tms._ul return the wrong coordinates for y:
tms._ul(Tile(0, 0, 0)).y, tms._lr(Tile(0, 0, 0)).y (-100000.0, 200000.0)
xy_bounds of a tile is correct:
tms.xy_bounds(Tile(0, 0, 0))BoundingBox(left=-100000.0, bottom=-100000.0, right=200000.0, top=200000.0)
The first issue is because there is a wrong index in the coordinate computation:
https://github.com/developmentseed/morecantile/blob/main/morecantile/models.py#L1123
https://github.com/developmentseed/morecantile/blob/main/morecantile/models.py#L1158
This should be the same as in xy_bounds, which means:
origin_y + (t.y + 1) * matrix.cellSize * matrix.tileHeight in tms._ul and origin_y + t.y * matrix.cellSize * matrix.tileHeight in tms._lr.
The second issue is, that tms.xy_bbox uses the wrong tile to compute the bounding box of the tms:
https://github.com/developmentseed/morecantile/blob/main/morecantile/models.py#L1262-L1266
This needs to be adjusted to:
if matrix.cornerOfOrigin == "topLeft":
left, top = self._ul(Tile(0, 0, zoom))
right, bottom = self._lr(Tile(matrix.matrixWidth - 1, matrix.matrixHeight - 1, zoom))
else:
left, top = self._ul(Tile(0, matrix.matrixHeight - 1, zoom))
right, bottom = self._lr(Tile(matrix.matrixWidth - 1, 0, zoom))I hope I am not misunderstanding sth. here - please let me know if you require further inputs from my side. Maybe it would be also a good idea to cross-compare bounds in new tests, e.g.: tms._lr(Tile(0, 0, 0)).y == tms.xy_bounds(Tile(0, 0, 0)).bottom
Thank you in advance!