Balls2d
This commit is contained in:
parent
5f546a03b0
commit
a9e80d6df9
@ -41,6 +41,7 @@ pub enum PCM {
|
|||||||
Grid3KDTsang(StickProbabilityCli),
|
Grid3KDTsang(StickProbabilityCli),
|
||||||
Grid3(StickProbabilityCli),
|
Grid3(StickProbabilityCli),
|
||||||
Hex(StickProbabilityCli),
|
Hex(StickProbabilityCli),
|
||||||
|
Balls2d(BallsCli),
|
||||||
Balls(BallsCli),
|
Balls(BallsCli),
|
||||||
SurfaceProbabilityMeasure(SurfaceProbabilityMeasureCli),
|
SurfaceProbabilityMeasure(SurfaceProbabilityMeasureCli),
|
||||||
}
|
}
|
||||||
|
|||||||
19
src/main.rs
19
src/main.rs
@ -6,10 +6,11 @@ use clap::Parser;
|
|||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use crate::cli::{drive_system};
|
use crate::cli::{drive_system};
|
||||||
use crate::cli::cli::{StickProbabilityCli, InitialCli, BallsCli, PCM, ModelCli, SurfaceProbabilityMeasureCli};
|
use crate::cli::cli::{StickProbabilityCli, InitialCli, BallsCli, PCM, ModelCli, SurfaceProbabilityMeasureCli};
|
||||||
|
use crate::cli::cli::PCM::Balls2d;
|
||||||
use crate::cli::output::write;
|
use crate::cli::output::write;
|
||||||
use crate::surface_probability_measure::{LoggerSticker, ReadOnlyVectorStorage};
|
use crate::surface_probability_measure::{LoggerSticker, ReadOnlyVectorStorage};
|
||||||
use crate::system::model::DLASystem;
|
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::hexagonal::HexPosition;
|
||||||
use crate::system::spaces::kd_grid::{KDSpace};
|
use crate::system::spaces::kd_grid::{KDSpace};
|
||||||
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
||||||
@ -112,6 +113,22 @@ fn main() {
|
|||||||
write(&sys, cli.format, &cli.output);
|
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 }) => {
|
PCM::Balls(BallsCli { ball_radius, stick_distance, walk_step }) => {
|
||||||
let mut sys = DLASystem::new(
|
let mut sys = DLASystem::new(
|
||||||
SmallRng::seed_from_u64(cli.seed),
|
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 kd_grid;
|
||||||
pub mod hexagonal;
|
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 struct Grid3D {
|
||||||
pub x: i32,
|
pub x: i32,
|
||||||
pub y: i32,
|
pub y: i32,
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
use std::f32::consts::PI;
|
use std::f32::consts::PI;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use crate::system::Position;
|
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::hexagonal::HexPosition;
|
||||||
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
use crate::system::spaces::square_grid::{Grid2D, Grid3D};
|
||||||
|
|
||||||
@ -49,3 +50,9 @@ impl Spawner<P3> for UniformSpawner {
|
|||||||
P3::random_with_radius(rng, radius)
|
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