measurements are now rendered alongside the terminal view
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user