use crate::{Extent, Position, Stride};
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
#[must_use]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Region<P, E, const D: usize> {
pub pos: Position<P, D>,
pub ext: Extent<E, D>,
}
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
pub type Region1<P, E> = Region<P, E, 1>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
pub type Region2<P, E> = Region<P, E, 2>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
pub type Region3<P, E> = Region<P, E, 3>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
pub type RegionS<T, const D: usize> = Region<T, T, D>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
pub type RegionS1<T> = RegionS<T, 1>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
pub type RegionS2<T> = RegionS<T, 2>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
pub type RegionS3<T> = RegionS<T, 3>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_meta!{location("geom/metric")}]
#[must_use]
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RegionStrided<P, E, const D: usize> {
pub region: Region<P, E, D>,
pub stride: Stride<E, D>,
}
#[rustfmt::skip]
impl<P, E, const D: usize> Region<P, E, D> {
pub const fn new(pos: Position<P, D>, ext: Extent<E, D>) -> Self { Self { pos, ext } }
pub fn from_parts<PI, EI>(pos: PI, ext: EI) -> Self
where
PI: Into<Position<P, D>>,
EI: Into<Extent<E, D>>,
{
Self::new(pos.into(), ext.into())
}
}
impl<P, E> From<((P, P), (E, E))> for Region<P, E, 2> {
fn from(((x, y), (w, h)): ((P, P), (E, E))) -> Self {
Self {
pos: Position::from((x, y)),
ext: Extent::from((w, h)),
}
}
}
impl<P, E> From<((P, P, P), (E, E, E))> for Region<P, E, 3> {
fn from(((x, y, z), (w, h, d)): ((P, P, P), (E, E, E))) -> Self {
Self {
pos: Position::from((x, y, z)),
ext: Extent::from((w, h, d)),
}
}
}
impl<P, E, const D: usize> From<(Position<P, D>, Extent<E, D>)> for Region<P, E, D> {
fn from(from: (Position<P, D>, Extent<E, D>)) -> Self {
Self::new(from.0, from.1)
}
}
impl<P, E, const D: usize> From<(Extent<E, D>, Position<P, D>)> for Region<P, E, D> {
fn from(from: (Extent<E, D>, Position<P, D>)) -> Self {
Self::new(from.1, from.0)
}
}
#[rustfmt::skip]
impl<P: Copy, E: Copy> Region2<P, E> {
#[must_use]
pub const fn x(self) -> P { self.pos.x() }
#[must_use]
pub const fn y(self) -> P { self.pos.y() }
#[must_use]
pub const fn w(self) -> E { self.ext.w() }
#[must_use]
pub const fn h(self) -> E { self.ext.h() }
}
#[rustfmt::skip]
impl<P: Copy, E: Copy> Region3<P, E> {
#[must_use]
pub const fn x(self) -> P { self.pos.x() }
#[must_use]
pub const fn y(self) -> P { self.pos.y() }
#[must_use]
pub const fn z(self) -> P { self.pos.z() }
#[must_use]
pub const fn w(self) -> E { self.ext.w() }
#[must_use]
pub const fn h(self) -> E { self.ext.h() }
#[must_use]
pub const fn d(self) -> E { self.ext.d() }
}
impl<P, E, const D: usize> Region<P, E, D> {
pub fn map_pos<P2>(self, f: impl FnMut(P) -> P2) -> Region<P2, E, D> {
Region::new(self.pos.map(f), self.ext)
}
pub fn map_ext<E2>(self, f: impl FnMut(E) -> E2) -> Region<P, E2, D> {
Region::new(self.pos, self.ext.map(f))
}
pub fn map<P2, E2>(
self,
fpos: impl FnMut(P) -> P2,
fext: impl FnMut(E) -> E2,
) -> Region<P2, E2, D> {
Region::new(self.pos.map(fpos), self.ext.map(fext))
}
pub fn try_map_pos<P2, X>(
self,
f: impl FnMut(P) -> Result<P2, X>,
) -> Result<Region<P2, E, D>, X> {
Ok(Region::new(self.pos.try_map(f)?, self.ext))
}
pub fn try_map_ext<E2, X>(
self,
f: impl FnMut(E) -> Result<E2, X>,
) -> Result<Region<P, E2, D>, X> {
Ok(Region::new(self.pos, self.ext.try_map(f)?))
}
pub fn try_map<P2, E2, X>(
self,
fpos: impl FnMut(P) -> Result<P2, X>,
fext: impl FnMut(E) -> Result<E2, X>,
) -> Result<Region<P2, E2, D>, X> {
Ok(Region::new(self.pos.try_map(fpos)?, self.ext.try_map(fext)?))
}
pub fn map_into<P2, E2>(self) -> Region<P2, E2, D>
where
P2: From<P>,
E2: From<E>,
{
self.map(P2::from, E2::from)
}
pub fn try_map_into<P2, E2, X>(self) -> Result<Region<P2, E2, D>, X>
where
P2: TryFrom<P, Error = X>,
E2: TryFrom<E, Error = X>,
{
self.try_map(P2::try_from, E2::try_from)
}
}