bestagon 0.9.0

An engine for discrete stuff in hexagonal grids
Documentation
#[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);
  }
}