Add trail deposition, diffusion and decay.

This commit is contained in:
mindv0rtex 2021-02-26 20:39:27 -05:00
parent cf35e041dd
commit 51f10723ed
4 changed files with 26 additions and 12 deletions

View File

@ -32,8 +32,7 @@ impl Blur {
fn boxes_for_gaussian<const N: usize>(sigma: f32) -> ([usize; N]) { fn boxes_for_gaussian<const N: usize>(sigma: f32) -> ([usize; N]) {
let w_ideal = (12.0 * sigma * sigma / N as f32 + 1.0).sqrt(); let w_ideal = (12.0 * sigma * sigma / N as f32 + 1.0).sqrt();
let mut w = w_ideal as usize; let mut w = w_ideal as usize;
w -= 1 - w & 1; w -= 1 - (w & 1);
let mut m = 0.25 * (N * (w + 3)) as f32; let mut m = 0.25 * (N * (w + 3)) as f32;
m -= 3.0 * sigma * sigma / (w + 1) as f32; m -= 3.0 * sigma * sigma / (w + 1) as f32;
let m = m.round() as usize; let m = m.round() as usize;
@ -145,4 +144,16 @@ mod tests {
] ]
) )
} }
#[test]
fn test_boxes_for_gaussian() {
let boxes = Blur::boxes_for_gaussian::<3>(1.5);
assert_eq!(boxes, [1, 1, 1]);
let boxes = Blur::boxes_for_gaussian::<3>(1.8);
assert_eq!(boxes, [1, 1, 2]);
let boxes = Blur::boxes_for_gaussian::<3>(2.5);
assert_eq!(boxes, [2, 2, 2]);
}
} }

View File

@ -17,8 +17,7 @@ pub struct Grid {
impl Grid { impl Grid {
/// Create a new grid filled with random floats in the [0.0..1.0) range. /// Create a new grid filled with random floats in the [0.0..1.0) range.
pub fn new(width: usize, height: usize) -> Self { pub fn new(width: usize, height: usize) -> Self {
use crate::util::is_power_of_two; if !width.is_power_of_two() || !height.is_power_of_two() {
if !is_power_of_two(width) || !is_power_of_two(height) {
panic!("Grid dimensitions must be a power of two."); panic!("Grid dimensitions must be a power of two.");
} }
let rng = rand::thread_rng(); let rng = rand::thread_rng();

View File

@ -1,6 +1,6 @@
use crate::grid::Grid; use crate::grid::Grid;
use rand::{seq::SliceRandom, thread_rng, Rng}; use rand::{seq::SliceRandom, Rng};
use rayon::prelude::*; use rayon::prelude::*;
/// A single Physarum agent. The x and y positions are continuous, hence we use floating point /// A single Physarum agent. The x and y positions are continuous, hence we use floating point
@ -49,6 +49,7 @@ struct PopulationConfig {
decay_factor: f32, decay_factor: f32,
sensor_angle: f32, sensor_angle: f32,
rotation_angle: f32, rotation_angle: f32,
deposition_amount: f32,
} }
impl PopulationConfig { impl PopulationConfig {
@ -77,6 +78,8 @@ impl PopulationConfig {
rotation_angle: rng rotation_angle: rng
.gen_range(Self::ROTATION_ANGLE_MIN..=Self::ROTATION_ANGLE_MAX) .gen_range(Self::ROTATION_ANGLE_MIN..=Self::ROTATION_ANGLE_MAX)
.to_radians(), .to_radians(),
deposition_amount: rng
.gen_range(Self::DEPOSITION_AMOUNT_MIN..=Self::DEPOSITION_AMOUNT_MAX),
} }
} }
} }
@ -163,8 +166,14 @@ impl Model {
agent.rotate_and_move(direction, rotation_angle, step_distance, width, height); agent.rotate_and_move(direction, rotation_angle, step_distance, width, height);
}); });
// Deposit + Diffuse + Decay // Deposit
for agent in self.agents.iter() {
self.grid
.add(agent.x, agent.y, self.config.deposition_amount);
}
// Diffuse + Decay
self.grid
.diffuse(self.diffusivity, self.config.decay_factor);
self.iteration += 1; self.iteration += 1;
} }
} }

View File

@ -1,8 +1,3 @@
#[inline(always)]
pub fn is_power_of_two(x: usize) -> bool {
(x & (x - 1)) == 0
}
#[inline(always)] #[inline(always)]
pub fn wrap(x: f32, max: f32) -> f32 { pub fn wrap(x: f32, max: f32) -> f32 {
x - max * ((x > max) as i32 as f32 - (x < 0.0_f32) as i32 as f32) x - max * ((x > max) as i32 as f32 - (x < 0.0_f32) as i32 as f32)