Parameterize 2d geometry types over the Float type
I'll work toward parameterizing more geometry (Vec3); this is just a starting point.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use crate::geom::{Index, Meters, Vec2, Vec3, Vec3u};
|
||||
use crate::{flt::{Flt, Real}, Material as _, MaterialExt as _};
|
||||
use crate::{Material as _, MaterialExt as _};
|
||||
use crate::mat;
|
||||
use crate::sim::{Cell, GenericSim, StaticSim};
|
||||
use crate::meas::AbstractMeasurement;
|
||||
@@ -22,7 +22,7 @@ use y4m;
|
||||
/// Accept a value from (-\inf, \inf) and return a value in (-1, 1).
|
||||
/// If the input is equal to `typical`, it will be mapped to 0.5.
|
||||
/// If the input is equal to -`typical`, it will be mapped to -0.5.
|
||||
fn scale_signed(x: Flt, typical: Flt) -> Flt {
|
||||
fn scale_signed(x: f32, typical: f32) -> f32 {
|
||||
if x >= 0.0 {
|
||||
scale_unsigned(x, typical)
|
||||
} else {
|
||||
@@ -32,29 +32,26 @@ fn scale_signed(x: Flt, typical: Flt) -> Flt {
|
||||
|
||||
/// Accept a value from [0, \inf) and return a value in [0, 1).
|
||||
/// If the input is equal to `typical`, it will be mapped to 0.5.
|
||||
fn scale_unsigned(x: Flt, typical: Flt) -> Flt {
|
||||
fn scale_unsigned(x: f32, typical: f32) -> f32 {
|
||||
// f(0) => 0
|
||||
// f(1) => 0.5
|
||||
// f(\inf) => 1
|
||||
// f(x) = 1 - 1/(x+1)
|
||||
let x = Real::from_inner(x);
|
||||
let typ = Real::from_inner(typical);
|
||||
let y = Real::from_inner(1.0) - Real::from_inner(1.0)/(x/typ + 1.0);
|
||||
y.into()
|
||||
1.0 - 1.0/(x/typical + 1.0)
|
||||
}
|
||||
|
||||
fn scale_signed_to_u8(x: Flt, typ: Flt) -> u8 {
|
||||
fn scale_signed_to_u8(x: f32, typ: f32) -> u8 {
|
||||
let norm = 128.0 + 128.0*scale_signed(x, typ);
|
||||
norm as _
|
||||
}
|
||||
|
||||
fn scale_unsigned_to_u8(x: Flt, typ: Flt) -> u8 {
|
||||
fn scale_unsigned_to_u8(x: f32, typ: f32) -> u8 {
|
||||
let norm = 256.0*scale_unsigned(x, typ);
|
||||
norm as _
|
||||
}
|
||||
|
||||
/// Scale a vector to have magnitude between [0, 1).
|
||||
fn scale_vector(x: Vec2, typical_mag: Flt) -> Vec2 {
|
||||
fn scale_vector(x: Vec2<f32>, typical_mag: f32) -> Vec2<f32> {
|
||||
let new_mag = scale_unsigned(x.mag(), typical_mag);
|
||||
x.with_mag(new_mag)
|
||||
}
|
||||
@@ -103,7 +100,7 @@ impl FieldDisplayMode {
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct RenderConfig {
|
||||
mode: FieldDisplayMode,
|
||||
scale: Flt,
|
||||
scale: f32,
|
||||
}
|
||||
|
||||
impl Default for RenderConfig {
|
||||
@@ -155,7 +152,7 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
||||
trace!("rendering at {}x{} with z={}", width, height, z);
|
||||
let mut me = Self::new(state, measurements, width, height, z);
|
||||
me.render_scalar_field(10.0, false, 2, |cell| {
|
||||
cell.mat().conductivity().mag() + if cell.mat().is_vacuum() {
|
||||
cell.mat().conductivity().mag() as f32 + if cell.mat().is_vacuum() {
|
||||
0.0
|
||||
} else {
|
||||
5.0
|
||||
@@ -191,49 +188,49 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
||||
}
|
||||
|
||||
fn get_at_px(&self, x_px: u32, y_px: u32) -> Cell {
|
||||
let x_prop = x_px as Flt / self.im.width() as Flt;
|
||||
let x_m = x_prop * (self.sim.width() as Flt * self.sim.feature_size());
|
||||
let y_prop = y_px as Flt / self.im.height() as Flt;
|
||||
let y_m = y_prop * (self.sim.height() as Flt * self.sim.feature_size());
|
||||
let z_m = self.z as Flt * self.sim.feature_size();
|
||||
self.sim.sample(Meters(Vec3::new(x_m, y_m, z_m)))
|
||||
let x_prop = x_px as f32 / self.im.width() as f32;
|
||||
let x_m = x_prop * (self.sim.width() as f32 * self.sim.feature_size() as f32);
|
||||
let y_prop = y_px as f32 / self.im.height() as f32;
|
||||
let y_m = y_prop * (self.sim.height() as f32 * self.sim.feature_size() as f32);
|
||||
let z_m = self.z as f32 * self.sim.feature_size() as f32;
|
||||
self.sim.sample(Meters(Vec3::new(x_m as _, y_m as _, z_m as _)))
|
||||
}
|
||||
|
||||
////////////// Ex/Ey/Bz configuration ////////////
|
||||
fn render_b_z_field(&mut self, scale: Flt) {
|
||||
self.render_scalar_field(1.0e-4 * scale, true, 1, |cell| cell.b().z());
|
||||
fn render_b_z_field(&mut self, scale: f32) {
|
||||
self.render_scalar_field(1.0e-4 * scale, true, 1, |cell| cell.b().z() as f32);
|
||||
}
|
||||
fn render_e_xy_field(&mut self, scale: Flt) {
|
||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 100.0 * scale, |cell| cell.e().xy());
|
||||
fn render_e_xy_field(&mut self, scale: f32) {
|
||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 100.0 * scale, |cell| cell.e().xy().to_f32());
|
||||
// current
|
||||
self.render_vector_field(Rgb([0x00, 0xa0, 0x30]), 1.0e-12 * scale, |cell| {
|
||||
cell.e().elem_mul(cell.mat().conductivity()).xy()
|
||||
cell.e().elem_mul(cell.mat().conductivity()).xy().to_f32()
|
||||
});
|
||||
}
|
||||
////////////// Magnitude configuration /////////////
|
||||
fn render_b(&mut self, scale: Flt) {
|
||||
self.render_scalar_field(1.0e-3 * scale, false, 1, |cell| cell.b().mag());
|
||||
fn render_b(&mut self, scale: f32) {
|
||||
self.render_scalar_field(1.0e-3 * scale, false, 1, |cell| cell.b().mag() as f32);
|
||||
}
|
||||
fn render_current(&mut self, scale: Flt) {
|
||||
fn render_current(&mut self, scale: f32) {
|
||||
self.render_scalar_field(1.0e1 * scale, false, 0, |cell| {
|
||||
cell.e().elem_mul(cell.mat().conductivity()).mag()
|
||||
cell.e().elem_mul(cell.mat().conductivity()).mag() as f32
|
||||
});
|
||||
}
|
||||
|
||||
////////////// Bx/By/Ez configuration ////////////
|
||||
fn render_e_z_field(&mut self, scale: Flt) {
|
||||
self.render_scalar_field(1e4 * scale, true, 1, |cell| cell.e().z());
|
||||
fn render_e_z_field(&mut self, scale: f32) {
|
||||
self.render_scalar_field(1e4 * scale, true, 1, |cell| cell.e().z() as f32);
|
||||
}
|
||||
fn render_b_xy_field(&mut self, scale: Flt) {
|
||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 1.0e-9 * scale, |cell| cell.b().xy());
|
||||
fn render_b_xy_field(&mut self, scale: f32) {
|
||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 1.0e-9 * scale, |cell| cell.b().xy().to_f32());
|
||||
}
|
||||
|
||||
fn render_m(&mut self, scale: Flt) {
|
||||
self.render_scalar_field(1.0e5 * scale, false, 1, |cell| cell.mat().m().mag());
|
||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 1.0e5 * scale, |cell| cell.mat().m().xy());
|
||||
fn render_m(&mut self, scale: f32) {
|
||||
self.render_scalar_field(1.0e5 * scale, false, 1, |cell| cell.mat().m().mag() as f32);
|
||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 1.0e5 * scale, |cell| cell.mat().m().xy().to_f32());
|
||||
}
|
||||
|
||||
fn render_vector_field<F: Fn(&Cell<mat::Static>) -> Vec2>(&mut self, color: Rgb<u8>, typical: Flt, measure: F) {
|
||||
fn render_vector_field<F: Fn(&Cell<mat::Static>) -> Vec2<f32>>(&mut self, color: Rgb<u8>, typical: f32, measure: F) {
|
||||
let w = self.im.width();
|
||||
let h = self.im.height();
|
||||
let vec_spacing = 10;
|
||||
@@ -242,13 +239,13 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
||||
let vec = self.field_vector(x, y, vec_spacing, &measure);
|
||||
let norm_vec = scale_vector(vec, typical);
|
||||
let alpha = 0.7*scale_unsigned(vec.mag_sq(), typical * 5.0);
|
||||
let vec = norm_vec * (vec_spacing as Flt);
|
||||
let center = Vec2::new(x as _, y as _) + Vec2::new(vec_spacing as _, vec_spacing as _)*0.5;
|
||||
let vec = norm_vec * (vec_spacing as f32);
|
||||
let center = Vec2::new(x as f32, y as f32) + Vec2::new(vec_spacing as f32, vec_spacing as f32)*0.5;
|
||||
self.im.draw_field_arrow(center, vec, color, alpha as f32);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn render_scalar_field<F: Fn(&Cell<mat::Static>) -> Flt + Sync>(&mut self, typical: Flt, signed: bool, slot: u32, measure: F) {
|
||||
fn render_scalar_field<F: Fn(&Cell<mat::Static>) -> f32 + Sync>(&mut self, typical: f32, signed: bool, slot: u32, measure: F) {
|
||||
// XXX: get_at_px borrows self, so we need to clone the image to operate on it mutably.
|
||||
let mut im = self.im.clone();
|
||||
let w = im.width();
|
||||
@@ -294,7 +291,7 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
||||
}
|
||||
}
|
||||
|
||||
fn field_vector<F: Fn(&Cell<mat::Static>) -> Vec2>(&self, xidx: u32, yidx: u32, size: u32, measure: &F) -> Vec2 {
|
||||
fn field_vector<F: Fn(&Cell<mat::Static>) -> Vec2<f32>>(&self, xidx: u32, yidx: u32, size: u32, measure: &F) -> Vec2<f32> {
|
||||
let mut field = Vec2::default();
|
||||
let w = self.im.width();
|
||||
let h = self.im.height();
|
||||
@@ -313,17 +310,17 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
||||
// avoid division by zero
|
||||
Vec2::new(0.0, 0.0)
|
||||
} else {
|
||||
field * (1.0 / ((xw*yw) as Flt))
|
||||
field * (1.0 / ((xw*yw) as f32))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ImageRenderExt {
|
||||
fn draw_field_arrow(&mut self, center: Vec2, rel: Vec2, color: Rgb<u8>, alpha: f32);
|
||||
fn draw_field_arrow(&mut self, center: Vec2<f32>, rel: Vec2<f32>, color: Rgb<u8>, alpha: f32);
|
||||
}
|
||||
|
||||
impl ImageRenderExt for RgbImage {
|
||||
fn draw_field_arrow(&mut self, center: Vec2, rel: Vec2, color: Rgb<u8>, alpha: f32) {
|
||||
fn draw_field_arrow(&mut self, center: Vec2<f32>, rel: Vec2<f32>, color: Rgb<u8>, alpha: f32) {
|
||||
let start = (center - rel * 0.5).round();
|
||||
let end = (center + rel * 0.5).round();
|
||||
let i_start = (start.x().round() as _, start.y().round() as _);
|
||||
@@ -569,9 +566,9 @@ impl<S: GenericSim> Renderer<S> for PlotlyRenderer {
|
||||
//let g = scale_unsigned_to_u8(mat, 10.0);
|
||||
//let r = scale_unsigned_to_u8(cell.mat().m().mag(), 100.0);
|
||||
//let b = scale_unsigned_to_u8(cell.e().mag(), 1e2);
|
||||
let r = scale_unsigned_to_u8(cell.mat().m().mag(), 100.0);
|
||||
let g = scale_unsigned_to_u8(cell.e().mag(), 1e2);
|
||||
let b = scale_unsigned_to_u8(mat, 10.0);
|
||||
let r = scale_unsigned_to_u8(cell.mat().m().mag() as f32, 100.0);
|
||||
let g = scale_unsigned_to_u8(cell.e().mag() as f32, 1e2);
|
||||
let b = scale_unsigned_to_u8(mat as f32, 10.0);
|
||||
let alpha = 1.0;
|
||||
colors.push(Rgba::new(r, g, b, alpha));
|
||||
}
|
||||
|
Reference in New Issue
Block a user