Skip to content

Commit

Permalink
BoundingBox class
Browse files Browse the repository at this point in the history
  • Loading branch information
ecomodeller committed Dec 14, 2024
1 parent 40b2309 commit 8f6a8f6
Showing 1 changed file with 36 additions and 39 deletions.
75 changes: 36 additions & 39 deletions mikeio/spatial/_grid_geometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from functools import cached_property
from pathlib import Path
import warnings
from typing import Any, Sequence, TYPE_CHECKING, overload
from typing import Any, Sequence, TYPE_CHECKING, Sized, overload
from dataclasses import dataclass
import numpy as np

Expand Down Expand Up @@ -431,7 +431,10 @@ def __init__(
y0: float = 0.0,
dy: float | None = None,
ny: int | None = None,
bbox: tuple[float, float, float, float] | None = None,
bbox: BoundingBox
| Sequence[float]
| tuple[float, float, float, float]
| None = None,
projection: str = "LONG/LAT",
origin: tuple[float, float] | None = None,
orientation: float = 0.0,
Expand Down Expand Up @@ -520,7 +523,7 @@ def _is_rotated(self) -> Any:

def _create_in_bbox(
self,
bbox: tuple[float, float, float, float],
bbox: BoundingBox | tuple[float, float, float, float] | Sequence[float],
dx: float | tuple[float, float] | None = None,
dy: float | None = None,
nx: int | None = None,
Expand All @@ -547,10 +550,10 @@ def _create_in_bbox(
in which case the value will be inferred
"""
left, bottom, right, top = self._parse_bbox(bbox)
box = self._parse_bbox(bbox)

xr = right - left # dx too large
yr = top - bottom # dy too large
xr = box.right - box.left # dx too large
yr = box.top - box.bottom # dy too large

if (dx is None and dy is None) and (nx is None and ny is None):
if xr <= yr:
Expand All @@ -567,32 +570,23 @@ def _create_in_bbox(
dx, dy = dx
dy = dx if dy is None else dy

self._x0, self._dx, self._nx = self._create_in_bbox_1d("x", left, right, dx, nx)
self._y0, self._dy, self._ny = self._create_in_bbox_1d("y", bottom, top, dy, ny)
self._x0, self._dx, self._nx = self._create_in_bbox_1d(
"x", box.left, box.right, dx, nx
)
self._y0, self._dy, self._ny = self._create_in_bbox_1d(
"y", box.bottom, box.top, dy, ny
)

@staticmethod
def _parse_bbox(
bbox: tuple[float, float, float, float],
) -> tuple[float, float, float, float]:
left = bbox[0]
bottom = bbox[1]
right = bbox[2]
top = bbox[3]

if left > right:
raise (
ValueError(
f"Invalid x axis, left: {left} must be smaller than right: {right}"
)
)

if bottom > top:
raise (
ValueError(
f"Invalid y axis, bottom: {bottom} must be smaller than top: {top}"
)
)
return left, bottom, right, top
bbox: BoundingBox | Sequence[float],
) -> BoundingBox:
if isinstance(bbox, BoundingBox):
return bbox
elif isinstance(bbox, Sequence) and len(bbox) == 4:
return BoundingBox(*bbox)
else:
raise ValueError("bbox must be a BoundingBox or a tuple of length 4")

@staticmethod
def _create_in_bbox_1d(
Expand Down Expand Up @@ -876,21 +870,24 @@ def _xy_to_index(self, xy: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
return ii, jj

def _bbox_to_index(
self, bbox: tuple[float, float, float, float] | BoundingBox
self, values: BoundingBox | tuple[float, float, float, float]
) -> tuple[range, range]:
"""Find subarea within this geometry."""
if not (len(bbox) == 4):
raise ValueError(
"area most be a bounding box of coordinates e.g. area=(-10.0, 10.0 20.0, 30.0)"
)

x0, y0, x1, y1 = bbox
if x0 > self.x[-1] or y0 > self.y[-1] or x1 < self.x[0] or y1 < self.y[0]:
match values:
case BoundingBox():
bbox = values
case left, bottom, right, top:
bbox = BoundingBox(left, bottom, right, top)
case _:
raise ValueError(
"area most be a bounding box of coordinates e.g. area=(-10.0, 10.0 20.0, 30.0)"
)
if not bbox.overlaps(self.bbox):
raise ValueError("area is outside grid")

mask = (self.x >= x0) & (self.x <= x1)
mask = (self.x >= bbox.left) & (self.x <= bbox.right)
ii = np.where(mask)[0]
mask = (self.y >= y0) & (self.y <= y1)
mask = (self.y >= bbox.bottom) & (self.y <= bbox.top)
jj = np.where(mask)[0]

i = range(ii[0], ii[-1] + 1)
Expand Down

0 comments on commit 8f6a8f6

Please sign in to comment.