transform_bounds does not appear to support bbox crossing the antimeridian
See original GitHub issueIssue Description
example (EPSG:32601)
Upper Left (365474, 7696071)
Lower Left (365474, 7591951)
Upper Right (477094, 7696071)
Lower Right (477094, 7591951)
rasterio. warp.transform_bounds
return flattened bounds.
transform_bounds('EPSG:32601', 'EPSG:4326', 365474, 7591951, 477094, 7696071)
-> (-179.90689695793938, 68.40816857051695, 179.96969316611757, 69.37306968939305)
correct bounds
(179.5819541972332, 68.40816857051695, -177.55854062377162, 69.37306968939305)
It seems to need checking transformed points is crossing the antimeridian. For example, like this.
def is_clockwise(xs, ys):
if len(xs) != len(ys):
raise TransformError("xs and ys arrays must be the same length")
area = 0
if len(xs) > 2:
if xs[0] == xs[-1] and ys[0] == ys[-1]:
length = len(xs) - 1
else:
length = len(xs)
for i in range(length - 1):
area = area + xs[i] * ys[i+1] - ys[i] * xs[i+1]
area = area + xs[length - 1] * ys[0] - ys[length - 1] * xs[0]
return area >= 0
def transform_bounds(
src_crs,
dst_crs,
left,
bottom,
right,
top,
densify_pts=21):
if densify_pts < 0:
raise ValueError('densify parameter must be >= 0')
if src_crs == dst_crs:
return [left, bottom, right, top]
in_xs = []
in_ys = []
if densify_pts > 0:
densify_factor = 1.0 / float(densify_pts + 1)
# left_bottom to right_bottom
in_xs.extend(
left + np.arange(1, densify_pts + 1, dtype=np.float64) *
((right - left) * densify_factor)
)
in_ys.extend([bottom] * densify_pts)
# right_bottom to right_top
in_xs.extend([right] * (densify_pts + 2))
in_ys.extend(
bottom + np.arange(0, densify_pts + 2, dtype=np.float64) *
((top - bottom) * densify_factor)
)
# right_top to left_top
in_xs.extend(
right + np.arange(1, densify_pts + 1, dtype=np.float64) *
((left - right) * densify_factor)
)
in_ys.extend([top] * densify_pts)
# left_top to left_bottom
in_xs.extend([left] * (densify_pts + 2))
in_ys.extend(
top + np.arange(0, densify_pts + 2, dtype=np.float64) *
((bottom - top) * densify_factor)
)
else:
in_xs = np.array(left, right, right, left,left)
in_ys = np.array(bottom, bottom, top, top, bottom)
xs, ys = transform(src_crs, dst_crs, in_xs, in_ys)
if dst_crs == 'EPSG:4326' and not is_clockwise(xs, ys):
xs = [x + 360 if x < 0 else x for x in xs]
return (min(xs), min(ys), max(xs) - 360, max(ys))
return (min(xs), min(ys), max(xs), max(ys))
cogeo.bounds
, cogeo.get_zooms
, reader.part
, etc., a lot of methods to create tile are affected.
Couldn’t we improve?
Issue Analytics
- State:
- Created 2 years ago
- Comments:9 (5 by maintainers)
Top Results From Across the Web
bounding boxes crossing the antimeridian are not rendered ...
Bounding boxes which cross the anti-meridian (i.e. international date line) do not show up correctly. Solr requires east and west values to ...
Read more >gdal - Get a bounding box of a geometry that crosses the ...
It has no notion of SRS / antimeridian / etc. ... box from a geometry that crosses the antimeridian using OGR/GDAL is by...
Read more >Wrapping lines/polygons across the antimeridian in Leaflet.js
My solution is not perfect, as I will show below, but it is a good start. Here is the code: function addLineToMap(start, end)...
Read more >Antimeridian Crossing with Python and Shapely
Splitting or cutting GeoJSON polygons crossing the antimeridian (180th meridian or international date line) in Python with Shapely.
Read more >rasterio Documentation - Read the Docs
Before Rasterio there was one Python option for accessing the many different kind of raster data files used in the GIS.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Alright @yonda-yonda, first thanks for starting the PR I really appreciate it.
Working with bounds, crs and antimeridan is definitely not an easy task. I’d like for us to take a step back and define clearly:
this is not really defined anywhere in the docs, but yeah
bounds
should always be in WGS84.Feel free to start a PR to improve
tile_exits
🙏