Balls2d
This commit is contained in:
parent
5f546a03b0
commit
a9e80d6df9
@ -41,6 +41,7 @@ pub enum PCM {
|
||||
Grid3KDTsang(StickProbabilityCli),
|
||||
Grid3(StickProbabilityCli),
|
||||
Hex(StickProbabilityCli),
|
||||
Balls2d(BallsCli),
|
||||
Balls(BallsCli),
|
||||
SurfaceProbabilityMeasure(SurfaceProbabilityMeasureCli),
|
||||
}
|
||||
|
||||
19
src/main.rs
19
src/main.rs
@ -6,10 +6,11 @@ use clap::Parser;
|
||||
use rand::prelude::*;
|
||||
use crate::cli::{drive_system};
|
||||
use crate::cli::cli::{StickProbabilityCli, InitialCli, BallsCli, PCM, ModelCli, SurfaceProbabilityMeasureCli};
|
||||
use crate::cli::cli::PCM::Balls2d;
|
||||
use crate::cli::output::write;
|
||||
use crate::surface_probability_measure::{LoggerSticker, ReadOnlyVectorStorage};
|
||||
use crate::system::model::DLASystem;
|
||||
use crate::system::spaces::continuous::{ContinuousSticker, ContinuousStorage, ContinuousWalker};
|
||||
use crate::system::spaces::continuous_3d::{ContinuousSticker, ContinuousStorage, ContinuousWalker};
|
||||
use crate::system::spaces::hexagonal::HexPosition;
|
||||
use crate::system::spaces::kd_grid::{KDSpace};
|
||||
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
||||
@ -112,6 +113,22 @@ fn main() {
|
||||
write(&sys, cli.format, &cli.output);
|
||||
}
|
||||
|
||||
PCM::Balls2d(BallsCli { ball_radius, stick_distance, walk_step }) => {
|
||||
use system::spaces::continuous_2d;
|
||||
|
||||
let mut sys = DLASystem::new(
|
||||
SmallRng::seed_from_u64(cli.seed),
|
||||
continuous_2d::ContinuousStorage { inner: kiddo::KdTree::new(), ball_radius_sq: ball_radius * ball_radius },
|
||||
continuous_2d::ContinuousWalker { walk_step },
|
||||
UniformSpawner,
|
||||
continuous_2d::ContinuousSticker { range_sq: stick_distance * stick_distance },
|
||||
cli.max_particles,
|
||||
);
|
||||
|
||||
drive_system(&mut sys, cli.max_frames, cli.notify_every);
|
||||
write(&sys, cli.format, &cli.output);
|
||||
}
|
||||
|
||||
PCM::Balls(BallsCli { ball_radius, stick_distance, walk_step }) => {
|
||||
let mut sys = DLASystem::new(
|
||||
SmallRng::seed_from_u64(cli.seed),
|
||||
|
||||
102
src/system/spaces/continuous_2d.rs
Normal file
102
src/system/spaces/continuous_2d.rs
Normal file
@ -0,0 +1,102 @@
|
||||
use std::f32::consts::PI;
|
||||
use std::ops::Add;
|
||||
use kiddo::distance::squared_euclidean;
|
||||
use rand::Rng;
|
||||
use serde::Serialize;
|
||||
use crate::system::sticker::Sticker;
|
||||
use crate::system::{Position, Storage};
|
||||
use crate::system::walker::Walker;
|
||||
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct P2 {
|
||||
x: f32,
|
||||
y: f32,
|
||||
}
|
||||
|
||||
impl P2 {
|
||||
fn as_arr(&self) -> [f32; 2] {
|
||||
[self.x, self.y]
|
||||
}
|
||||
|
||||
pub fn random_with_radius<R: Rng>(rng: &mut R, radius: f32) -> P2 {
|
||||
let theta = rng.gen_range(0f32..1.0) * 2.0 * PI;
|
||||
|
||||
let (x, y) = (
|
||||
radius * theta.sin(),
|
||||
radius * theta.sin(),
|
||||
);
|
||||
|
||||
P2 { x, y }
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for P2 {
|
||||
type Output = P2;
|
||||
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
P2 {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContinuousStorage {
|
||||
pub inner: kiddo::KdTree<f32, (), 2>,
|
||||
pub ball_radius_sq: f32,
|
||||
}
|
||||
|
||||
impl Position for P2 {
|
||||
type Cartesian = [f32; 2];
|
||||
|
||||
fn zero() -> Self {
|
||||
P2 { x: 0f32, y: 0f32 }
|
||||
}
|
||||
|
||||
fn abs(&self) -> f32 {
|
||||
(self.x.powi(2) + self.y.powi(2)).powf(0.5)
|
||||
}
|
||||
|
||||
fn from_cartesian(cartesian: Self::Cartesian) -> Self {
|
||||
P2 { x: cartesian[0], y: cartesian[1] }
|
||||
}
|
||||
|
||||
fn to_cartesian(&self) -> Self::Cartesian {
|
||||
[self.x, self.y]
|
||||
}
|
||||
}
|
||||
|
||||
impl Storage<P2> for ContinuousStorage {
|
||||
fn is_occupied(&self, position: &P2) -> bool {
|
||||
let (dist_sq, _) = self.inner.nearest_one(&position.as_arr(), &squared_euclidean).unwrap();
|
||||
|
||||
// Is the distance of this point to the next one less than twice the ball radius
|
||||
dist_sq < 2.0 * self.ball_radius_sq
|
||||
}
|
||||
|
||||
fn deposit(&mut self, position: &P2) {
|
||||
self.inner.add(&position.as_arr(), ()).expect("Failed to write to space")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContinuousSticker {
|
||||
/// INVARIANT: THIS SHOULD BE GREATER THAN THE BALL_RADIUS_SQ value
|
||||
pub range_sq: f32,
|
||||
}
|
||||
|
||||
impl Sticker<P2, ContinuousStorage> for ContinuousSticker {
|
||||
fn should_stick<R: Rng>(&self, _rng: &mut R, space: &ContinuousStorage, position: &P2) -> bool {
|
||||
let (a, _) = space.inner.nearest_one(&position.as_arr(), &squared_euclidean).unwrap();
|
||||
a < self.range_sq
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ContinuousWalker {
|
||||
pub walk_step: f32
|
||||
}
|
||||
|
||||
impl Walker<P2> for ContinuousWalker {
|
||||
fn walk<R: Rng>(&self, rng: &mut R, position: &P2) -> P2 {
|
||||
position.clone() + P2::random_with_radius(rng, self.walk_step)
|
||||
}
|
||||
}
|
||||
@ -5,4 +5,5 @@ pub mod square_grid;
|
||||
pub mod kd_grid;
|
||||
pub mod hexagonal;
|
||||
|
||||
pub mod continuous;
|
||||
pub mod continuous_3d;
|
||||
pub mod continuous_2d;
|
||||
|
||||
@ -80,7 +80,7 @@ impl GriddedPosition for Grid2D {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct Grid3D {
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
use std::f32::consts::PI;
|
||||
use rand::Rng;
|
||||
use crate::system::Position;
|
||||
use crate::system::spaces::continuous::P3;
|
||||
use crate::system::spaces::continuous_2d::P2;
|
||||
use crate::system::spaces::continuous_3d::P3;
|
||||
use crate::system::spaces::hexagonal::HexPosition;
|
||||
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
||||
|
||||
@ -49,3 +50,9 @@ impl Spawner<P3> for UniformSpawner {
|
||||
P3::random_with_radius(rng, radius)
|
||||
}
|
||||
}
|
||||
|
||||
impl Spawner<P2> for UniformSpawner {
|
||||
fn spawn<R: Rng>(&self, rng: &mut R, radius: f32) -> P2 {
|
||||
P2::random_with_radius(rng, radius)
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user