From fc14961d322fe7151ae2d34092d65c909ef33a25 Mon Sep 17 00:00:00 2001 From: Colin Date: Sat, 5 Sep 2020 17:43:51 -0700 Subject: [PATCH] Render simulations to the terminal and to disk simultaneously --- examples/em_reflection.rs | 6 ++++-- examples/ferromagnet.rs | 6 ++++-- src/render.rs | 36 +++++++++++++++++++++++++++++++----- 3 files changed, 39 insertions(+), 9 deletions(-) diff --git a/examples/em_reflection.rs b/examples/em_reflection.rs index ed847b2..d5f7c5c 100644 --- a/examples/em_reflection.rs +++ b/examples/em_reflection.rs @@ -26,7 +26,9 @@ fn main() { } let mut step = 0u64; - let mut renderer = render::Y4MRenderer::new("test.y4m"); + let mut renderer = render::MultiRenderer::new() + .with(render::Y4MRenderer::new("em_reflection.y4m")) + .with(render::ColorTermRenderer); loop { step += 1; let imp = if step < 50 { @@ -43,6 +45,6 @@ fn main() { } renderer.render(&state); state.step(); - thread::sleep(time::Duration::from_millis(67)); + //thread::sleep(time::Duration::from_millis(67)); } } diff --git a/examples/ferromagnet.rs b/examples/ferromagnet.rs index d8a908e..7c144a4 100644 --- a/examples/ferromagnet.rs +++ b/examples/ferromagnet.rs @@ -45,7 +45,9 @@ fn main() { } } - let mut renderer = render::ColorTermRenderer; + let mut renderer = render::MultiRenderer::new() + .with(render::Y4MRenderer::new("ferromagnet.y4m")) + .with(render::ColorTermRenderer); loop { //let imp = match state.step_no() { // 20..=60 => 1e6, @@ -66,7 +68,7 @@ fn main() { state.impulse_ey(x, y, imp as _); } } - if state.step_no() % 10 == 0 { + if state.step_no() % 1 == 0 { renderer.render(&state); thread::sleep(time::Duration::from_millis(33)); } diff --git a/src/render.rs b/src/render.rs index d186f18..805bc53 100644 --- a/src/render.rs +++ b/src/render.rs @@ -128,7 +128,12 @@ impl ImageRenderExt for RgbImage { } pub trait Renderer { - fn render(&mut self, state: &SimState); + fn render(&mut self, state: &SimState) { + self.render_with_image(state, &state.to_image()); + } + fn render_with_image(&mut self, state: &SimState, _im: &RgbImage) { + self.render(state); + } } pub struct NumericTermRenderer; @@ -154,9 +159,8 @@ impl Renderer for NumericTermRenderer { pub struct ColorTermRenderer; impl Renderer for ColorTermRenderer { - fn render(&mut self, state: &SimState) { + fn render_with_image(&mut self, state: &SimState, im: &RgbImage) { let square = "█"; - let im = state.to_image(); let buf: String = im .enumerate_rows() .map(|(_y, row)| { @@ -185,8 +189,7 @@ impl Y4MRenderer { } impl Renderer for Y4MRenderer { - fn render(&mut self, state: &SimState) { - let im = state.to_image(); + fn render_with_image(&mut self, _state: &SimState, im: &RgbImage) { if self.encoder.is_none() { let writer = File::create(&self.out_path).unwrap(); self.encoder = Some(y4m::encode(im.width() as usize, im.height() as usize, y4m::Ratio::new(30, 1)) @@ -216,3 +219,26 @@ impl Renderer for Y4MRenderer { enc.write_frame(&frame).unwrap() } } + +#[derive(Default)] +pub struct MultiRenderer { + renderers: Vec>, +} + +impl MultiRenderer { + pub fn new() -> Self { + Default::default() + } + pub fn with(mut self, r: R) -> Self { + self.renderers.push(Box::new(r)); + self + } +} + +impl Renderer for MultiRenderer { + fn render_with_image(&mut self, state: &SimState, im: &RgbImage) { + for r in &mut self.renderers { + r.render_with_image(state, im); + } + } +}