use std::ops::Add; use num_integer::Roots; use crate::system::{GriddedPosition, Position}; use serde::{Serialize, Deserialize}; #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct HexPosition { pub q: i32, pub r: i32, } impl Add for HexPosition { type Output = Self; fn add(self, rhs: Self) -> Self::Output { HexPosition { q: self.q + rhs.q, r: self.r + rhs.r } } } impl GriddedPosition for HexPosition { const NEIGHBOURS: u32 = 6; fn neighbour(&self, neighbour_index: u32) -> Self { let neighbour_index = neighbour_index as usize; const OFFSETS: [(i32, i32); 6] = [ (1, 0), (1, -1), (0, -1), (-1, 0), (-1, 1), (0, 1), ]; self.clone() + HexPosition { q: OFFSETS[neighbour_index].0, r: OFFSETS[neighbour_index].1 } } fn linear_index(&self, grid_size: u32) -> usize { let q = (self.q + (grid_size as i32 / 2)) as usize; let r = (self.r + (grid_size as i32 / 2)) as usize; r * (grid_size as usize) + q } } impl Position for HexPosition { // const DIM: usize = 2; type Cartesian = [f32; 2]; fn zero() -> Self { HexPosition { q: 0, r: 0 } } fn abs(&self) -> f32 { ((self.q.pow(2) + self.r.pow(2) + self.q * self.r) as f32).sqrt() } fn from_cartesian(cartesian: Self::Cartesian) -> Self { let q = (1.0f32 / 3.0f32).sqrt() * cartesian[0] - 1.0 / 3.0 * cartesian[1]; let r = 2.0 / 3.0 * cartesian[1]; Self { q: q as i32, r: r as i32 } } fn to_cartesian(&self) -> Self::Cartesian { let q = self.q as f32; let r = self.r as f32; [ 3f32.sqrt() * q + 3f32.sqrt() / 2f32 * r, (3. / 2.) * r ] } }