Add N-dimensional position code
This commit is contained in:
parent
14b5cb4679
commit
1c49bf92c8
@ -1,3 +1,5 @@
|
||||
#![feature(array_zip)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
use rand::prelude::*;
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ use serde::{Serialize, Deserialize, Serializer};
|
||||
pub mod walker;
|
||||
pub mod storage;
|
||||
pub mod model;
|
||||
pub mod nd;
|
||||
|
||||
pub trait GriddedPosition: Add<Output=Self> + Serialize + Clone {
|
||||
fn zero() -> Self;
|
||||
|
||||
99
src/system/nd.rs
Normal file
99
src/system/nd.rs
Normal file
@ -0,0 +1,99 @@
|
||||
use std::ops::Add;
|
||||
use rand::Rng;
|
||||
use serde::{Serialize, Serializer};
|
||||
use serde::ser::SerializeMap;
|
||||
use crate::system::GriddedPosition;
|
||||
use crate::system::storage::Storage;
|
||||
|
||||
pub struct NDVectorStorage<const DIM: usize> {
|
||||
backing: Vec<bool>,
|
||||
grid_size: u32,
|
||||
}
|
||||
|
||||
impl<const DIM: usize> Storage<NDPosition<DIM>> for NDVectorStorage<DIM> {
|
||||
fn at(&self, position: &NDPosition<DIM>) -> bool {
|
||||
return self.backing[position.linear_index(self.grid_size)];
|
||||
}
|
||||
|
||||
fn deposit(&mut self, position: &NDPosition<DIM>) {
|
||||
self.backing[position.linear_index(self.grid_size)] = true;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct NDPosition<const DIM: usize>([i32; DIM]);
|
||||
|
||||
impl<const DIM: usize> NDPosition<DIM> {
|
||||
pub fn in_direction(direction: usize, value: i32) -> Self {
|
||||
let mut arr = [0; DIM];
|
||||
arr[direction] = value;
|
||||
NDPosition(arr)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const DIM: usize> Add for NDPosition<DIM> {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0.zip(rhs.0).map(|(a, b)| a + b))
|
||||
}
|
||||
}
|
||||
|
||||
impl<const DIM: usize> Serialize for NDPosition<DIM> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
|
||||
let mut map = serializer.serialize_map(Some(DIM))?;
|
||||
for (i, v) in self.0.iter().enumerate() {
|
||||
map.serialize_entry(&format!("r{}", i), v)?;
|
||||
}
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
|
||||
impl<const DIM: usize> GriddedPosition for NDPosition<DIM> {
|
||||
fn zero() -> Self {
|
||||
NDPosition([0; DIM])
|
||||
}
|
||||
|
||||
fn spawn<R: Rng>(rng: &mut R, radius: f32) -> Self {
|
||||
let mut a: [f32; DIM] = [0f32; DIM];
|
||||
let mut b: [i32; DIM] = [0i32; DIM];
|
||||
|
||||
for i in 0..DIM {
|
||||
a[i] = rng.gen_range(0f32..1f32);
|
||||
}
|
||||
|
||||
let norm = a.iter().sum::<f32>()
|
||||
.sqrt();
|
||||
|
||||
for i in 0..DIM {
|
||||
a[i] = a[i] / norm;
|
||||
b[i] = a[i] as i32;
|
||||
}
|
||||
|
||||
return Self(b)
|
||||
}
|
||||
|
||||
fn abs(&self) -> f32 {
|
||||
let a: i32 = self.0.iter()
|
||||
.map(|r| r.pow(2))
|
||||
.sum();
|
||||
|
||||
(a as f32).powf(0.5)
|
||||
}
|
||||
|
||||
fn neighbours(&self) -> Vec<Self> {
|
||||
let a = (0..DIM).into_iter();
|
||||
|
||||
return a.flat_map(|direction| [
|
||||
self.clone() + NDPosition::in_direction(direction, 1),
|
||||
self.clone() + NDPosition::in_direction(direction, -1),
|
||||
]).collect();
|
||||
}
|
||||
|
||||
fn linear_index(&self, grid_size: u32) -> usize {
|
||||
self.0.iter()
|
||||
.enumerate()
|
||||
.map(|(i, v)| (grid_size.pow(i as u32) as usize) * (v + ((grid_size / 2) as i32)) as usize)
|
||||
.sum()
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user