use crate::square::index::GridCoords;
use serde::{Deserialize, Serialize};
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct GridTransform {
pub a: i32,
pub b: i32,
pub c: i32,
pub d: i32,
}
impl GridTransform {
pub const IDENTITY: GridTransform = GridTransform {
a: 1,
b: 0,
c: 0,
d: 1,
};
#[inline]
pub fn apply(&self, i: i32, j: i32) -> GridCoords {
GridCoords {
i: self.a * i + self.b * j,
j: self.c * i + self.d * j,
}
}
pub fn inverse(&self) -> Option<GridTransform> {
let det = self.a * self.d - self.b * self.c;
if det != 1 && det != -1 {
return None;
}
Some(GridTransform {
a: self.d / det,
b: -self.b / det,
c: -self.c / det,
d: self.a / det,
})
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct GridAlignment {
pub transform: GridTransform,
pub translation: [i32; 2],
}
impl GridAlignment {
pub const IDENTITY: GridAlignment = GridAlignment {
transform: GridTransform::IDENTITY,
translation: [0, 0],
};
#[inline]
pub fn map(&self, i: i32, j: i32) -> GridCoords {
let g = self.transform.apply(i, j);
GridCoords {
i: g.i + self.translation[0],
j: g.j + self.translation[1],
}
}
pub fn inverse(&self) -> Option<GridAlignment> {
let inv = self.transform.inverse()?;
let [tx, ty] = self.translation;
let g = inv.apply(-tx, -ty);
Some(GridAlignment {
transform: inv,
translation: [g.i, g.j],
})
}
}
pub const GRID_TRANSFORMS_D4: [GridTransform; 8] = [
GridTransform {
a: 1,
b: 0,
c: 0,
d: 1,
},
GridTransform {
a: 0,
b: 1,
c: -1,
d: 0,
},
GridTransform {
a: -1,
b: 0,
c: 0,
d: -1,
},
GridTransform {
a: 0,
b: -1,
c: 1,
d: 0,
},
GridTransform {
a: -1,
b: 0,
c: 0,
d: 1,
},
GridTransform {
a: 1,
b: 0,
c: 0,
d: -1,
},
GridTransform {
a: 0,
b: 1,
c: 1,
d: 0,
},
GridTransform {
a: 0,
b: -1,
c: -1,
d: 0,
},
];