measurements are now rendered alongside the terminal view

This commit is contained in:
2020-11-29 12:27:52 -08:00
parent 70e6cdf0cb
commit ed86aff504
7 changed files with 94 additions and 67 deletions

View File

@@ -1,15 +1,16 @@
use crate::geom::{Index, Meters, Vec2, Vec3, Vec3u};
use crate::{flt::{Flt, Real}, Material as _};
use crate::mat;
use crate::sim::{Cell, GenericSim};
use crate::sim::{Cell, GenericSim, StaticSim};
use crate::meas::AbstractMeasurement;
use crossterm::{cursor, ExecutableCommand as _, QueueableCommand as _};
use crossterm::style::{style, Color, PrintStyledContent, StyledContent as _};
use crossterm::{cursor, QueueableCommand as _};
use crossterm::style::{style, Color, PrintStyledContent};
use font8x8::{BASIC_FONTS, GREEK_FONTS, UnicodeFonts as _};
use log::{trace, info};
use log::trace;
use plotly;
use image::{RgbImage, Rgb};
use imageproc::{pixelops, drawing};
use serde::{Serialize, Deserialize};
use std::fs::File;
use std::io::{BufWriter, Write as _};
use std::path::PathBuf;
@@ -243,15 +244,15 @@ impl ImageRenderExt for RgbImage {
pub trait Renderer: Send + Sync {
fn render_z_slice(&self, state: &dyn GenericSim, z: u32, measurements: &[Box<dyn AbstractMeasurement>]) {
self.render_with_image(state, &RenderSteps::render(state, measurements, z));
self.render_with_image(state, &RenderSteps::render(state, measurements, z), measurements);
}
fn render(&self, state: &dyn GenericSim, measurements: &[Box<dyn AbstractMeasurement>]) {
self.render_z_slice(state, state.depth() / 2, measurements);
}
/// Not intended to be called directly by users; implement this if you want the image to be
/// computed using default settings and you just manage where to display/save it.
fn render_with_image(&self, state: &dyn GenericSim, _im: &RgbImage) {
self.render(state, &[]);
fn render_with_image(&self, state: &dyn GenericSim, _im: &RgbImage, measurements: &[Box<dyn AbstractMeasurement>]) {
self.render(state, measurements);
}
}
@@ -280,26 +281,34 @@ pub struct ColorTermRenderer;
impl Renderer for ColorTermRenderer {
fn render_z_slice(&self, state: &dyn GenericSim, z: u32, measurements: &[Box<dyn AbstractMeasurement>]) {
let max_size = crossterm::terminal::size().unwrap();
let im = RenderSteps::render_configured(state, measurements, z, (max_size.0 as _, max_size.1 as _));
let (max_w, mut max_h) = crossterm::terminal::size().unwrap();
max_h = max_h.saturating_sub(1 + measurements.len() as u16);
let im = RenderSteps::render_configured(state, &[], z, (max_w as _, max_h as _));
let mut stdout = std::io::stdout();
let (w, h) = crossterm::terminal::size().unwrap();
stdout.queue(cursor::MoveTo(0, 0));
for (y, row) in im.enumerate_rows() {
if y >= h.into() {
break;
}
stdout.queue(cursor::MoveDown(1));
stdout.queue(cursor::MoveToColumn(0));
for (_x, _y, p) in row {
// TODO: consider clearing line-by-line for less tearing?
stdout.queue(crossterm::terminal::Clear(crossterm::terminal::ClearType::All)).unwrap();
stdout.queue(cursor::MoveTo(0, 0)).unwrap();
for row in im.rows() {
stdout.queue(cursor::MoveDown(1)).unwrap();
stdout.queue(cursor::MoveToColumn(0)).unwrap();
for p in row {
stdout.queue(PrintStyledContent(style(" ").on(Color::Rgb {
r: p.0[0],
g: p.0[1],
b: p.0[2],
})));
}))).unwrap();
}
}
stdout.flush();
stdout.queue(cursor::MoveDown(1)).unwrap();
stdout.queue(cursor::MoveToColumn(1)).unwrap();
stdout.queue(PrintStyledContent(style(format!("z: {}", z)))).unwrap();
for m in measurements {
let meas_string = m.eval(state);
stdout.queue(cursor::MoveDown(1)).unwrap();
stdout.queue(cursor::MoveToColumn(1)).unwrap();
stdout.queue(PrintStyledContent(style(meas_string))).unwrap();
}
stdout.flush().unwrap();
}
}
@@ -318,7 +327,7 @@ impl Y4MRenderer {
}
impl Renderer for Y4MRenderer {
fn render_with_image(&self, _state: &dyn GenericSim, im: &RgbImage) {
fn render_with_image(&self, _state: &dyn GenericSim, im: &RgbImage, _meas: &[Box<dyn AbstractMeasurement>]) {
{
let mut enc = self.encoder.lock().unwrap();
if enc.is_none() {
@@ -385,9 +394,9 @@ impl PlotlyRenderer {
}
impl Renderer for PlotlyRenderer {
fn render(&self, state: &dyn GenericSim, measurements: &[Box<dyn AbstractMeasurement>]) {
use plotly::{ImageFormat, Plot, Rgba, Scatter};
use plotly::common::Marker;
fn render(&self, state: &dyn GenericSim, _meas: &[Box<dyn AbstractMeasurement>]) {
use plotly::{ImageFormat, Plot, Rgba};
// use plotly::common::Marker;
use plotly::layout::{AspectMode, Axis, Layout, LayoutScene};
let mut plot = Plot::new();
let scene = LayoutScene::new()
@@ -463,7 +472,7 @@ impl MultiRenderer {
pub fn push<R: Renderer + 'static>(&self, r: R) {
self.renderers.write().unwrap().push(Box::new(r));
}
pub fn with<R: Renderer + 'static>(mut self, r: R) -> Self {
pub fn with<R: Renderer + 'static>(self, r: R) -> Self {
self.push(r);
self
}
@@ -472,17 +481,23 @@ impl MultiRenderer {
impl Renderer for MultiRenderer {
fn render(&self, state: &dyn GenericSim, measurements: &[Box<dyn AbstractMeasurement>]) {
if self.renderers.read().unwrap().len() != 0 {
self.render_with_image(state, &RenderSteps::render(state, measurements, state.depth() / 2));
self.render_with_image(state, &RenderSteps::render(state, measurements, state.depth() / 2), measurements);
}
}
fn render_with_image(&self, state: &dyn GenericSim, im: &RgbImage) {
fn render_with_image(&self, state: &dyn GenericSim, im: &RgbImage, measurements: &[Box<dyn AbstractMeasurement>]) {
for r in &*self.renderers.read().unwrap() {
r.render_with_image(state, im);
r.render_with_image(state, im, measurements);
}
}
}
#[derive(Serialize, Deserialize)]
pub struct SerializedFrame {
pub state: StaticSim,
pub measurements: Vec<Box<dyn AbstractMeasurement>>,
}
pub struct SerializerRenderer {
out_base: String
}
@@ -498,9 +513,13 @@ impl SerializerRenderer {
impl Renderer for SerializerRenderer {
fn render(&self, state: &dyn GenericSim, measurements: &[Box<dyn AbstractMeasurement>]) {
let snap = state.to_static();
let name = format!("{}{}.bc", self.out_base, snap.step_no());
let frame = SerializedFrame {
state: snap,
measurements: measurements.iter().cloned().collect(),
};
let name = format!("{}{}.bc", self.out_base, frame.state.step_no());
let out = BufWriter::new(File::create(name).unwrap());
//serde_cbor::to_writer(out, &snap).unwrap();
bincode::serialize_into(out, &snap).unwrap();
bincode::serialize_into(out, &frame).unwrap();
}
}