#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Vec2<T> {
pub x: T,
pub y: T,
}
impl<T> Vec2<T> {
pub fn new(x: T, y: T) -> Self {
Vec2 { x, y }
}
pub fn into_tuple(self) -> (T, T) {
(self.x, self.y)
}
}
impl<T> From<(T, T)> for Vec2<T> {
fn from(value: (T, T)) -> Self {
Vec2::new(value.0, value.1)
}
}
macro_rules! div_impl {
($($t:ty)*) => ($(
impl std::ops::Div<$t> for Vec2<$t> {
type Output = Vec2<$t>;
fn div(self, other: $t) -> Self::Output {
Vec2::new(self.x / other, self.y / other)
}
}
)*)
}
div_impl! { f32 isize }
macro_rules! add_impl {
($($t:ty)*) => ($(
impl std::ops::Add for Vec2<$t> {
type Output = Vec2<$t>;
fn add(self, other: Self) -> Self::Output {
Vec2::new(self.x + other.x, self.y + other.y)
}
}
)*)
}
add_impl! { f32 isize }
macro_rules! subtract_impl {
($($t:ty)*) => ($(
impl std::ops::Sub for Vec2<$t> {
type Output = Vec2<$t>;
fn sub(self, other: Self) -> Self::Output {
Vec2::new(self.x - other.x, self.y - other.y)
}
}
)*)
}
subtract_impl! { f32 isize }
pub trait AverageExt: Iterator {
fn average<M>(self) -> M
where
M: Average<Self::Item>,
Self: Sized,
{
M::average(self)
}
}
impl<I: Iterator> AverageExt for I {}
pub trait Average<A = Self> {
fn average<I>(iter: I) -> Self
where
I: Iterator<Item = A>;
}
impl Average for Vec2<f32> {
fn average<I>(iter: I) -> Self
where
I: Iterator<Item = Vec2<f32>>,
{
let mut sum = Vec2::new(0.0, 0.0);
let mut count: usize = 0;
for v in iter {
sum = sum + v;
count += 1;
}
if count > 0 {
sum / (count as f32)
} else {
sum
}
}
}
impl<'a> Average<&'a Vec2<f32>> for Vec2<f32> {
fn average<I>(iter: I) -> Self
where
I: Iterator<Item = &'a Vec2<f32>>,
{
iter.copied().average()
}
}
#[cfg(feature = "glam")]
impl Into<glam::Vec2> for Vec2<f32> {
fn into(self) -> glam::Vec2 {
glam::Vec2::new(self.x, self.y)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn add_cartesians() {
let a = Vec2::new(2., 3.);
let b = Vec2::new(5., 6.);
let sum = a + b;
assert!(sum.x == a.x + b.x);
assert!(sum.y == a.y + b.y);
}
#[test]
fn avg_of_vec2s() {
let vecs = [Vec2::new(1.0, 1.0), Vec2::new(3.0, 3.0)];
let avg = vecs.iter().average();
assert_eq!(Vec2::new(2.0, 2.0), avg);
}
}