Created
October 11, 2023 20:16
-
-
Save wchargin/fddc5a325e8f2e133dae521b080d7cbb to your computer and use it in GitHub Desktop.
dump flow fields before and after disturbances
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/art.rs b/src/art.rs | |
index bcba7e0..1d99457 100644 | |
--- a/src/art.rs | |
+++ b/src/art.rs | |
@@ -548,10 +548,84 @@ impl FlowField { | |
} => Self::raw_circular(*circularity, *direction, *rotation, traits.version, rng), | |
}; | |
let disturbances = Disturbance::build(traits, rng); | |
+ ff.dump(&[], "flowfield0_initial.png").unwrap(); | |
+ ff.dump(&disturbances, "flowfield1_disturbances.png") | |
+ .unwrap(); | |
ff.adjust(&disturbances); | |
+ ff.dump(&disturbances, "flowfield2_disturbed.png").unwrap(); | |
+ ff.dump(&[], "flowfield3_disturbed_clean.png").unwrap(); | |
+ panic!("goodbye"); | |
ff | |
} | |
+ fn dump(&self, disturbances: &[Disturbance], to: &str) -> anyhow::Result<()> { | |
+ let mut dt = DrawTarget::new(VIRTUAL_W as i32, VIRTUAL_H as i32); | |
+ dt.clear(Rgb(200.0, 200.0, 200.0).to_solid_source()); | |
+ // The flow field is dense; only show every `n`th point on each axis. | |
+ let step = 6; | |
+ for (x, col) in self.0.iter().enumerate().step_by(step) { | |
+ for (y, theta) in col.iter().enumerate().step_by(step) { | |
+ let mut pb = PathBuilder::new(); | |
+ let half_length = SPC as f32 * step as f32 * 0.5; | |
+ let (x, y) = (x as f32 * SPC as f32, y as f32 * SPC as f32); | |
+ let (cos, sin) = (theta.cos() as f32, theta.sin() as f32); | |
+ pb.move_to(x - cos * half_length, y - sin * half_length); | |
+ pb.line_to(x + cos * half_length, y + sin * half_length); | |
+ let path = pb.finish(); | |
+ | |
+ let mut total_disturbance = 0.0; | |
+ for d in disturbances { | |
+ let dist = dist(d.center, (x as f64, y as f64)); | |
+ let theta_adjust = rescale(dist, (0.0, d.radius), (d.theta, 0.0)); | |
+ total_disturbance += theta_adjust; | |
+ } | |
+ total_disturbance = (-total_disturbance / std::f64::consts::TAU).rem_euclid(1.0); | |
+ // Color `total_disturbance` based on how close it is to `base` (on S^1 topology). | |
+ let redblue = |base: f64| -> u8 { | |
+ let mut diff = (total_disturbance - base).abs(); | |
+ if diff > 0.5 { | |
+ diff = 1.0 - diff; | |
+ } | |
+ let fac = (diff * 4.0 - 0.5).clamp(0.0, 1.0); | |
+ (fac * 512.0).clamp(0.0, 255.0) as u8 | |
+ }; | |
+ let color = Source::Solid(SolidSource { | |
+ r: redblue(7.0 / 8.0), | |
+ g: 0, | |
+ b: redblue(1.0 / 8.0), | |
+ a: 255, | |
+ }); | |
+ | |
+ let mut style = StrokeStyle::default(); | |
+ style.width = 4.0; | |
+ dt.stroke(&path, &color, &style, &DrawOptions::new()); | |
+ } | |
+ } | |
+ for d in disturbances { | |
+ let mut pb = PathBuilder::new(); | |
+ pb.arc( | |
+ d.center.0 as f32, | |
+ d.center.1 as f32, | |
+ d.radius as f32, | |
+ 0.0, | |
+ std::f32::consts::TAU, | |
+ ); | |
+ let path = pb.finish(); | |
+ let theta_rel = (d.theta * 100.0).clamp(-255.0, 255.0); | |
+ let color = Source::Solid(SolidSource { | |
+ r: theta_rel.max(0.0) as u8, | |
+ g: 0, | |
+ b: -theta_rel.min(0.0) as u8, | |
+ a: theta_rel.abs() as u8, | |
+ }); | |
+ let mut style = StrokeStyle::default(); | |
+ style.width = 4.0; | |
+ dt.stroke(&path, &color, &style, &DrawOptions::new()); | |
+ } | |
+ dt.write_png(to)?; | |
+ Ok(()) | |
+ } | |
+ | |
fn constant_flow_field(theta: f64) -> Box<[[f64; FLOW_FIELD_ROWS]; FLOW_FIELD_COLS]> { | |
let vec_of_arrays = vec![[theta; FLOW_FIELD_ROWS]; FLOW_FIELD_COLS]; | |
let slice_of_arrays = vec_of_arrays.into_boxed_slice(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment