from typing import Tuple, List, Union
from typing_extensions import Literal
[docs]
class Extent:
"""Three-dimensional value-based extent with support for a missing dimension (2D).
"""
def __init__(self, *args, skip_dimension: Literal['x', 1, 'y', 2, 'z', 3, ''] = ''):
self._extents = list()
if len(args) % 2 != 0:
ValueError("An invalid number of arguments were passed to the constructor.")
for i in range(0, len(args), 2):
self._extents.append((float(args[i]), float(args[i + 1])))
if skip_dimension in ('x', 1):
self._extents.insert(0, (0, 0))
elif skip_dimension in ('y', 2):
self._extents.insert(1, (0, 0))
elif skip_dimension in ('z', 3):
self._extents.append((0, 0))
def __eq__(self, other):
return self._extents == other._extents
def __repr__(self, *args, **kwargs):
return "Extent([{:.2f}, {:.2f}] x [{:.2f}, {:.2f}] x [{:.2f}, {:.2f}])".format(self.x_start, self.x_end,
self.y_start, self.y_end,
self.z_start, self.z_end)
def __getitem__(self, item: Union[Literal['x', 'y', 'z', 1, 2, 3]]):
if item == 'x':
return self.x_start, self.x_end
elif item == 'y':
return self.y_start, self.y_end
elif item == 'z':
return self.z_start, self.z_end
return self._extents[item - 1]
@property
def x_start(self) -> float:
"""Gives the absolute extent in x-direction.
"""
return self._extents[0][0]
@property
def y_start(self) -> float:
"""Gives the absolute extent in y-direction.
"""
return self._extents[1][0]
@property
def z_start(self) -> float:
"""Gives the absolute extent in z-direction.
"""
return self._extents[2][0]
@property
def x_end(self) -> float:
"""Gives the absolute extent in x-direction.
"""
return self._extents[0][1]
@property
def y_end(self) -> float:
"""Gives the absolute extent in y-direction.
"""
return self._extents[1][1]
@property
def z_end(self) -> float:
"""Gives the absolute extent in z-direction.
"""
return self._extents[2][1]
[docs]
def as_tuple(self, reduced=True) -> Tuple[float, ...]:
"""Gives the extent in tuple notation (without empty extents).
:param reduced: Whether to leave out empty extents or not.
"""
if reduced:
if self.x_start == self.x_end:
return self.y_start, self.y_end, self.z_start, self.z_end
elif self.y_start == self.y_end:
return self.x_start, self.x_end, self.z_start, self.z_end
elif self.z_start == self.z_end:
return self.x_start, self.x_end, self.y_start, self.y_end
return self.x_start, self.x_end, self.y_start, self.y_end, self.z_start, self.z_end
[docs]
def as_list(self, reduced=True) -> List[float]:
"""Gives the extent in list notation (without empty extents).
:param reduced: Whether to leave out empty extents or not.
"""
return list(self.as_tuple(reduced))