La pregunta tiene poco o ningún sentido si no es en coordenadas proyectadas, porque un "cuadro delimitador" e incluso un rumbo constante tienen significados ambiguos en un esferoide. En el plano proyectado, sólo hay que girar los puntos para que el rodamiento sea horizontal o vertical. La búsqueda de la caja delimitadora se realiza entonces de la forma habitual (obteniendo los valores extremos de las coordenadas). La rotación de esta figura hacia atrás termina el trabajo.
Para mantener una alta precisión, gire los puntos alrededor de algún lugar central (o cercano).
Si imagináramos un SIG que soportara las operaciones básicas de (a) rotar figuras y (b) encontrar cajas delimitadoras -lo que hace la mayoría de ellos-, su solución sería la siguiente:
BoundingBox = Rotate(Extent(Rotate(points, bearing)), -bearing)
donde
Rotate(p, a)
gira una característica p
por una cantidad a
y
Extent(p)
devuelve la extensión (rectangular) de una característica.
Aquí hay un ejemplo que muestra las situaciones giradas y originales:
R
(que es fácilmente trasladable a Python o a cualquier otra plataforma que soporte operaciones matriciales básicas). La mayor parte se limita a generar datos de muestra y a trazar los resultados.
#
# Sample data (looking like those of the question,
# with typical ranges of projected coordinates).
#
xy <- cbind(1:4 + 200000, c(0,5,0,4) + 4000000)
bearing <- 45 * pi/180 # Radians east of north
#
# Helper functions.
#
rotate <- function(xy, a, origin=c(0,0)) {
c <- cos(a); s <- sin(a)
return(t(matrix(c(c, -s, s, c), 2) %*% (t(xy) - origin) + origin))
}
extent <- function(xy) {
e <- apply(xy, 2, range)
return(matrix(c(e[1,1], e[2,1], e[2,1], e[1,1],
e[1,2], e[1,2], e[2,2], e[2,2]), ncol=2, byrow=FALSE))
}
#
# Compute the oriented bounding box.
#
center <- apply(xy, 2, mean)
bb <- rotate(extent(rotate(xy, bearing, center)), -bearing, center)
#
# Display the points and their oriented bounding box.
#
plot(rbind(bb, xy), type="n", asp=1, xlab="X", ylab="Y", main="Solution")
polygon(bb, col="#f0f0f0")
points(xy, pch=19, col="Red")