use coremem_cross::real::ToFloat; use coremem_cross::vec::{Vec3, Vec3u}; use serde::{Serialize, Deserialize}; use std::fmt::{self, Display}; use std::cmp::Ordering; use std::ops::{Add, Deref, Div, Mul, Neg, Sub}; use std::hash::{Hash, Hasher}; pub trait Coord: Copy + Clone { fn to_meters(&self, feature_size: f32) -> Meters; /// rounds fn to_index(&self, feature_size: f32) -> Index; fn to_index_ceil(&self, feature_size: f32) -> Index; fn to_index_floor(&self, feature_size: f32) -> Index; fn from_meters(other: Meters, feature_size: f32) -> Self; fn from_index(other: Index, feature_size: f32) -> Self; fn from_either(i: Index, m: Meters) -> Self; } #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize)] pub struct Meters(pub Vec3); impl Meters { pub fn new(x: R, y: R, z: R) -> Self { Self(Vec3::new(x.to_f32(), y.to_f32(), z.to_f32())) } pub fn new_x(x: R) -> Self { Self::new(x.to_f32(), 0.0, 0.0) } pub fn new_y(y: R) -> Self { Self::new(0.0, y.to_f32(), 0.0) } pub fn new_z(z: R) -> Self { Self::new(0.0, 0.0, z.to_f32()) } pub fn with_x(&self, x: R) -> Self { Self::new(x.to_f32(), self.y(), self.z()) } pub fn with_y(&self, y: R) -> Self { Self::new(self.x(), y.to_f32(), self.z()) } pub fn with_z(&self, z: R) -> Self { Self::new(self.x(), self.y(), z.to_f32()) } /// Rotate `rad` radians around the +z axis pub fn rotate_z(&self, rad: R) -> Self { Self(self.0.with_xy(self.0.xy().rotate(rad.to_f32()))) } } impl Coord for Meters { fn to_meters(&self, _feature_size: f32) -> Meters { *self } fn to_index(&self, feature_size: f32) -> Index { Index((self.0 / feature_size).round().into()) } fn to_index_ceil(&self, feature_size: f32) -> Index { Index((self.0 / feature_size).ceil().into()) } fn to_index_floor(&self, feature_size: f32) -> Index { Index((self.0 / feature_size).floor().into()) } fn from_meters(other: Meters, _feature_size: f32) -> Self { other } fn from_index(other: Index, feature_size: f32) -> Self { other.to_meters(feature_size) } fn from_either(_i: Index, m: Meters) -> Self { m } } impl Deref for Meters { type Target = Vec3; fn deref(&self) -> &Self::Target { &self.0 } } impl Add for Meters { type Output = Self; fn add(self, other: Self) -> Self { Self(self.0 + other.0) } } impl Neg for Meters { type Output = Self; fn neg(self) -> Self { Self(-self.0) } } impl Sub for Meters { type Output = Self; fn sub(self, other: Self) -> Self { Self(self.0 - other.0) } } impl Div for Meters { type Output = Meters; fn div(self, s: f32) -> Self { Self(self.0/s) } } impl Mul for Meters { type Output = Meters; fn mul(self, s: f32) -> Self { Self(self.0*s) } } impl Display for Meters { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Meters{}", self.0) } } #[derive(Copy, Clone, Debug, Default, PartialEq, PartialOrd, Serialize, Deserialize)] pub struct OrdMeters(pub Meters); impl Deref for OrdMeters { type Target = Meters; fn deref(&self) -> &Self::Target { &self.0 } } impl Ord for OrdMeters { fn cmp(&self, other: &Self) -> Ordering { self.partial_cmp(other).unwrap() } } impl Eq for OrdMeters { } impl Hash for OrdMeters { fn hash(&self, state: &mut H) { let bits: (u32, u32, u32) = unsafe { std::mem::transmute(*self) }; bits.hash(state) } } #[derive(Copy, Clone, Debug, Default, Hash, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)] pub struct Index(pub Vec3u); impl Index { pub fn new(x: u32, y: u32, z: u32) -> Self { Self((x, y, z).into()) } pub fn unit() -> Self { Self::new(1, 1, 1) } pub fn to_tuple(&self) -> (u32, u32, u32) { (self.0.x(), self.0.y(), self.0.z()) } pub fn from_tuple(xyz: (u32, u32, u32)) -> Self { Self::new(xyz.0, xyz.1, xyz.2) } pub fn volume(&self) -> u64 { (self.0.x() as u64) * (self.0.y() as u64) * (self.0.z() as u64) } pub fn left(&self) -> Self { Self::new(self.x() - 1, self.y(), self.z()) } pub fn right(&self) -> Self { Self::new(self.x() + 1, self.y(), self.z()) } pub fn up(&self) -> Self { Self::new(self.x(), self.y() - 1, self.z()) } pub fn down(&self) -> Self { Self::new(self.x(), self.y() + 1, self.z()) } pub fn out(&self) -> Self { Self::new(self.x(), self.y(), self.z() - 1) } pub fn in_(&self) -> Self { Self::new(self.x(), self.y(), self.z() + 1) } pub fn cardinal_neighbors(&self) -> [Self; 6] { [self.left(), self.right(), self.up(), self.down(), self.out(), self.in_()] } } impl Into for Index { fn into(self) -> Vec3u { self.0 } } impl From for Index { fn from(v: Vec3u) -> Self { Self(v) } } impl Coord for Index { fn to_meters(&self, feature_size: f32) -> Meters { Meters(Vec3::from(self.0) * feature_size) } fn to_index(&self, _feature_size: f32) -> Index { *self } fn to_index_ceil(&self, _feature_size: f32) -> Index { *self } fn to_index_floor(&self, _feature_size: f32) -> Index { *self } fn from_meters(other: Meters, feature_size: f32) -> Self { other.to_index(feature_size) } fn from_index(other: Index, _feature_size: f32) -> Self { other } fn from_either(i: Index, _m: Meters) -> Self { i } } impl Deref for Index { type Target = Vec3u; fn deref(&self) -> &Vec3u { &self.0 } } impl Add for Index { type Output = Self; fn add(self, other: Self) -> Self { Self(self.0 + other.0) } } impl Sub for Index { type Output = Self; fn sub(self, other: Self) -> Self { Self(self.0 - other.0) } } impl Div for Index { type Output = Index; fn div(self, s: u32) -> Self { Self(self.0/s) } } impl Mul for Index { type Output = Index; fn mul(self, s: u32) -> Self { Self(self.0*s) } } impl Display for Index { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Index{}", self.0) } }