Files
fdtd-coremem/crates/coremem/src/geom/units.rs

267 lines
6.5 KiB
Rust

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<f32>);
impl Meters {
pub fn new<R: ToFloat>(x: R, y: R, z: R) -> Self {
Self(Vec3::new(x.to_f32(), y.to_f32(), z.to_f32()))
}
pub fn new_x<R: ToFloat>(x: R) -> Self {
Self::new(x.to_f32(), 0.0, 0.0)
}
pub fn new_y<R: ToFloat>(y: R) -> Self {
Self::new(0.0, y.to_f32(), 0.0)
}
pub fn new_z<R: ToFloat>(z: R) -> Self {
Self::new(0.0, 0.0, z.to_f32())
}
pub fn with_x<R: ToFloat>(&self, x: R) -> Self {
Self::new(x.to_f32(), self.y(), self.z())
}
pub fn with_y<R: ToFloat>(&self, y: R) -> Self {
Self::new(self.x(), y.to_f32(), self.z())
}
pub fn with_z<R: ToFloat>(&self, z: R) -> Self {
Self::new(self.x(), self.y(), z.to_f32())
}
/// Rotate `rad` radians around the +z axis
pub fn rotate_z<R: ToFloat>(&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<f32>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Add<Meters> 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<Meters> for Meters {
type Output = Self;
fn sub(self, other: Self) -> Self {
Self(self.0 - other.0)
}
}
impl Div<f32> for Meters {
type Output = Meters;
fn div(self, s: f32) -> Self {
Self(self.0/s)
}
}
impl Mul<f32> 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<H: Hasher>(&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<Vec3u> for Index {
fn into(self) -> Vec3u {
self.0
}
}
impl From<Vec3u> 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<Index> for Index {
type Output = Self;
fn add(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
impl Sub<Index> for Index {
type Output = Self;
fn sub(self, other: Self) -> Self {
Self(self.0 - other.0)
}
}
impl Div<u32> for Index {
type Output = Index;
fn div(self, s: u32) -> Self {
Self(self.0/s)
}
}
impl Mul<u32> 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)
}
}