use std::cmp::Ordering;
use std::ops::{Deref, DerefMut};
use super::{GridCoord, GridPoint2, Root, RootIndex};
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
pub struct GridPoint3 {
pub rxy: GridPoint2,
pub z: GridCoord,
}
impl GridPoint3 {
pub fn new(root: Root, x: GridCoord, y: GridCoord, z: GridCoord) -> GridPoint3 {
GridPoint3 {
rxy: GridPoint2::new(root, x, y),
z: z,
}
}
pub fn with_root(&self, new_root_index: RootIndex) -> Self {
let mut new_point = *self;
new_point.rxy.root.index = new_root_index;
new_point
}
pub fn with_x(&self, new_x: GridCoord) -> Self {
let mut new_point = *self;
new_point.rxy.x = new_x;
new_point
}
pub fn with_y(&self, new_y: GridCoord) -> Self {
let mut new_point = *self;
new_point.rxy.y = new_y;
new_point
}
pub fn with_z(&self, new_z: GridCoord) -> Self {
let mut new_point = *self;
new_point.z = new_z;
new_point
}
}
#[derive(Default, Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub struct PosInOwningRoot {
pos: GridPoint3,
}
impl Into<GridPoint3> for PosInOwningRoot {
fn into(self) -> GridPoint3 {
self.pos
}
}
impl PosInOwningRoot {
pub fn new(pos: GridPoint3, resolution: [GridCoord; 2]) -> PosInOwningRoot {
debug_assert!(pos.z >= 0);
let end_x = resolution[0];
let end_y = resolution[1];
let half_y = resolution[1] / 2;
let pos_in_owning_root = if pos.x == 0 && pos.y == 0 {
GridPoint3::new(
0.into(),
0,
0,
pos.z,
)
} else if pos.x == end_x && pos.y == end_y {
GridPoint3::new(
4.into(),
end_x,
end_y,
pos.z,
)
} else if pos.y == 0 {
GridPoint3::new(pos.root.next_west(), 0, pos.x, pos.z)
} else if pos.x == end_x && pos.y < half_y {
GridPoint3::new(pos.root.next_west(), 0, half_y + pos.y, pos.z)
} else if pos.x == end_x {
GridPoint3::new(pos.root.next_west(), pos.y - half_y, end_y, pos.z)
} else {
pos
};
PosInOwningRoot { pos: pos_in_owning_root }
}
pub fn set_z(&mut self, new_z: GridCoord) {
self.pos.z = new_z;
}
}
impl<'a> PosInOwningRoot {
pub fn pos(&'a self) -> &'a GridPoint3 {
&self.pos
}
}
impl Deref for GridPoint3 {
type Target = GridPoint2;
fn deref(&self) -> &GridPoint2 {
&self.rxy
}
}
impl DerefMut for GridPoint3 {
fn deref_mut(&mut self) -> &mut GridPoint2 {
&mut self.rxy
}
}
pub fn semi_arbitrary_compare(a: &GridPoint3, b: &GridPoint3) -> Ordering {
let cmp_root = a.root.index.cmp(&b.root.index);
if cmp_root != Ordering::Equal {
return cmp_root;
}
let cmp_z = a.z.cmp(&b.z);
if cmp_z != Ordering::Equal {
return cmp_z;
}
let cmp_y = a.y.cmp(&b.y);
if cmp_y != Ordering::Equal {
return cmp_y;
}
a.x.cmp(&b.x)
}