3

I would like to rotate a bounding box given a particular angle.

Here is what i get :

enter image description here

In this example the rotated bounding box does not contain the AOI blue polygon which is an issue for me. The green bounding box is oriented south-north and I can get the angle with which I want to rotate it.

The AOI coordinates are in (lat, lon) degrees but I would like to put a margin in meters on the 4 sides of my rotated bounding box. I guess the best way is to reproject in 3857?

The AOI could be a polygon situated everywhere on the globe.

enter image description here

enter image description here

I first thought to buffer little by little the orange bounding box until the AOI would be contained inside but getting the correct margin would be difficult using this method.

The example :

import shapely

a = [0, 0]
b = [1, 1]
c = [3, 1.5]
d = [1, 2]
e = [0, 1.5]
pol = shapely.geometry.Polygon([a, b, c, d, e])

bounds = shapely.geometry.box(*pol.bounds)
bounds_rotated = shapely.affinity.rotate(bounds, 30)
7
  • Have you tried buffering an oriented bounding box instead of a regular bounding box?
    – Kalak
    Jan 17 at 14:08
  • Yes but the margin will not be the same on each side if i do this method. Jan 17 at 14:10
  • pol.buffer(margin).minimum_rotated_rectangle? Jan 17 at 14:11
  • 2
    No, do not use Web Mercator (EPSG:3857) for this. Web Mercator is useless for distance, because the poles are infinitely far from the Equator. You cannot rotate angular units as if they were Cartesian, because that does not work (as you have demonstrated). Even if you project decimal degrees into a locally appropriate projection, rotate there, and deproject, it's unlikely to "look" correct due to the oddities of Cartesian transformation of angular units.
    – Vince
    Jan 17 at 14:58
  • 1
    The crs problem can be solved using .estimate_utm_crs. Groupby some unique id and for each subframe returned - reproject to the estimated utm
    – BERA
    Jan 17 at 18:27

2 Answers 2

2

For your exact example you can union the original polygon and the rotated, then .minimum_rotated_rectangle the union.

import shapely.affinity
import geopandas as gpd

a = [0, 0]
b = [1, 1]
c = [3, 1.5]
d = [1, 2]
e = [0, 1.5]
pol = shapely.geometry.Polygon([a, b, c, d, e])
bounds = shapely.geometry.box(*pol.bounds)
bounds_rotated = shapely.affinity.rotate(bounds, 30)
bounds_rotated_2 = pol.union(bounds_rotated).minimum_rotated_rectangle

df = gpd.GeoDataFrame(geometry=[pol, bounds, bounds_rotated, bounds_rotated_2])
df["color"] = ["blue", "green", "orange", "red"]
df.boundary.plot(color=df["color"])

enter image description here

1
  • 1
    Thanks, it's not exactly what i was looking for but it makes the job. Jan 18 at 8:55
0

here a solution that can fit :

import shapely

a = [0, 0]
b = [1, 1]
c = [3, 1.5]
d = [1, 2]
e = [0, 1.5]
pol = shapely.geometry.Polygon([a, b, c, d, e])
circle = shapely.minimum_bounding_circle(pol)
bounds_circle = shapely.geometry.box(*circle.bounds)

plt.plot(*circle.exterior.coords.xy)
plt.plot(*bounds_circle.exterior.coords.xy)
plt.plot(*pol.exterior.coords.xy)
plt.show()
import numpy as np
for i in np.arange(0, 360):
    a = shapely.affinity.rotate(bounds_circle, i)
    print(a.contains(pol))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.