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:
@@ -91,7 +91,7 @@ fn main() {
|
|||||||
Meters((half_width + 0.5 * (ferro_inner_rad + ferro_outer_rad), half_width, half_depth).into())
|
Meters((half_width + 0.5 * (ferro_inner_rad + ferro_outer_rad), half_width, half_depth).into())
|
||||||
));
|
));
|
||||||
|
|
||||||
let center = Vec2::new(half_width as _, half_width as _);
|
let center = Vec2::new(half_width as Flt, half_width as Flt);
|
||||||
|
|
||||||
for z_px in 0..depth_px {
|
for z_px in 0..depth_px {
|
||||||
for y_px in 0..width_px {
|
for y_px in 0..width_px {
|
||||||
@@ -99,9 +99,9 @@ fn main() {
|
|||||||
let loc = Index((x_px, y_px, z_px).into());
|
let loc = Index((x_px, y_px, z_px).into());
|
||||||
let d = Vec2::new(to_m(x_px), to_m(y_px)) - center;
|
let d = Vec2::new(to_m(x_px), to_m(y_px)) - center;
|
||||||
let r = d.mag();
|
let r = d.mag();
|
||||||
if (conductor_inner_rad as _..conductor_outer_rad as _).contains(&r) {
|
if (conductor_inner_rad as Flt..conductor_outer_rad as Flt).contains(&r) {
|
||||||
driver.state.put_material(loc, mat::db::conductor(conductivity).into());
|
driver.state.put_material(loc, mat::db::conductor(conductivity).into());
|
||||||
} else if (ferro_inner_rad as _..ferro_outer_rad as _).contains(&r) {
|
} else if (ferro_inner_rad as Flt..ferro_outer_rad as Flt).contains(&r) {
|
||||||
let half_depth_px = from_m(half_depth);
|
let half_depth_px = from_m(half_depth);
|
||||||
let ferro_depth_px = from_m(ferro_depth);
|
let ferro_depth_px = from_m(ferro_depth);
|
||||||
if (half_depth_px-ferro_depth_px/2 .. half_depth_px+(ferro_depth_px+1)/2).contains(&z_px) {
|
if (half_depth_px-ferro_depth_px/2 .. half_depth_px+(ferro_depth_px+1)/2).contains(&z_px) {
|
||||||
|
121
src/geom/mod.rs
121
src/geom/mod.rs
@@ -8,69 +8,68 @@ pub use units::{Coord, Meters, Index};
|
|||||||
pub use vec::{Vec2, Vec3};
|
pub use vec::{Vec2, Vec3};
|
||||||
pub use vecu::Vec3u;
|
pub use vecu::Vec3u;
|
||||||
|
|
||||||
use crate::flt::{Flt, Real};
|
use crate::flt;
|
||||||
|
use crate::real::Real;
|
||||||
use std::ops::Add;
|
use std::ops::Add;
|
||||||
|
|
||||||
fn real(f: Flt) -> Real {
|
|
||||||
Real::from_inner(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
pub struct Line2d {
|
pub struct Line2d<R=flt::Real> {
|
||||||
from: Vec2,
|
from: Vec2<R>,
|
||||||
to: Vec2,
|
to: Vec2<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for Line2d {
|
impl<R: Real> Add for Line2d<R> {
|
||||||
type Output = Line2d;
|
type Output = Self;
|
||||||
fn add(self, other: Line2d) -> Line2d {
|
fn add(self, other: Self) -> Self {
|
||||||
Line2d {
|
Line2d {
|
||||||
from: self.from + Vec2::new(0.0, other.y(self.from.x())),
|
from: self.from + Vec2::new(R::zero(), other.y(self.from.x())),
|
||||||
to: self.to + Vec2::new(0.0, other.y(self.to.x())),
|
to: self.to + Vec2::new(R::zero(), other.y(self.to.x())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Line2d {
|
impl<R> Line2d<R> {
|
||||||
pub fn new(from: Vec2, to: Vec2) -> Self {
|
pub fn new(from: Vec2<R>, to: Vec2<R>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn x(&self, y: Flt) -> Flt {
|
impl<R: Real> Line2d<R> {
|
||||||
self.shifted(Vec2::new(0.0, -y)).x_intercept()
|
pub fn from(&self) -> Vec2<R> {
|
||||||
}
|
|
||||||
pub fn y(&self, x: Flt) -> Flt {
|
|
||||||
(self.from.y + (real(x) - self.from.x) * self.slope()).into()
|
|
||||||
}
|
|
||||||
pub fn at_x(&self, x: Flt) -> Vec2 {
|
|
||||||
Vec2::new(x, self.y(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from(&self) -> Vec2 {
|
|
||||||
self.from
|
self.from
|
||||||
}
|
}
|
||||||
pub fn to(&self) -> Vec2 {
|
pub fn to(&self) -> Vec2<R> {
|
||||||
self.to
|
self.to
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn x_intercept(&self) -> Flt {
|
pub fn x(&self, y: R) -> R {
|
||||||
|
self.shifted(Vec2::new(R::zero(), -y)).x_intercept()
|
||||||
|
}
|
||||||
|
pub fn y(&self, x: R) -> R {
|
||||||
|
(self.from.y + (x - self.from.x) * self.slope()).into()
|
||||||
|
}
|
||||||
|
pub fn at_x(&self, x: R) -> Vec2<R> {
|
||||||
|
Vec2::new(x, self.y(x))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn x_intercept(&self) -> R {
|
||||||
let t = (-self.from.y) / (self.to.y - self.from.y);
|
let t = (-self.from.y) / (self.to.y - self.from.y);
|
||||||
(self.from.x + t * (self.to.x - self.from.x)).into()
|
(self.from.x + t * (self.to.x - self.from.x)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_vector(&self) -> Vec2 {
|
pub fn as_vector(&self) -> Vec2<R> {
|
||||||
self.to + (-self.from)
|
self.to + (-self.from)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn length_sq(&self) -> Flt {
|
pub fn length_sq(&self) -> R {
|
||||||
let Vec2 { x, y } = self.as_vector();
|
let Vec2 { x, y } = self.as_vector();
|
||||||
(x*x + y*y).into()
|
(x*x + y*y).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn distance_sq(&self, pt: Vec2) -> Flt {
|
pub fn distance_sq(&self, pt: Vec2<R>) -> R {
|
||||||
// source: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points
|
// source: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points
|
||||||
let d = self.as_vector();
|
let d = self.as_vector();
|
||||||
let twice_area = d.y*pt.x - d.x*pt.y + self.to.x*self.from.y - self.to.y*self.from.x;
|
let twice_area = d.y*pt.x - d.x*pt.y + self.to.x*self.from.y - self.to.y*self.from.x;
|
||||||
@@ -86,8 +85,7 @@ impl Line2d {
|
|||||||
self.to.x > self.from.x
|
self.to.x > self.from.x
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_x(&self, x: Flt) -> bool {
|
pub fn contains_x(&self, x: R) -> bool {
|
||||||
let x = real(x);
|
|
||||||
if self.is_ascending_x() {
|
if self.is_ascending_x() {
|
||||||
x >= self.from.x && x < self.to.x
|
x >= self.from.x && x < self.to.x
|
||||||
} else {
|
} else {
|
||||||
@@ -95,8 +93,7 @@ impl Line2d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_y(&self, y: Flt) -> bool {
|
pub fn contains_y(&self, y: R) -> bool {
|
||||||
let y = real(y);
|
|
||||||
if self.is_ascending_x() {
|
if self.is_ascending_x() {
|
||||||
y >= self.from.y && y < self.to.y
|
y >= self.from.y && y < self.to.y
|
||||||
} else {
|
} else {
|
||||||
@@ -104,15 +101,15 @@ impl Line2d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min_x(&self) -> Flt {
|
pub fn min_x(&self) -> R {
|
||||||
self.from.x.min(self.to.x).into()
|
self.from.x.min_or_undefined(&self.to.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_x(&self) -> Flt {
|
pub fn max_x(&self) -> R {
|
||||||
self.from.x.max(self.to.x).into()
|
self.from.x.max_or_undefined(&self.to.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clamp_x(&self, x: Flt) -> Flt {
|
pub fn clamp_x(&self, x: R) -> R {
|
||||||
match x {
|
match x {
|
||||||
v if v < self.min_x() => self.min_x(),
|
v if v < self.min_x() => self.min_x(),
|
||||||
v if v > self.max_x() => self.max_x(),
|
v if v > self.max_x() => self.max_x(),
|
||||||
@@ -120,24 +117,23 @@ impl Line2d {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clamp_by_x(&self, x: Flt) -> Vec2 {
|
pub fn clamp_by_x(&self, x: R) -> Vec2<R> {
|
||||||
self.at_x(self.clamp_x(x))
|
self.at_x(self.clamp_x(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slope(&self) -> Flt {
|
pub fn slope(&self) -> R {
|
||||||
let s = (self.to.y - self.from.y) / (self.to.x - self.from.x);
|
(self.to.y - self.from.y) / (self.to.x - self.from.x)
|
||||||
s.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the coordinate along the line toward some desired `y(x)` value.
|
/// Move the coordinate along the line toward some desired `y(x)` value.
|
||||||
/// The returned value could be OOB: check `self.contains_x` to find out.
|
/// The returned value could be OOB: check `self.contains_x` to find out.
|
||||||
pub fn move_toward_y_unclamped(&self, start_x: Flt, target_y: Flt) -> Flt {
|
pub fn move_toward_y_unclamped(&self, start_x: R, target_y: R) -> R {
|
||||||
let start_y = self.y(start_x);
|
let start_y = self.y(start_x);
|
||||||
let delta_x = real(target_y - start_y) / self.slope();
|
let delta_x = (target_y - start_y) / self.slope();
|
||||||
(real(start_x) + delta_x).into()
|
start_x + delta_x
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shifted(&self, p: Vec2) -> Line2d {
|
pub fn shifted(&self, p: Vec2<R>) -> Self {
|
||||||
Line2d {
|
Line2d {
|
||||||
from: self.from + p,
|
from: self.from + p,
|
||||||
to: self.to + p
|
to: self.to + p
|
||||||
@@ -146,39 +142,40 @@ impl Line2d {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Polygon2d {
|
pub struct Polygon2d<R=flt::Real> {
|
||||||
points: Vec<Vec2>,
|
points: Vec<Vec2<R>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Polygon2d {
|
impl<R> Polygon2d<R> {
|
||||||
pub fn new(points: Vec<Vec2>) -> Self {
|
pub fn new(points: Vec<Vec2<R>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
points
|
points
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn segments<'a>(&'a self) -> impl Iterator<Item=Line2d> + 'a {
|
impl<R: Real> Polygon2d<R> {
|
||||||
|
pub fn segments<'a>(&'a self) -> impl Iterator<Item=Line2d<R>> + 'a {
|
||||||
(0..self.points.len()).into_iter().map(move |i| {
|
(0..self.points.len()).into_iter().map(move |i| {
|
||||||
let from = self.points[i];
|
let from = self.points[i];
|
||||||
let to = *self.points.get(i+1).unwrap_or_else(|| &self.points[0]);
|
let to = *self.points.get(i+1).unwrap_or_else(|| &self.points[0]);
|
||||||
Line2d { from, to }
|
Line2d { from, to }
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
pub fn min_x(&self) -> R {
|
||||||
pub fn min_x(&self) -> Flt {
|
self.points.iter().map(|p| p.x).reduce(|p, q| p.min_or_undefined(&q)).unwrap()
|
||||||
self.points.iter().map(|p| p.x).min().unwrap().into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_x(&self) -> Flt {
|
pub fn max_x(&self) -> R {
|
||||||
self.points.iter().map(|p| p.x).max().unwrap().into()
|
self.points.iter().map(|p| p.x).reduce(|p, q| p.max_or_undefined(&q)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn min_y(&self) -> Flt {
|
pub fn min_y(&self) -> R {
|
||||||
self.points.iter().map(|p| p.y).min().unwrap().into()
|
self.points.iter().map(|p| p.y).reduce(|p, q| p.min_or_undefined(&q)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_y(&self) -> Flt {
|
pub fn max_y(&self) -> R {
|
||||||
self.points.iter().map(|p| p.y).max().unwrap().into()
|
self.points.iter().map(|p| p.y).reduce(|p, q| p.max_or_undefined(&q)).unwrap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@ impl CylinderZ {
|
|||||||
#[typetag::serde]
|
#[typetag::serde]
|
||||||
impl Region for CylinderZ {
|
impl Region for CylinderZ {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
p.xy().distance_sq(self.center) <= (self.radius * self.radius).into()
|
p.xy().distance_sq(self.center) <= self.radius * self.radius
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
133
src/geom/vec.rs
133
src/geom/vec.rs
@@ -1,4 +1,5 @@
|
|||||||
use crate::flt::{Flt, Real};
|
use crate::flt::{self, Flt};
|
||||||
|
use crate::real::Real;
|
||||||
use super::Vec3u;
|
use super::Vec3u;
|
||||||
|
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
@@ -7,35 +8,31 @@ use std::fmt;
|
|||||||
use std::iter::Sum;
|
use std::iter::Sum;
|
||||||
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub};
|
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub};
|
||||||
|
|
||||||
fn round(f: Real) -> Real {
|
|
||||||
Real::from_inner(f.into_inner().round())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct Vec2 {
|
pub struct Vec2<R=flt::Real> {
|
||||||
pub x: Real,
|
pub x: R,
|
||||||
pub y: Real,
|
pub y: R,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Add for Vec2 {
|
impl<R: Real> Add for Vec2<R> {
|
||||||
type Output = Vec2;
|
type Output = Self;
|
||||||
fn add(self, other: Vec2) -> Vec2 {
|
fn add(self, other: Self) -> Self {
|
||||||
let mut ret = self.clone();
|
let mut ret = self.clone();
|
||||||
ret += other;
|
ret += other;
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AddAssign for Vec2 {
|
impl<R: Real> AddAssign for Vec2<R> {
|
||||||
fn add_assign(&mut self, other: Vec2) {
|
fn add_assign(&mut self, other: Self) {
|
||||||
self.x += other.x;
|
self.x += other.x;
|
||||||
self.y += other.y;
|
self.y += other.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Neg for Vec2 {
|
impl<R: Real> Neg for Vec2<R> {
|
||||||
type Output = Vec2;
|
type Output = Self;
|
||||||
fn neg(self) -> Vec2 {
|
fn neg(self) -> Self {
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: -self.x,
|
x: -self.x,
|
||||||
y: -self.y,
|
y: -self.y,
|
||||||
@@ -43,16 +40,16 @@ impl Neg for Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sub for Vec2 {
|
impl<R: Real> Sub for Vec2<R> {
|
||||||
type Output = Vec2;
|
type Output = Self;
|
||||||
fn sub(self, other: Vec2) -> Vec2 {
|
fn sub(self, other: Self) -> Self {
|
||||||
self + (-other)
|
self + (-other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<Flt> for Vec2 {
|
impl<R: Real> Mul<R> for Vec2<R> {
|
||||||
type Output = Vec2;
|
type Output = Self;
|
||||||
fn mul(self, s: Flt) -> Vec2 {
|
fn mul(self, s: R) -> Self {
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: self.x * s,
|
x: self.x * s,
|
||||||
y: self.y * s,
|
y: self.y * s,
|
||||||
@@ -60,69 +57,77 @@ impl Mul<Flt> for Vec2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Into<(Flt, Flt)> for Vec2 {
|
impl<R> Into<(R, R)> for Vec2<R> {
|
||||||
fn into(self) -> (Flt, Flt) {
|
fn into(self) -> (R, R) {
|
||||||
(self.x(), self.y())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<(Real, Real)> for Vec2 {
|
|
||||||
fn into(self) -> (Real, Real) {
|
|
||||||
(self.x, self.y)
|
(self.x, self.y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vec2 {
|
impl<R> Vec2<R> {
|
||||||
pub fn new(x: Flt, y: Flt) -> Self {
|
pub fn new<R2: Into<R>>(x: R2, y: R2) -> Self {
|
||||||
Self {
|
Self {
|
||||||
x: x.into(),
|
x: x.into(),
|
||||||
y: y.into(),
|
y: y.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn x(&self) -> Flt {
|
impl<R: Real> Vec2<R> {
|
||||||
|
pub fn zero() -> Self {
|
||||||
|
Self::new(R::zero(), R::zero())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unit() -> Self {
|
||||||
|
Self::new(R::one(), R::one())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn x(&self) -> R {
|
||||||
self.x.into()
|
self.x.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn y(&self) -> Flt {
|
pub fn y(&self) -> R {
|
||||||
self.y.into()
|
self.y.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn round(&self) -> Vec2 {
|
pub fn to_f32(&self) -> Vec2<f32> {
|
||||||
|
Vec2::new(self.x.to_f32(), self.y.to_f32())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn round(&self) -> Self {
|
||||||
Vec2 {
|
Vec2 {
|
||||||
x: round(self.x),
|
x: self.x.round(),
|
||||||
y: round(self.y),
|
y: self.y.round(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn distance_sq(&self, other: Self) -> Flt {
|
pub fn distance_sq(&self, other: Self) -> R {
|
||||||
(*self - other).mag_sq()
|
(*self - other).mag_sq()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mag_sq(&self) -> Flt {
|
pub fn mag_sq(&self) -> R {
|
||||||
(self.x*self.x + self.y*self.y).into()
|
self.x*self.x + self.y*self.y
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mag(&self) -> Flt {
|
pub fn mag(&self) -> R {
|
||||||
self.mag_sq().sqrt()
|
self.mag_sq().sqrt()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_mag(&self, new_mag: Flt) -> Vec2 {
|
pub fn with_mag(&self, new_mag: R) -> Self {
|
||||||
if new_mag == 0.0 {
|
if new_mag.is_zero() {
|
||||||
// avoid div-by-zero if self.mag() == 0 and new_mag == 0
|
// avoid div-by-zero if self.mag() == 0 and new_mag == 0
|
||||||
Vec2::new(0.0, 0.0)
|
Vec2::new(R::zero(), R::zero())
|
||||||
} else {
|
} else {
|
||||||
let scale = Real::from_inner(new_mag) / self.mag();
|
let scale = new_mag / self.mag();
|
||||||
self.clone() * scale.into_inner()
|
*self * scale
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Vec3 {
|
pub struct Vec3 {
|
||||||
pub(crate) x: Real,
|
pub(crate) x: flt::Real,
|
||||||
pub(crate) y: Real,
|
pub(crate) y: flt::Real,
|
||||||
pub(crate) z: Real,
|
pub(crate) z: flt::Real,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Vec3 {
|
impl Vec3 {
|
||||||
@@ -161,13 +166,13 @@ impl Vec3 {
|
|||||||
self.z.into()
|
self.z.into()
|
||||||
}
|
}
|
||||||
pub fn set_x(&mut self, x: Flt) {
|
pub fn set_x(&mut self, x: Flt) {
|
||||||
self.x = Real::from_inner(x);
|
self.x = flt::Real::from_inner(x);
|
||||||
}
|
}
|
||||||
pub fn set_y(&mut self, y: Flt) {
|
pub fn set_y(&mut self, y: Flt) {
|
||||||
self.y = Real::from_inner(y);
|
self.y = flt::Real::from_inner(y);
|
||||||
}
|
}
|
||||||
pub fn set_z(&mut self, z: Flt) {
|
pub fn set_z(&mut self, z: Flt) {
|
||||||
self.z = Real::from_inner(z);
|
self.z = flt::Real::from_inner(z);
|
||||||
}
|
}
|
||||||
pub fn xy(&self) -> Vec2 {
|
pub fn xy(&self) -> Vec2 {
|
||||||
Vec2::new(self.x(), self.y())
|
Vec2::new(self.x(), self.y())
|
||||||
@@ -237,7 +242,7 @@ impl Vec3 {
|
|||||||
// avoid div-by-zero if self.mag() == 0 and new_mag == 0
|
// avoid div-by-zero if self.mag() == 0 and new_mag == 0
|
||||||
Self::zero()
|
Self::zero()
|
||||||
} else {
|
} else {
|
||||||
let scale = Real::from_inner(new_mag) / self.mag();
|
let scale = flt::Real::from_inner(new_mag) / self.mag();
|
||||||
self.clone() * scale.into_inner()
|
self.clone() * scale.into_inner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -267,8 +272,8 @@ impl From<(Flt, Flt, Flt)> for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(Real, Real, Real)> for Vec3 {
|
impl From<(flt::Real, flt::Real, flt::Real)> for Vec3 {
|
||||||
fn from((x, y, z): (Real, Real, Real)) -> Self {
|
fn from((x, y, z): (flt::Real, flt::Real, flt::Real)) -> Self {
|
||||||
Self { x, y, z }
|
Self { x, y, z }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,17 +323,17 @@ impl Neg for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MulAssign<Real> for Vec3 {
|
impl MulAssign<flt::Real> for Vec3 {
|
||||||
fn mul_assign(&mut self, other: Real) {
|
fn mul_assign(&mut self, other: flt::Real) {
|
||||||
self.x *= other;
|
self.x *= other;
|
||||||
self.y *= other;
|
self.y *= other;
|
||||||
self.z *= other;
|
self.z *= other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mul<Real> for Vec3 {
|
impl Mul<flt::Real> for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn mul(self, other: Real) -> Self {
|
fn mul(self, other: flt::Real) -> Self {
|
||||||
let mut work = self.clone();
|
let mut work = self.clone();
|
||||||
work *= other;
|
work *= other;
|
||||||
work
|
work
|
||||||
@@ -352,15 +357,15 @@ impl Mul<Flt> for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DivAssign<Real> for Vec3 {
|
impl DivAssign<flt::Real> for Vec3 {
|
||||||
fn div_assign(&mut self, other: Real) {
|
fn div_assign(&mut self, other: flt::Real) {
|
||||||
*self *= Real::from_inner(1.0) / other;
|
*self *= flt::Real::from_inner(1.0) / other;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Div<Real> for Vec3 {
|
impl Div<flt::Real> for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
fn div(self, other: Real) -> Self {
|
fn div(self, other: flt::Real) -> Self {
|
||||||
let mut work = self.clone();
|
let mut work = self.clone();
|
||||||
work /= other;
|
work /= other;
|
||||||
work
|
work
|
||||||
|
@@ -12,6 +12,7 @@ pub mod geom;
|
|||||||
pub mod mat;
|
pub mod mat;
|
||||||
pub mod meas;
|
pub mod meas;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
|
pub mod real;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod sim;
|
pub mod sim;
|
||||||
pub mod stim;
|
pub mod stim;
|
||||||
|
12
src/mat.rs
12
src/mat.rs
@@ -249,24 +249,24 @@ impl MHCurve {
|
|||||||
let line = segments.next().unwrap_or_else(|| {
|
let line = segments.next().unwrap_or_else(|| {
|
||||||
panic!("failed to find segment for h:{}, m:{}, {:?}", h, m, self.geom.segments().collect::<Vec<_>>());
|
panic!("failed to find segment for h:{}, m:{}, {:?}", h, m, self.geom.segments().collect::<Vec<_>>());
|
||||||
});
|
});
|
||||||
if line.contains_y(m.into()) && line.is_ascending() == is_ascending {
|
if line.contains_y(m) && line.is_ascending() == is_ascending {
|
||||||
if line.contains_x(h.into()) && line.distance_sq(Vec2::new(h.into(), m.into())) < 1.0e-6 {
|
if line.contains_x(h) && line.distance_sq(Vec2::new(h, m)) < 1.0e-6 {
|
||||||
// (h, m) resides on this line
|
// (h, m) resides on this line
|
||||||
break line;
|
break line;
|
||||||
} else {
|
} else {
|
||||||
// need to move the point toward this line
|
// need to move the point toward this line
|
||||||
let h_intercept = line.x(m.into());
|
let h_intercept = line.x(m);
|
||||||
break Line2d::new(Vec2::new(h.into(), m.into()), Vec2::new(h_intercept.into(), m.into()));
|
break Line2d::new(Vec2::new(h, m), Vec2::new(h_intercept, m));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
trace!("active segment: {:?}", active_segment);
|
trace!("active segment: {:?}", active_segment);
|
||||||
|
|
||||||
// Find some m(h) on the active_segment such that sum(h) = h + m(h) = target_hm
|
// Find some m(h) on the active_segment such that sum(h) = h + m(h) = target_hm
|
||||||
let sum_h = active_segment + Line2d::new(Vec2::new(0.0, 0.0), Vec2::new(1.0, 1.0));
|
let sum_h = active_segment + Line2d::new(Vec2::zero(), Vec2::unit());
|
||||||
trace!("sum_h: {:?}", sum_h);
|
trace!("sum_h: {:?}", sum_h);
|
||||||
let new_h = if sum_h.to().y() != sum_h.from().y() {
|
let new_h = if sum_h.to().y() != sum_h.from().y() {
|
||||||
sum_h.move_toward_y_unclamped(h.into(), target_hm.into())
|
sum_h.move_toward_y_unclamped(h, target_hm)
|
||||||
} else {
|
} else {
|
||||||
// avoid a division-by-zero.
|
// avoid a division-by-zero.
|
||||||
// We could be anywhere along this line, but we prefer the endpoint
|
// We could be anywhere along this line, but we prefer the endpoint
|
||||||
|
50
src/real.rs
Normal file
50
src/real.rs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
use std::ops::AddAssign;
|
||||||
|
use decorum::cmp::IntrinsicOrd;
|
||||||
|
|
||||||
|
/// This exists to allow configuration over # of bits (f32 v.s. f64) as well as
|
||||||
|
/// constraints.
|
||||||
|
pub trait Real: decorum::Real + IntrinsicOrd + AddAssign {
|
||||||
|
fn to_f32(&self) -> f32 {
|
||||||
|
self.to_f64() as _
|
||||||
|
}
|
||||||
|
fn to_f64(&self) -> f64 {
|
||||||
|
self.to_f32() as _
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Real for f32 {
|
||||||
|
fn to_f32(&self) -> f32 {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Real for f64 {
|
||||||
|
fn to_f64(&self) -> f64 {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Real for decorum::R32 {
|
||||||
|
fn to_f32(&self) -> f32 {
|
||||||
|
self.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Real for decorum::R64 {
|
||||||
|
fn to_f64(&self) -> f64 {
|
||||||
|
self.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Real for decorum::N32 {
|
||||||
|
fn to_f32(&self) -> f32 {
|
||||||
|
self.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Real for decorum::N64 {
|
||||||
|
fn to_f64(&self) -> f64 {
|
||||||
|
self.into_inner()
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
use crate::geom::{Index, Meters, Vec2, Vec3, Vec3u};
|
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::mat;
|
||||||
use crate::sim::{Cell, GenericSim, StaticSim};
|
use crate::sim::{Cell, GenericSim, StaticSim};
|
||||||
use crate::meas::AbstractMeasurement;
|
use crate::meas::AbstractMeasurement;
|
||||||
@@ -22,7 +22,7 @@ use y4m;
|
|||||||
/// Accept a value from (-\inf, \inf) and return a value in (-1, 1).
|
/// 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.
|
||||||
/// 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 {
|
if x >= 0.0 {
|
||||||
scale_unsigned(x, typical)
|
scale_unsigned(x, typical)
|
||||||
} else {
|
} 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).
|
/// 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.
|
/// 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(0) => 0
|
||||||
// f(1) => 0.5
|
// f(1) => 0.5
|
||||||
// f(\inf) => 1
|
// f(\inf) => 1
|
||||||
// f(x) = 1 - 1/(x+1)
|
// f(x) = 1 - 1/(x+1)
|
||||||
let x = Real::from_inner(x);
|
1.0 - 1.0/(x/typical + 1.0)
|
||||||
let typ = Real::from_inner(typical);
|
|
||||||
let y = Real::from_inner(1.0) - Real::from_inner(1.0)/(x/typ + 1.0);
|
|
||||||
y.into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
let norm = 128.0 + 128.0*scale_signed(x, typ);
|
||||||
norm as _
|
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);
|
let norm = 256.0*scale_unsigned(x, typ);
|
||||||
norm as _
|
norm as _
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scale a vector to have magnitude between [0, 1).
|
/// 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);
|
let new_mag = scale_unsigned(x.mag(), typical_mag);
|
||||||
x.with_mag(new_mag)
|
x.with_mag(new_mag)
|
||||||
}
|
}
|
||||||
@@ -103,7 +100,7 @@ impl FieldDisplayMode {
|
|||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
pub struct RenderConfig {
|
pub struct RenderConfig {
|
||||||
mode: FieldDisplayMode,
|
mode: FieldDisplayMode,
|
||||||
scale: Flt,
|
scale: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for RenderConfig {
|
impl Default for RenderConfig {
|
||||||
@@ -155,7 +152,7 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
|||||||
trace!("rendering at {}x{} with z={}", width, height, z);
|
trace!("rendering at {}x{} with z={}", width, height, z);
|
||||||
let mut me = Self::new(state, measurements, width, height, z);
|
let mut me = Self::new(state, measurements, width, height, z);
|
||||||
me.render_scalar_field(10.0, false, 2, |cell| {
|
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
|
0.0
|
||||||
} else {
|
} else {
|
||||||
5.0
|
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 {
|
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_prop = x_px as f32 / self.im.width() as f32;
|
||||||
let x_m = x_prop * (self.sim.width() as Flt * self.sim.feature_size());
|
let x_m = x_prop * (self.sim.width() as f32 * self.sim.feature_size() as f32);
|
||||||
let y_prop = y_px as Flt / self.im.height() as Flt;
|
let y_prop = y_px as f32 / self.im.height() as f32;
|
||||||
let y_m = y_prop * (self.sim.height() as Flt * self.sim.feature_size());
|
let y_m = y_prop * (self.sim.height() as f32 * self.sim.feature_size() as f32);
|
||||||
let z_m = self.z as Flt * self.sim.feature_size();
|
let z_m = self.z as f32 * self.sim.feature_size() as f32;
|
||||||
self.sim.sample(Meters(Vec3::new(x_m, y_m, z_m)))
|
self.sim.sample(Meters(Vec3::new(x_m as _, y_m as _, z_m as _)))
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////// Ex/Ey/Bz configuration ////////////
|
////////////// Ex/Ey/Bz configuration ////////////
|
||||||
fn render_b_z_field(&mut self, scale: Flt) {
|
fn render_b_z_field(&mut self, scale: f32) {
|
||||||
self.render_scalar_field(1.0e-4 * scale, true, 1, |cell| cell.b().z());
|
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) {
|
fn render_e_xy_field(&mut self, scale: f32) {
|
||||||
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 100.0 * scale, |cell| cell.e().xy());
|
self.render_vector_field(Rgb([0xff, 0xff, 0xff]), 100.0 * scale, |cell| cell.e().xy().to_f32());
|
||||||
// current
|
// current
|
||||||
self.render_vector_field(Rgb([0x00, 0xa0, 0x30]), 1.0e-12 * scale, |cell| {
|
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 /////////////
|
////////////// Magnitude configuration /////////////
|
||||||
fn render_b(&mut self, scale: Flt) {
|
fn render_b(&mut self, scale: f32) {
|
||||||
self.render_scalar_field(1.0e-3 * scale, false, 1, |cell| cell.b().mag());
|
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| {
|
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 ////////////
|
////////////// Bx/By/Ez configuration ////////////
|
||||||
fn render_e_z_field(&mut self, scale: Flt) {
|
fn render_e_z_field(&mut self, scale: f32) {
|
||||||
self.render_scalar_field(1e4 * scale, true, 1, |cell| cell.e().z());
|
self.render_scalar_field(1e4 * scale, true, 1, |cell| cell.e().z() as f32);
|
||||||
}
|
}
|
||||||
fn render_b_xy_field(&mut self, scale: Flt) {
|
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());
|
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) {
|
fn render_m(&mut self, scale: f32) {
|
||||||
self.render_scalar_field(1.0e5 * scale, false, 1, |cell| cell.mat().m().mag());
|
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());
|
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 w = self.im.width();
|
||||||
let h = self.im.height();
|
let h = self.im.height();
|
||||||
let vec_spacing = 10;
|
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 vec = self.field_vector(x, y, vec_spacing, &measure);
|
||||||
let norm_vec = scale_vector(vec, typical);
|
let norm_vec = scale_vector(vec, typical);
|
||||||
let alpha = 0.7*scale_unsigned(vec.mag_sq(), typical * 5.0);
|
let alpha = 0.7*scale_unsigned(vec.mag_sq(), typical * 5.0);
|
||||||
let vec = norm_vec * (vec_spacing as Flt);
|
let vec = norm_vec * (vec_spacing as f32);
|
||||||
let center = Vec2::new(x as _, y as _) + Vec2::new(vec_spacing as _, vec_spacing as _)*0.5;
|
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);
|
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.
|
// 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 mut im = self.im.clone();
|
||||||
let w = im.width();
|
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 mut field = Vec2::default();
|
||||||
let w = self.im.width();
|
let w = self.im.width();
|
||||||
let h = self.im.height();
|
let h = self.im.height();
|
||||||
@@ -313,17 +310,17 @@ impl<'a, S: GenericSim> RenderSteps<'a, S> {
|
|||||||
// avoid division by zero
|
// avoid division by zero
|
||||||
Vec2::new(0.0, 0.0)
|
Vec2::new(0.0, 0.0)
|
||||||
} else {
|
} else {
|
||||||
field * (1.0 / ((xw*yw) as Flt))
|
field * (1.0 / ((xw*yw) as f32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait ImageRenderExt {
|
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 {
|
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 start = (center - rel * 0.5).round();
|
||||||
let end = (center + rel * 0.5).round();
|
let end = (center + rel * 0.5).round();
|
||||||
let i_start = (start.x().round() as _, start.y().round() as _);
|
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 g = scale_unsigned_to_u8(mat, 10.0);
|
||||||
//let r = scale_unsigned_to_u8(cell.mat().m().mag(), 100.0);
|
//let r = scale_unsigned_to_u8(cell.mat().m().mag(), 100.0);
|
||||||
//let b = scale_unsigned_to_u8(cell.e().mag(), 1e2);
|
//let b = scale_unsigned_to_u8(cell.e().mag(), 1e2);
|
||||||
let r = scale_unsigned_to_u8(cell.mat().m().mag(), 100.0);
|
let r = scale_unsigned_to_u8(cell.mat().m().mag() as f32, 100.0);
|
||||||
let g = scale_unsigned_to_u8(cell.e().mag(), 1e2);
|
let g = scale_unsigned_to_u8(cell.e().mag() as f32, 1e2);
|
||||||
let b = scale_unsigned_to_u8(mat, 10.0);
|
let b = scale_unsigned_to_u8(mat as f32, 10.0);
|
||||||
let alpha = 1.0;
|
let alpha = 1.0;
|
||||||
colors.push(Rgba::new(r, g, b, alpha));
|
colors.push(Rgba::new(r, g, b, alpha));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user