bestagon 0.10.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 }

macro_rules! mul_impl {
  ($($t:ty)*) => ($(
    impl std::ops::Mul<$t> for Vec2<$t> {
      type Output = Vec2<$t>;

      fn mul(self, other: $t) -> Self::Output {
        Vec2::new(self.x * other, self.y * other)
      }
    }
  )*)
}

mul_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);
  }

  #[test]
  fn mul_cartesians() {
    let a = Vec2::new(2.0, 3.0);
    let prod = a * 2.0;
    assert_eq!(prod, Vec2::new(4.0, 6.0));

    let b = Vec2::new(2, 3);
    let prod_int = b * 3;
    assert_eq!(prod_int, Vec2::new(6, 9));
  }
}