diff --git a/src/agent.rs b/src/agent.rs index fe038cc..0cf032a 100644 --- a/src/agent.rs +++ b/src/agent.rs @@ -1,11 +1,8 @@ -use crate::{ - util::wrap, - buffer::Buf, -}; +use crate::{buffer::Buf, util::wrap}; +use fastapprox::faster::{cos, sin}; use rand::{seq::SliceRandom, Rng}; use std::f32::consts::TAU; -use fastapprox::faster::{cos, sin}; use std::fmt::{Display, Formatter}; // A single Physarum agent. The x and y positions are continuous, hence we use floating point numbers instead of integers. @@ -30,7 +27,13 @@ impl Display for Agent { impl Agent { // Construct a new agent with random parameters. - pub fn new(width: usize, height: usize, id: usize, rng: &mut R, i: usize) -> Self { + pub fn new( + width: usize, + height: usize, + id: usize, + rng: &mut R, + i: usize, + ) -> Self { let (x, y, angle) = rng.gen::<(f32, f32, f32)>(); Agent { x: x * width as f32, @@ -43,7 +46,16 @@ impl Agent { // Tick an agent #[inline] - pub fn tick(&mut self, buf: &Buf, sensor_distance: f32, sensor_angle: f32, rotation_angle: f32, step_distance: f32, width: usize, height: usize) { + pub fn tick( + &mut self, + buf: &Buf, + sensor_distance: f32, + sensor_angle: f32, + rotation_angle: f32, + step_distance: f32, + width: usize, + height: usize, + ) { let xc = self.x + cos(self.angle) * sensor_distance; let yc = self.y + sin(self.angle) * sensor_distance; @@ -77,14 +89,8 @@ impl Agent { let delta_angle = rotation_angle * direction; self.angle = wrap(self.angle + delta_angle, TAU); - self.x = wrap( - self.x + step_distance * cos(self.angle), - width as f32, - ); - self.y = wrap( - self.y + step_distance * sin(self.angle), - height as f32, - ); + self.x = wrap(self.x + step_distance * cos(self.angle), width as f32); + self.y = wrap(self.y + step_distance * sin(self.angle), height as f32); } } @@ -108,4 +114,4 @@ impl PartialEq for Agent { && self.population_id == other.population_id && self.i == other.i } -} \ No newline at end of file +} diff --git a/src/blur.rs b/src/blur.rs index 64e5b09..1ecdc39 100644 --- a/src/blur.rs +++ b/src/blur.rs @@ -148,15 +148,69 @@ mod tests { // ndimage.uniform_filter(a, size=3, mode='wrap') # 2D blur let mut src: Vec = vec![ - 0.32352856, 0.06571674, 0.01939427, 0.06352045, 0.708_527, 0.617_221_7, 0.16638431, - 0.628_400_74, 0.554_893_9, 0.240_076_77, 0.325_009_94, 0.08515139, 0.679_840_9, 0.6975669, - 0.736_234_25, 0.55053085, 0.692_227_66, 0.22727048, 0.13594262, 0.10002105, 0.16099514, - 0.07719103, 0.23984282, 0.9083058, 0.642_227_4, 0.968_934_2, 0.74662715, 0.715_620_1, - 0.736_546_5, 0.70610344, 0.221_011_18, 0.755_721_87, 0.691_958_84, 0.837_414, 0.27583158, - 0.572_570_5, 0.681_606, 0.392_373_38, 0.33524343, 0.893_968_34, 0.602_969_35, 0.171_301_13, - 0.1733834, 0.771_278_2, 0.99537134, 0.915_049_6, 0.493_121_1, 0.430_352_03, 0.70297265, - 0.367_341_8, 0.4551964, 0.471_043_14, 0.603_747_8, 0.738_726_85, 0.5630592, 0.974_402_25, - 0.633_682_85, 0.841_092_94, 0.24447136, 0.750384, 0.16893725, 0.542_256_65, 0.435_607_82, + 0.32352856, + 0.06571674, + 0.01939427, + 0.06352045, + 0.708_527, + 0.617_221_7, + 0.16638431, + 0.628_400_74, + 0.554_893_9, + 0.240_076_77, + 0.325_009_94, + 0.08515139, + 0.679_840_9, + 0.6975669, + 0.736_234_25, + 0.55053085, + 0.692_227_66, + 0.22727048, + 0.13594262, + 0.10002105, + 0.16099514, + 0.07719103, + 0.23984282, + 0.9083058, + 0.642_227_4, + 0.968_934_2, + 0.74662715, + 0.715_620_1, + 0.736_546_5, + 0.70610344, + 0.221_011_18, + 0.755_721_87, + 0.691_958_84, + 0.837_414, + 0.27583158, + 0.572_570_5, + 0.681_606, + 0.392_373_38, + 0.33524343, + 0.893_968_34, + 0.602_969_35, + 0.171_301_13, + 0.1733834, + 0.771_278_2, + 0.99537134, + 0.915_049_6, + 0.493_121_1, + 0.430_352_03, + 0.70297265, + 0.367_341_8, + 0.4551964, + 0.471_043_14, + 0.603_747_8, + 0.738_726_85, + 0.5630592, + 0.974_402_25, + 0.633_682_85, + 0.841_092_94, + 0.24447136, + 0.750384, + 0.16893725, + 0.542_256_65, + 0.435_607_82, 0.414_971_23, ]; let (width, height) = (8, 8); @@ -165,15 +219,69 @@ mod tests { blur.box_blur_h(&src, &mut dst, width, 1); let mut sol: Vec = vec![ - 0.339_215_37, 0.136_213_18, 0.04954382, 0.263_813_9, 0.46308973, 0.497_377_7, 0.470_668_94, - 0.372_771_2, 0.448_500_5, 0.373_326_87, 0.21674603, 0.363_334_1, 0.48751974, 0.70454735, - 0.661_444, 0.613_886_36, 0.609_268, 0.351_813_58, 0.15441138, 0.1323196, 0.11273574, - 0.159343, 0.40844655, 0.613_458_75, 0.788_961_2, 0.785_929_56, 0.810_393_8, 0.732_931_26, - 0.719_423_35, 0.554_553_7, 0.560_945_5, 0.539_653_5, 0.807_780_4, 0.601_734_8, 0.561_938_7, - 0.510_002_7, 0.548_849_94, 0.46974093, 0.540_528_4, 0.640_390_2, 0.40154082, 0.315_884_62, - 0.371_987_58, 0.646_677_6, 0.893_899_74, 0.801_180_66, 0.612_840_9, 0.508_814_16, 0.681_572_2, - 0.508_503_6, 0.431_193_77, 0.509_995_76, 0.604_505_9, 0.635_177_9, 0.758_729_4, 0.746_811_33, - 0.629_915_65, 0.573_082_4, 0.611_982_76, 0.38793087, 0.48719263, 0.38226724, 0.464_278_58, + 0.339_215_37, + 0.136_213_18, + 0.04954382, + 0.263_813_9, + 0.46308973, + 0.497_377_7, + 0.470_668_94, + 0.372_771_2, + 0.448_500_5, + 0.373_326_87, + 0.21674603, + 0.363_334_1, + 0.48751974, + 0.70454735, + 0.661_444, + 0.613_886_36, + 0.609_268, + 0.351_813_58, + 0.15441138, + 0.1323196, + 0.11273574, + 0.159343, + 0.40844655, + 0.613_458_75, + 0.788_961_2, + 0.785_929_56, + 0.810_393_8, + 0.732_931_26, + 0.719_423_35, + 0.554_553_7, + 0.560_945_5, + 0.539_653_5, + 0.807_780_4, + 0.601_734_8, + 0.561_938_7, + 0.510_002_7, + 0.548_849_94, + 0.46974093, + 0.540_528_4, + 0.640_390_2, + 0.40154082, + 0.315_884_62, + 0.371_987_58, + 0.646_677_6, + 0.893_899_74, + 0.801_180_66, + 0.612_840_9, + 0.508_814_16, + 0.681_572_2, + 0.508_503_6, + 0.431_193_77, + 0.509_995_76, + 0.604_505_9, + 0.635_177_9, + 0.758_729_4, + 0.746_811_33, + 0.629_915_65, + 0.573_082_4, + 0.611_982_76, + 0.38793087, + 0.48719263, + 0.38226724, + 0.464_278_58, 0.494_753_96, ]; for (v1, v2) in dst.iter().zip(sol) { @@ -182,15 +290,69 @@ mod tests { blur.box_blur_v(&src, &mut dst, width, height, 1, 1.0); sol = vec![ - 0.504_035_1, 0.382_295_5, 0.19629186, 0.299_685_27, 0.519_101_74, 0.619_015_1, 0.446_075_47, - 0.531_300_96, 0.523_550_03, 0.177688, 0.16011561, 0.08289763, 0.516_454_34, 0.46399322, - 0.38082045, 0.695_745_8, 0.629_783_03, 0.47876048, 0.402_526_56, 0.300_264_18, 0.5257942, - 0.49362046, 0.3990294, 0.738_186_2, 0.675_471_3, 0.677_872_9, 0.386_133_8, 0.46273723, - 0.526_382_57, 0.391_889_3, 0.265_365_8, 0.852_665_36, 0.645_718_5, 0.659_216_46, 0.39861405, - 0.686_489_6, 0.804_508, 0.671_175_5, 0.349_791_88, 0.693_347_4, 0.665_966_9, 0.458_685_64, - 0.30147046, 0.604_963_96, 0.760_241_7, 0.682_05, 0.463_807_9, 0.766_240_9, 0.6465416, - 0.459_911_97, 0.291_017_06, 0.664_235_1, 0.589_352_13, 0.732_011, 0.497_262_72, 0.606_575_13, - 0.553_394_7, 0.42471716, 0.23968734, 0.428_315_88, 0.493_737_34, 0.632_735_1, 0.388_350_46, + 0.504_035_1, + 0.382_295_5, + 0.19629186, + 0.299_685_27, + 0.519_101_74, + 0.619_015_1, + 0.446_075_47, + 0.531_300_96, + 0.523_550_03, + 0.177688, + 0.16011561, + 0.08289763, + 0.516_454_34, + 0.46399322, + 0.38082045, + 0.695_745_8, + 0.629_783_03, + 0.47876048, + 0.402_526_56, + 0.300_264_18, + 0.5257942, + 0.49362046, + 0.3990294, + 0.738_186_2, + 0.675_471_3, + 0.677_872_9, + 0.386_133_8, + 0.46273723, + 0.526_382_57, + 0.391_889_3, + 0.265_365_8, + 0.852_665_36, + 0.645_718_5, + 0.659_216_46, + 0.39861405, + 0.686_489_6, + 0.804_508, + 0.671_175_5, + 0.349_791_88, + 0.693_347_4, + 0.665_966_9, + 0.458_685_64, + 0.30147046, + 0.604_963_96, + 0.760_241_7, + 0.682_05, + 0.463_807_9, + 0.766_240_9, + 0.6465416, + 0.459_911_97, + 0.291_017_06, + 0.664_235_1, + 0.589_352_13, + 0.732_011, + 0.497_262_72, + 0.606_575_13, + 0.553_394_7, + 0.42471716, + 0.23968734, + 0.428_315_88, + 0.493_737_34, + 0.632_735_1, + 0.388_350_46, 0.672_591_45, ]; for (v1, v2) in dst.iter().zip(sol) { @@ -199,15 +361,69 @@ mod tests { blur.box_blur(&mut src, &mut dst, width, height, 1, 1.0); sol = vec![ - 0.472_543_84, 0.36087415, 0.29275754, 0.338_359_62, 0.47926736, 0.528_064_1, 0.5321305, - 0.493_803_83, 0.465_661_3, 0.287_117_9, 0.140_233_76, 0.253_155_86, 0.3544484, 0.453_756, - 0.513_519_8, 0.5333721, 0.615_576_57, 0.503_69, 0.393_850_42, 0.40952832, 0.43989295, - 0.472_814_68, 0.543_612, 0.588_999_5, 0.735_336_54, 0.579826, 0.508_914_65, 0.458_417_86, - 0.460_336_36, 0.39454588, 0.503_306_8, 0.597_834_17, 0.666_094_1, 0.567_849_7, 0.581_440_03, - 0.62987053, 0.720_724_34, 0.608_491_8, 0.571_438_25, 0.562_952_64, 0.630_297_84, 0.475_374_34, - 0.455_04, 0.5555587, 0.682_418_5, 0.635_366_5, 0.63736624, 0.632_005_2, 0.571_009_6, - 0.465_823_53, 0.471_721_38, 0.5148681, 0.661_866_07, 0.606_208_6, 0.611_949_6, 0.583_459_8, - 0.550_234_44, 0.405_933_05, 0.364_240_14, 0.38724685, 0.518_262_74, 0.504_940_9, 0.564_559, + 0.472_543_84, + 0.36087415, + 0.29275754, + 0.338_359_62, + 0.47926736, + 0.528_064_1, + 0.5321305, + 0.493_803_83, + 0.465_661_3, + 0.287_117_9, + 0.140_233_76, + 0.253_155_86, + 0.3544484, + 0.453_756, + 0.513_519_8, + 0.5333721, + 0.615_576_57, + 0.503_69, + 0.393_850_42, + 0.40952832, + 0.43989295, + 0.472_814_68, + 0.543_612, + 0.588_999_5, + 0.735_336_54, + 0.579826, + 0.508_914_65, + 0.458_417_86, + 0.460_336_36, + 0.39454588, + 0.503_306_8, + 0.597_834_17, + 0.666_094_1, + 0.567_849_7, + 0.581_440_03, + 0.62987053, + 0.720_724_34, + 0.608_491_8, + 0.571_438_25, + 0.562_952_64, + 0.630_297_84, + 0.475_374_34, + 0.455_04, + 0.5555587, + 0.682_418_5, + 0.635_366_5, + 0.63736624, + 0.632_005_2, + 0.571_009_6, + 0.465_823_53, + 0.471_721_38, + 0.5148681, + 0.661_866_07, + 0.606_208_6, + 0.611_949_6, + 0.583_459_8, + 0.550_234_44, + 0.405_933_05, + 0.364_240_14, + 0.38724685, + 0.518_262_74, + 0.504_940_9, + 0.564_559, 0.538_112_16, ]; for (v1, v2) in src.iter().zip(sol) { diff --git a/src/buffer.rs b/src/buffer.rs index ce62e29..b804ddd 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -17,11 +17,7 @@ impl Clone for Buf { impl Buf { pub fn new(width: usize, height: usize, buf: Vec) -> Self { - Buf { - width, - height, - buf, - } + Buf { width, height, buf } } // Truncate x and y and return a corresponding index into the data slice. @@ -36,4 +32,4 @@ impl Buf { pub fn get_buf(&self, x: f32, y: f32) -> f32 { self.buf[self.index(x, y)] } -} \ No newline at end of file +} diff --git a/src/grid.rs b/src/grid.rs index 6da4508..baf1240 100644 --- a/src/grid.rs +++ b/src/grid.rs @@ -1,12 +1,8 @@ -use crate::{ - blur::Blur, - agent::Agent, - buffer::Buf, -}; +use crate::{agent::Agent, blur::Blur, buffer::Buf}; use rand::{distributions::Uniform, Rng}; -use std::fmt::{Display, Formatter}; use rayon::{iter::ParallelIterator, prelude::*}; +use std::fmt::{Display, Formatter}; // A population configuration. #[derive(Debug)] @@ -93,7 +89,7 @@ pub struct Grid { // pub buf: Vec, pub buf: Buf, pub blur: Blur, - pub agents: Vec + pub agents: Vec, } impl Clone for Grid { @@ -112,7 +108,12 @@ impl Clone for Grid { impl Grid { // Create a new grid filled with random floats in the [0.0..1.0) range. - pub fn new(width: usize, height: usize, rng: &mut R, agents: Vec) -> Self { + pub fn new( + width: usize, + height: usize, + rng: &mut R, + agents: Vec, + ) -> Self { if !width.is_power_of_two() || !height.is_power_of_two() { panic!("Grid dimensions must be a power of two."); } @@ -177,10 +178,15 @@ impl Grid { let buf = self.buf.clone(); self.agents.par_iter_mut().for_each(|agent| { - agent.tick(&buf, - sensor_distance, sensor_angle, - rotation_angle, step_distance, - width, height); + agent.tick( + &buf, + sensor_distance, + sensor_angle, + rotation_angle, + step_distance, + width, + height, + ); }); self.deposit_all(); } diff --git a/src/imgdata.rs b/src/imgdata.rs index ba4b447..0fd7ab2 100644 --- a/src/imgdata.rs +++ b/src/imgdata.rs @@ -9,7 +9,6 @@ pub struct ThinGridData { pub data: Vec, } - impl Clone for ThinGridData { fn clone(&self) -> ThinGridData { ThinGridData { @@ -32,9 +31,10 @@ impl ThinGridData { #[allow(dead_code)] pub fn new_from_grid_vec(in_grids: Vec) -> Vec { - in_grids.iter().map(|grid|{ - Self::new_from_grid(grid) - }).collect() + in_grids + .iter() + .map(|grid| Self::new_from_grid(grid)) + .collect() } // from grid.rs (needed in image gen) @@ -109,13 +109,13 @@ impl ImgData { pub fn save_to_image(&self) { let (width, height) = (self.grids[0].width, self.grids[0].height); let mut img = image::RgbImage::new(width as u32, height as u32); - + let max_values: Vec<_> = self .grids .iter() .map(|grid| grid.quantile(0.999) * 1.5) .collect(); - + for y in 0..height { for x in 0..width { let i = y * width + x; @@ -135,7 +135,7 @@ impl ImgData { img.put_pixel(x as u32, y as u32, image::Rgb([r as u8, g as u8, b as u8])); } } - + img.save(format!("./tmp/out_{}.png", self.iteration).as_str()) .unwrap(); } diff --git a/src/lib.rs b/src/lib.rs index 0cfd952..7093f2c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,8 @@ +mod agent; mod blur; +mod buffer; mod grid; mod imgdata; // for storing image data pub mod model; mod palette; mod util; // for math things -mod agent; -mod buffer; \ No newline at end of file diff --git a/src/model.rs b/src/model.rs index f158222..677820c 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,8 +1,8 @@ use crate::{ + agent::Agent, grid::{combine, Grid}, imgdata::{ImgData, ThinGridData}, palette::{random_palette, Palette}, - agent::Agent, }; use indicatif::{ParallelProgressIterator, ProgressBar, ProgressStyle}; @@ -78,9 +78,8 @@ impl Model { let mut grids: Vec = Vec::new(); for pop in 0..n_populations { let agents = (0..particles_per_grid) - .map(|i| { - Agent::new(width, height, pop, &mut rng, i) - }).collect(); + .map(|i| Agent::new(width, height, pop, &mut rng, i)) + .collect(); grids.push(Grid::new(width, height, &mut rng, agents)); } @@ -123,7 +122,7 @@ impl Model { let agents_tick_time = Instant::now(); // Tick agents - let diffusivity = self.diffusivity; + let diffusivity = self.diffusivity; self.grids.par_iter_mut().for_each(|grid| { grid.tick(); grid.diffuse(diffusivity); // Diffuse + Decay @@ -167,12 +166,16 @@ impl Model { let img_data = ImgData::new(grids, self.palette, self.iteration); self.img_data_vec.push(img_data); let size: usize = self.size_of_imgdata_vec(); - let mb = size/1024/1024; + let mb = size / 1024 / 1024; // println!("{} B | {} KB | {} MB", size, size/1024, size/1024/1024); let max_mb = 6000; if mb >= max_mb { - println!("ram usage is over {} MB (and len of {}), flushing to disk\n", max_mb, self.img_data_vec.len()); + println!( + "ram usage is over {} MB (and len of {}), flushing to disk\n", + max_mb, + self.img_data_vec.len() + ); self.render_all_imgdata(); self.flush_image_data(); }