compb-dla-model/src/system/spaces/hexagonal.rs
2023-03-16 13:24:39 +00:00

70 lines
1.7 KiB
Rust

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
]
}
}