From 82833748f4912bf99f9e458ea05137001d9f1104 Mon Sep 17 00:00:00 2001 From: mindv0rtex Date: Mon, 1 Mar 2021 11:29:32 -0500 Subject: [PATCH] Bug in grid indexing. --- src/grid.rs | 7 ++++--- src/main.rs | 28 +++++++++++++++++++++++----- src/model.rs | 13 +++++++------ 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/grid.rs b/src/grid.rs index f0694ba..7902755 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -18,7 +18,7 @@ impl Grid { /// Create a new grid filled with random floats in the [0.0..1.0) range. pub fn new(width: usize, height: usize) -> Self { if !width.is_power_of_two() || !height.is_power_of_two() { - panic!("Grid dimensitions must be a power of two."); + panic!("Grid dimensions must be a power of two."); } let rng = rand::thread_rng(); let range = Uniform::from(0.0..1.0); @@ -35,8 +35,9 @@ impl Grid { /// Truncate x and y and return a corresponding index into the data slice. fn index(&self, x: f32, y: f32) -> usize { - let i = (x as usize + self.width) & (self.width - 1); - let j = (y as usize + self.height) & (self.height - 1); + // x/y can come in negative, hence we shift them by width/height. + let i = (x + self.width as f32) as usize & (self.width - 1); + let j = (y + self.height as f32) as usize & (self.height - 1); j * self.width + i } diff --git a/src/main.rs b/src/main.rs index 0fd4649..5a681d5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,27 @@ +use indicatif::{ProgressBar, ProgressStyle}; use physarum::model; fn main() { - let mut model = model::Model::new(128, 128, 4096, 1); - println!("{:#?}", model); - model.step(); - model.step(); - model.save_to_image(); + let n_iterations = 400; + let pb = ProgressBar::new(n_iterations); + pb.set_style( + ProgressStyle::default_bar() + .template( + "{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})", + ) + .progress_chars("#>-"), + ); + + let (width, height) = (1024, 1024); + let n_particles = 1 << 22; + let diffusivity = 1; + let mut model = model::Model::new(width, height, n_particles, diffusivity); + println!("Model configuration: {:#?}", model.config); + + for i in 0..n_iterations { + model.step(); + pb.set_position(i); + } + pb.finish_with_message("Finished!"); + model.save_to_image("out.png"); } diff --git a/src/model.rs b/src/model.rs index 6e51515..20e0f98 100644 --- a/src/model.rs +++ b/src/model.rs @@ -2,6 +2,7 @@ use crate::grid::Grid; use rand::{seq::SliceRandom, Rng}; use rayon::prelude::*; +use std::f32::consts::TAU; /// A single Physarum agent. The x and y positions are continuous, hence we use floating point /// numbers instead of integers. @@ -19,7 +20,7 @@ impl Agent { Agent { x: x * width as f32, y: y * height as f32, - angle: angle * std::f32::consts::TAU, + angle: angle * TAU, } } @@ -34,7 +35,7 @@ impl Agent { ) { use crate::util::wrap; let delta_angle = rotation_angle * direction; - self.angle = wrap(self.angle + delta_angle, std::f32::consts::TAU); + self.angle = wrap(self.angle + delta_angle, TAU); self.x = wrap(self.x + step_distance * self.angle.cos(), width as f32); self.y = wrap(self.y + step_distance * self.angle.sin(), height as f32); } @@ -43,7 +44,7 @@ impl Agent { /// A model configuration. We make it into a separate type, because we will eventually have multiple /// configurations in one model. #[derive(Debug)] -struct PopulationConfig { +pub struct PopulationConfig { sensor_distance: f32, step_distance: f32, decay_factor: f32, @@ -95,7 +96,7 @@ pub struct Model { // Simulation parameters. diffusivity: usize, - config: PopulationConfig, + pub config: PopulationConfig, iteration: i32, width: usize, @@ -178,7 +179,7 @@ impl Model { } /// Output the current trail layer as a grayscale image. - pub fn save_to_image(&self) { + pub fn save_to_image(&self, name: &str) { let mut img = image::GrayImage::new(self.width as u32, self.height as u32); let max_value = self.grid.quantile(0.999); @@ -188,6 +189,6 @@ impl Model { let c = (value / max_value).clamp(0.0, 1.0) * 255.0; img.put_pixel(x, y, image::Luma([c as u8])); } - img.save("out.png").unwrap(); + img.save(name).unwrap(); } }