use super::transform::AffineTransform;
pub type Vector2 = [f32; 2];
pub const ZERO: Vector2 = [0.0, 0.0];
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Axis {
X,
Y,
}
impl Axis {
pub fn counter(self) -> Self {
match self {
Axis::X => Axis::Y,
Axis::Y => Axis::X,
}
}
}
pub fn axis_oriented(a: f32, b: f32, main_axis: Axis) -> Vector2 {
match main_axis {
Axis::X => [a, b],
Axis::Y => [b, a],
}
}
pub fn is_zero(v: Vector2) -> bool {
v[0] == 0.0 && v[1] == 0.0
}
pub fn add(vectors: &[Vector2]) -> Vector2 {
let mut result = [0.0f32, 0.0f32];
for v in vectors {
result[0] += v[0];
result[1] += v[1];
}
result
}
pub fn sub(vectors: &[Vector2]) -> Vector2 {
if vectors.is_empty() {
return [0.0, 0.0];
}
let mut iter = vectors.iter();
let mut result = *iter.next().unwrap();
for v in iter {
result[0] -= v[0];
result[1] -= v[1];
}
result
}
pub trait IntoVector2 {
fn into_vector2(self) -> Vector2;
}
impl IntoVector2 for [f32; 2] {
fn into_vector2(self) -> Vector2 {
self
}
}
impl IntoVector2 for (f32, f32) {
fn into_vector2(self) -> Vector2 {
[self.0, self.1]
}
}
impl IntoVector2 for f32 {
fn into_vector2(self) -> Vector2 {
[self, self]
}
}
pub fn quantize(vector: Vector2, step: impl IntoVector2) -> Vector2 {
let step = step.into_vector2();
[
crate::quantize(vector[0], step[0]),
crate::quantize(vector[1], step[1]),
]
}
pub fn multiply(vectors: &[Vector2]) -> Vector2 {
if vectors.is_empty() {
return [1.0, 1.0];
}
let mut result = [1.0f32, 1.0f32];
for v in vectors {
result[0] *= v[0];
result[1] *= v[1];
}
result
}
pub fn invert(v: Vector2) -> Vector2 {
[-v[0], -v[1]]
}
pub fn angle(a: Vector2, b: Vector2) -> f32 {
let radians = (b[1] - a[1]).atan2(b[0] - a[0]);
let degrees = radians.to_degrees();
(degrees + 360.0) % 360.0
}
pub fn rotate(v: Vector2, angle: f32) -> Vector2 {
let rad = angle.to_radians();
let (sin, cos) = rad.sin_cos();
[v[0] * cos - v[1] * sin, v[0] * sin + v[1] * cos]
}
pub fn intersects(a: Vector2, b: Vector2) -> bool {
a[1] >= b[0] && b[1] >= a[0]
}
pub fn intersection(a: Vector2, b: Vector2) -> Option<Vector2> {
let start = a[0].max(b[0]);
let end = a[1].min(b[1]);
if start > end {
None
} else {
Some([start, end])
}
}
pub fn min(vectors: &[Vector2]) -> Vector2 {
let mut result = [f32::INFINITY, f32::INFINITY];
for v in vectors {
if v[0] < result[0] {
result[0] = v[0];
}
if v[1] < result[1] {
result[1] = v[1];
}
}
result
}
pub fn max(vectors: &[Vector2]) -> Vector2 {
let mut result = [f32::NEG_INFINITY, f32::NEG_INFINITY];
for v in vectors {
if v[0] > result[0] {
result[0] = v[0];
}
if v[1] > result[1] {
result[1] = v[1];
}
}
result
}
pub fn clamp(v: Vector2, min: Vector2, max: Vector2) -> Vector2 {
[v[0].max(min[0]).min(max[0]), v[1].max(min[1]).min(max[1])]
}
pub fn distance(a: Vector2, b: Vector2) -> f32 {
((b[0] - a[0]).powi(2) + (b[1] - a[1]).powi(2)).sqrt()
}
pub fn transform(v: Vector2, t: &AffineTransform) -> Vector2 {
let [[a, c, tx], [b, d, ty]] = t.matrix;
[a * v[0] + c * v[1] + tx, b * v[0] + d * v[1] + ty]
}
pub fn identical(a: Vector2, b: Vector2) -> bool {
a[0] == b[0] && a[1] == b[1]
}