Make vector field rendering logic generic

This commit is contained in:
2020-09-07 21:14:26 -07:00
parent 0b9861d619
commit 0c6a01c671

View File

@@ -1,6 +1,8 @@
use ansi_term::Color::RGB;
use crate::geom::Point;
use crate::{Material as _, SimSnapshot, SimState};
use crate::mat;
use crate::sim::Cell;
use crate::meas::AbstractMeasurement;
use decorum::R64;
use font8x8::{BASIC_FONTS, UnicodeFonts as _};
@@ -87,23 +89,26 @@ impl<'a> RenderSteps<'a> {
}
}
}
fn render_e_field(&mut self) {
fn render_vector_field<F: Fn(&Cell<mat::Static>) -> Point>(&mut self, color: Rgb<u8>, measure: F) {
let w = self.sim.width();
let h = self.sim.height();
let evec_spacing = 10;
let vec_spacing = 10;
for y in 0..h {
for x in 0..w {
if x % evec_spacing == 0 && y % evec_spacing == 0 {
let evec = self.e_vector(x, y, evec_spacing);
let norm_vec = scale_vector(evec, 100.0);
let alpha = scale_unsigned(evec.mag_sq(), 500.0);
let vec = norm_vec * (evec_spacing as f64);
let center = Point::new(x as _, y as _) + Point::new(evec_spacing as _, evec_spacing as _)*0.5;
self.im.draw_field_arrow(center, vec, Rgb([0xff, 0xff, 0xff]), alpha as f32);
if x % vec_spacing == 0 && y % vec_spacing == 0 {
let vec = self.field_vector(x, y, vec_spacing, &measure);
let norm_vec = scale_vector(vec, 100.0);
let alpha = scale_unsigned(vec.mag_sq(), 500.0);
let vec = norm_vec * (vec_spacing as f64);
let center = Point::new(x as _, y as _) + Point::new(vec_spacing as _, vec_spacing as _)*0.5;
self.im.draw_field_arrow(center, vec, color, alpha as f32);
}
}
}
}
fn render_e_field(&mut self) {
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), |cell| cell.e());
}
fn render_measurements(&mut self) {
for (meas_no, m) in self.meas.iter().enumerate() {
let meas_string = m.eval(self.sim);
@@ -124,8 +129,8 @@ impl<'a> RenderSteps<'a> {
}
}
fn e_vector(&self, xidx: u32, yidx: u32, size: u32) -> Point {
let mut e = Point::default();
fn field_vector<F: Fn(&Cell<mat::Static>) -> Point>(&self, xidx: u32, yidx: u32, size: u32, measure: &F) -> Point {
let mut field = Point::default();
let w = self.sim.width();
let h = self.sim.height();
let xstart = xidx.min(w);
@@ -134,7 +139,7 @@ impl<'a> RenderSteps<'a> {
let yend = (ystart + size).min(h);
for y in ystart..yend {
for x in xstart..xend {
e += self.sim.get(x, y).e();
field += measure(self.sim.get(x, y));
}
}
let xw = xend - xstart;
@@ -143,7 +148,7 @@ impl<'a> RenderSteps<'a> {
// avoid division by zero
Point::new(0.0, 0.0)
} else {
e * (1.0 / ((xw*yw) as f64))
field * (1.0 / ((xw*yw) as f64))
}
}
}