diff --git a/src/fd.rs b/src/fd.rs index 72e0bd6..2544537 100644 --- a/src/fd.rs +++ b/src/fd.rs @@ -6,7 +6,7 @@ use std::fs::File; use std::os::unix::fs::symlink; use bevy::tasks::ParallelSlice; use crate::system::spaces::square_grid::{Grid2D, Grid3D}; -use itertools::Itertools; +use itertools::{Itertools, MinMaxResult}; use clap::Parser; use crate::system::{GriddedPosition, Position}; use crate::system::model::HistoryLine; @@ -101,55 +101,19 @@ fn box_count_3d(data: &Vec, size: u32) -> usize { .count(); } -fn box_count_nd(data: &Vec

, size: u32) -> usize { - let n = data.len(); - let pp = data.iter().map(|op| op.to_cartesian()).collect::>(); +fn box_count_nd(data: &Vec<[f32; N]>, size: u32) -> usize { + let ranges = (0..N).map(|n| + match data.iter() + .minmax_by(|a, b| a[n].total_cmp(&b[n])) { + MinMaxResult::NoElements => panic!("No data"), + MinMaxResult::OneElement(_) => panic!("Needs more than one point to compute boxcount"), + MinMaxResult::MinMax(min, max) => [min[n], min[n]], + }).collect::>(); - let x_min = data - .iter() - .min_by(|Grid3D { x: x1, .. }, Grid3D { x: x2, .. }| x1.cmp(x2)) - .unwrap().x; + let w: f32 = (ranges[0][1] - ranges[0][0]) / (size as f32); - let x_max = data - .iter() - .max_by(|Grid3D { x: x1, .. }, Grid3D { x: x2, .. }| x1.cmp(x2)) - .unwrap().x; - - let y_min = data - .iter() - .min_by(|Grid3D { y: v1, .. }, Grid3D { y: v2, .. }| v1.cmp(v2)) - .unwrap().y; - - let y_max = data - .iter() - .max_by(|Grid3D { y: v1, .. }, Grid3D { y: v2, .. }| v1.cmp(v2)) - .unwrap().y; - - let z_min = data - .iter() - .min_by(|Grid3D { z: v1, .. }, Grid3D { z: v2, .. }| v1.cmp(v2)) - .unwrap().y; - - let z_max = data - .iter() - .max_by(|Grid3D { z: v1, .. }, Grid3D { z: v2, .. }| v1.cmp(v2)) - .unwrap().y; - - let x_range = (x_max - x_min) as f64; - let y_range = (y_max - y_min) as f64; - let z_range = (z_max - z_min) as f64; - - let w: f64 = x_range / (size as f64); - - let grid_points = data.iter() - .map(|Grid3D { x, y, z }| [ - ((x - x_min) as f64 / w) as u32, - ((y - y_min) as f64 / w) as u32, - ((z - z_min) as f64 / w) as u32, - ]) - .collect::>(); - - return grid_points.iter() + return data.iter() + .map(|point| -> [i32; N] { std::array::from_fn(|n| ((point[n] - ranges[n][0]) / w) as i32) }) .unique() .count(); } @@ -165,10 +129,10 @@ fn main() { .expect("Failed to read json"); let a = lines.iter() - .map(|l| l.position.clone()) + .map(|l| l.position.to_cartesian()) .collect::>(); for size in 1..250 { - println!("[{}, {:?}],", size, box_count_3d(&a, size)); + println!("[{}, {:?}],", size, box_count_nd(&a, size)); } } diff --git a/src/system/spaces/square_grid.rs b/src/system/spaces/square_grid.rs index bc2fa04..9598d5e 100644 --- a/src/system/spaces/square_grid.rs +++ b/src/system/spaces/square_grid.rs @@ -102,10 +102,26 @@ impl Add for Grid3D { type Output = Grid3D; fn add(self, rhs: Self) -> Self::Output { - Grid3D { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z } + Grid3D { + x: self.x + rhs.x, + y: self.y + rhs.y, + z: self.z + rhs.z, + } } } +#[test] +fn grid3_add_test() { + assert_eq!( + Grid3D::from_cartesian([0f32, 0f32, 0f32]) + Grid3D::from_cartesian([0f32, 1f32, 0f32]), + Grid3D::from_cartesian([0f32, 1f32, 0f32]) + ); + assert_eq!( + Grid3D::from_cartesian([5.0, 3.0, 1.0]) + Grid3D::from_cartesian([-2.0, 5.0, 100.0]), + Grid3D::from_cartesian([3.0, 8.0, 101.0]) + ); +} + impl Position for Grid3D { type Cartesian = [f32; 3]; @@ -130,11 +146,25 @@ impl Position for Grid3D { } } +#[test] +fn grid3_neighbours_test() { + let neighbours = (0..Grid3D::NEIGHBOURS) + .map(|n| Grid3D::neighbour(&Grid3D::zero(), n)) + .collect::>(); + + assert!(neighbours.contains(&Grid3D { x: 1, y: 0, z: 0 })); + assert!(neighbours.contains(&Grid3D { x: -1, y: 0, z: 0 })); + assert!(neighbours.contains(&Grid3D { x: 0, y: 1, z: 0 })); + assert!(neighbours.contains(&Grid3D { x: 0, y: -1, z: 0 })); + assert!(neighbours.contains(&Grid3D { x: 0, y: 0, z: 1 })); + assert!(neighbours.contains(&Grid3D { x: 0, y: 0, z: -1 })); +} + impl GriddedPosition for Grid3D { const NEIGHBOURS: u32 = 6; fn neighbour(&self, neighbour_index: u32) -> Self { - let (dim, sign) = neighbour_index.div_rem(&3); + let (dim, sign) = neighbour_index.div_rem(&2); let sign = if sign == 0 { 1 } else { -1 }; let offset = Self::in_direction(dim, sign);