Apply a log-like scaling to all values being rendered
This commit is contained in:
10
src/geom.rs
10
src/geom.rs
@@ -91,6 +91,16 @@ impl Point {
|
|||||||
pub fn mag(&self) -> f64 {
|
pub fn mag(&self) -> f64 {
|
||||||
self.mag_sq().sqrt()
|
self.mag_sq().sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn with_mag(&self, new_mag: f64) -> Point {
|
||||||
|
if new_mag == 0.0 {
|
||||||
|
// avoid div-by-zero if self.mag() == 0 and new_mag == 0
|
||||||
|
Point::new(0.0, 0.0)
|
||||||
|
} else {
|
||||||
|
let scale = R64::from_inner(new_mag) / self.mag();
|
||||||
|
self.clone() * scale.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
use ansi_term::Color::RGB;
|
use ansi_term::Color::RGB;
|
||||||
use crate::geom::Point;
|
use crate::geom::Point;
|
||||||
use crate::{Material as _, SimState};
|
use crate::{Material as _, SimState};
|
||||||
|
use decorum::R64;
|
||||||
use image::{RgbImage, Rgb};
|
use image::{RgbImage, Rgb};
|
||||||
use imageproc::{pixelops, drawing};
|
use imageproc::{pixelops, drawing};
|
||||||
use std::convert::TryInto as _;
|
use std::convert::TryInto as _;
|
||||||
@@ -22,6 +23,46 @@ 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: f64, typical: f64) -> f64 {
|
||||||
|
if x >= 0.0 {
|
||||||
|
scale_unsigned(x, typical)
|
||||||
|
} else {
|
||||||
|
-scale_unsigned(-x, typical)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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: f64, typical: f64) -> f64 {
|
||||||
|
// f(0) => 0
|
||||||
|
// f(1) => 0.5
|
||||||
|
// f(\inf) => 1
|
||||||
|
// f(x) = 1 - 1/(x+1)
|
||||||
|
let x = R64::from_inner(x);
|
||||||
|
let typ = R64::from_inner(typical);
|
||||||
|
let y = R64::from_inner(1.0) - R64::from_inner(1.0)/(x/typ + 1.0);
|
||||||
|
y.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale_signed_to_u8(x: f64, typ: f64) -> u8 {
|
||||||
|
let norm = 128.0 + 128.0*scale_signed(x, typ);
|
||||||
|
norm as _
|
||||||
|
}
|
||||||
|
|
||||||
|
fn scale_unsigned_to_u8(x: f64, typ: f64) -> u8 {
|
||||||
|
let norm = 256.0*scale_unsigned(x, typ);
|
||||||
|
norm as _
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Scale a vector to have magnitude between [0, 1).
|
||||||
|
fn scale_vector(x: Point, typical_mag: f64) -> Point {
|
||||||
|
let new_mag = scale_unsigned(x.mag(), typical_mag);
|
||||||
|
x.with_mag(new_mag)
|
||||||
|
}
|
||||||
|
|
||||||
trait SimStateRenderExt {
|
trait SimStateRenderExt {
|
||||||
fn to_image(&self) -> RgbImage;
|
fn to_image(&self) -> RgbImage;
|
||||||
fn e_vector(&self, xidx: u32, yidx: u32, size: u32) -> Point;
|
fn e_vector(&self, xidx: u32, yidx: u32, size: u32) -> Point;
|
||||||
@@ -38,14 +79,15 @@ impl SimStateRenderExt for SimState {
|
|||||||
let cell = self.get(x as usize, y as usize);
|
let cell = self.get(x as usize, y as usize);
|
||||||
//let r = norm_color(cell.bz() * consts::C);
|
//let r = norm_color(cell.bz() * consts::C);
|
||||||
//let r = 0;
|
//let r = 0;
|
||||||
let r = norm_color(cell.mat().mz()*1.0e-2);
|
let r = scale_signed_to_u8(cell.mat().mz(), 100.0);
|
||||||
let b = (55.0*cell.mat().conductivity()).min(255.0) as u8;
|
let b = scale_unsigned_to_u8(cell.mat().conductivity(), 10.0);
|
||||||
//let b = 0;
|
//let b = 0;
|
||||||
//let b = norm_color(cell.ey());
|
//let b = norm_color(cell.ey());
|
||||||
//let g = 0;
|
//let g = 0;
|
||||||
//let g = norm_color(cell.ex());
|
//let g = norm_color(cell.ex());
|
||||||
//let g = norm_color(curl(cell.ex(), cell.ey()));
|
//let g = norm_color(curl(cell.ex(), cell.ey()));
|
||||||
let g = norm_color((cell.bz() * 1.0e4).into());
|
//let g = norm_color((cell.bz() * 1.0e4).into());
|
||||||
|
let g = scale_signed_to_u8(cell.bz(), 1.0e-4);
|
||||||
image.put_pixel(x, y, Rgb([r, g, b]));
|
image.put_pixel(x, y, Rgb([r, g, b]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -54,9 +96,7 @@ impl SimStateRenderExt for SimState {
|
|||||||
for x in 0..w {
|
for x in 0..w {
|
||||||
if x % evec_spacing == 0 && y % evec_spacing == 0 {
|
if x % evec_spacing == 0 && y % evec_spacing == 0 {
|
||||||
let mut vec = self.e_vector(x, y, evec_spacing) * 0.01;
|
let mut vec = self.e_vector(x, y, evec_spacing) * 0.01;
|
||||||
if vec.mag() > evec_spacing as f64 {
|
let vec = scale_vector(self.e_vector(x, y, evec_spacing), 100.0) * (evec_spacing as f64);
|
||||||
vec = vec * (evec_spacing as f64 / vec.mag());
|
|
||||||
}
|
|
||||||
let center = Point::new(x as _, y as _) + Point::new(evec_spacing as _, evec_spacing as _)*0.5;
|
let center = Point::new(x as _, y as _) + Point::new(evec_spacing as _, evec_spacing as _)*0.5;
|
||||||
image.draw_field_arrow(center, vec, Rgb([0xff, 0xff, 0xff]));
|
image.draw_field_arrow(center, vec, Rgb([0xff, 0xff, 0xff]));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user