The Big Rename

This commit is contained in:
numzero 2024-06-11 13:43:59 +03:00
parent ae152f6d7d
commit 53075e0906

View File

@ -29,7 +29,7 @@ pub fn main() {
with_2d_graphics(move || {
let canvas = create_drawing_window("Refraction");
canvas.draw(|gc| {
let tube = Rect {
let tube = Tube {
inner_radius: 30.0,
outer_radius: 50.0,
internal_halflength: 100.0,
@ -53,7 +53,7 @@ pub fn main() {
r: 20.0,
})
.collect();
let space = Space { rect: tube, objs };
let space = Space { tube, objs };
gc.canvas_height(500.0);
gc.transform(Transform2D::rotate(FRAC_PI_2));
@ -118,7 +118,7 @@ struct Object {
}
struct Space {
rect: Rect,
tube: Tube,
objs: Vec<Object>,
}
@ -143,11 +143,11 @@ struct FlatTraceResult {
impl Space {
fn which_subspace(&self, pt: Vec2) -> Subspace {
if pt.y.abs() > self.rect.external_halflength {
if pt.y.abs() > self.tube.external_halflength {
Outer
} else if pt.x.abs() > self.rect.outer_radius {
} else if pt.x.abs() > self.tube.outer_radius {
Outer
} else if pt.x.abs() > self.rect.inner_radius {
} else if pt.x.abs() > self.tube.inner_radius {
Boundary
} else {
Inner
@ -155,17 +155,17 @@ impl Space {
}
fn flat_to_global(&self, at: Vec2) -> Mat2 {
Mat2::from(self.rect.sqrt_at(at).inverse())
Mat2::from(self.tube.sqrt_at(at).inverse())
}
fn global_to_flat(&self, at: Vec2) -> Mat2 {
Mat2::from(self.rect.sqrt_at(at))
Mat2::from(self.tube.sqrt_at(at))
}
/// Выполняет один шаг трассировки. Работает в любой части пространства, но вне Boundary доступны более эффективные методы.
/// ray задаётся в основной СК.
fn trace_step(&self, ray: Ray) -> Ray {
let a: Vec2 = -riemann::contract2(riemann::krist(&self.rect, ray.pos), ray.dir);
let a: Vec2 = -riemann::contract2(riemann::krist(&self.tube, ray.pos), ray.dir);
let v = ray.dir + a;
let p = ray.pos + v;
Ray { pos: p, dir: v }
@ -174,7 +174,7 @@ impl Space {
/// Выполняет один шаг перемещения. Работает в любой части пространства.
/// off задаётся в локальной СК. Рекомендуется считать небольшими шагами.
fn move_step(&self, loc: Location, off: Vec2) -> Location {
let corr = Mat2::IDENTITY - riemann::contract(riemann::krist(&self.rect, loc.pos), loc.rot * off);
let corr = Mat2::IDENTITY - riemann::contract(riemann::krist(&self.tube, loc.pos), loc.rot * off);
let p = loc.pos + corr * loc.rot * off;
Location { pos: p, rot: corr * loc.rot }
}
@ -185,7 +185,7 @@ impl Space {
fn trace_inner(&self, ray: Ray) -> FlatTraceResult {
assert_eq!(self.which_subspace(ray.pos), Inner);
let cell = RectInside { rect: self.rect };
let cell = TubeInside { tube: self.tube };
let ray = cell.ray_to_local(ray);
let objs = self.list_objects_inner();
let dist = cell.to_boundary(ray).expect("Can't get outta here!");
@ -197,7 +197,7 @@ impl Space {
fn trace_outer(&self, ray: Ray) -> FlatTraceResult {
assert_eq!(self.which_subspace(ray.pos), Outer);
let cell = basic_shapes::Rect { size: vec2(self.rect.outer_radius, self.rect.external_halflength) };
let cell = basic_shapes::Rect { size: vec2(self.tube.outer_radius, self.tube.external_halflength) };
let objs = self.list_objects_outer();
let lim = cell.trace_into(ray);
let dist = lim.unwrap_or(f32::INFINITY);
@ -224,8 +224,8 @@ impl Space {
Outer => loc,
Inner => {
let Vec2 { x, y } = loc.pos; // в основной СК
let y = self.rect.u(y) + y.signum() * (self.rect.external_halflength - self.rect.internal_halflength);
let m = Mat2::from_cols_array(&[1., 0., 0., self.rect.du(y)]);
let y = self.tube.u(y) + y.signum() * (self.tube.external_halflength - self.tube.internal_halflength);
let m = Mat2::from_cols_array(&[1., 0., 0., self.tube.du(y)]);
Location {
pos: vec2(x, y), // в плоском продолжении СК Outer на область Inner
rot: m * loc.rot,
@ -240,9 +240,9 @@ impl Space {
match self.which_subspace(pos) {
Inner | Outer => {
// NB: не работает для частей Outer с |y| < external_halflength. Но они и не нужны.
let m = Mat2::from_cols_array(&[1., 0., 0., self.rect.du(pos.y)]);
let m = Mat2::from_cols_array(&[1., 0., 0., self.tube.du(pos.y)]);
Location {
pos: vec2(pos.x, self.rect.u(pos.y)), // в плоской СК для Inner или её продолжении на Outer
pos: vec2(pos.x, self.tube.u(pos.y)), // в плоской СК для Inner или её продолжении на Outer
rot: m * rot,
}
}
@ -275,7 +275,7 @@ impl Space {
match self.which_subspace(a) {
Outer => vec![b],
Inner => {
let cell = RectInside { rect: self.rect };
let cell = TubeInside { tube: self.tube };
let n = ((b - a).length() / step) as usize + 1;
let a = cell.pos_to_local(a);
let b = cell.pos_to_local(b);
@ -288,10 +288,10 @@ impl Space {
fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
let mut hits = Vec::<Draw>::new();
let dir = space.rect.globalize(base, dir);
let dir = space.tube.globalize(base, dir);
gc.new_path();
gc.move_to(base.x, base.y);
let mut ray = Ray { pos: base, dir: space.rect.normalize_vec_at(base, dir) * DT };
let mut ray = Ray { pos: base, dir: space.tube.normalize_vec_at(base, dir) * DT };
for _ in 0..10000 {
ray = space.trace_step(ray);
gc.line_to(ray.pos.x, ray.pos.y);
@ -315,7 +315,7 @@ fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
for hit in ret.objects {
let obj = space.objs[hit.id as usize];
hits.move_to(obj.loc.pos.x, obj.loc.pos.y);
for pt in trace_iter(&space.rect, obj.loc.pos, obj.loc.rot * hit.rel.pos, hit.rel.pos.length() / 100.0).take(100) {
for pt in trace_iter(&space.tube, obj.loc.pos, obj.loc.rot * hit.rel.pos, hit.rel.pos.length() / 100.0).take(100) {
hits.line_to(pt.x, pt.y);
}
hits.circle(hit.pos.x, hit.pos.y, 1.5);
@ -324,7 +324,7 @@ fn draw_ray_2(gc: &mut Vec<Draw>, space: &Space, base: Vec2, dir: Vec2) {
assert!(diff >= 0.0);
let t = (-rel.dot(dir) + diff.sqrt()) / dir.length_squared();
let rel2 = hit.rel.forward(t).pos;
let pos2 = trace_iter(&space.rect, obj.loc.pos, obj.loc.rot * rel2, rel2.length() / 100.0).nth(100).unwrap();
let pos2 = trace_iter(&space.tube, obj.loc.pos, obj.loc.rot * rel2, rel2.length() / 100.0).nth(100).unwrap();
hits.move_to(pos2.x - 1.0, pos2.y - 1.0);
hits.line_to(pos2.x + 1.0, pos2.y + 1.0);
hits.move_to(pos2.x - 1.0, pos2.y + 1.0);
@ -379,8 +379,8 @@ fn draw_track(gc: &mut Vec<Draw>, space: &Space, start: Vec2, dir: Vec2) {
const SCALE: f32 = 5.0;
const STEP: f32 = 2.0 * SCALE;
// let mut loc = Location { pos: start, rot: Mat2::IDENTITY };
// let dir = space.rect.globalize(start, dir);
// let v = space.rect.normalize(start, dir);
// let dir = space.tube.globalize(start, dir);
// let v = space.tube.normalize(start, dir);
let mut loc = Location { pos: start, rot: mat2(dir, vec2(-dir.y, dir.x)) };
let v = vec2(1.0, 0.0);
let mut draw = |loc: &Location| {
@ -420,7 +420,7 @@ trait Renderable {
fn render(&self, gc: &mut Vec<Draw>);
}
impl Renderable for Rect {
impl Renderable for Tube {
fn render(&self, gc: &mut Vec<Draw>) {
gc.new_path();
gc.rect(-self.outer_radius, -self.external_halflength, self.outer_radius, self.external_halflength);
@ -579,49 +579,49 @@ trait FlatCell: std::fmt::Debug {
}
#[derive(Debug)]
struct RectInside {
rect: Rect,
struct TubeInside {
tube: Tube,
}
impl FlatCell for RectInside {
impl FlatCell for TubeInside {
fn pos_to_global(&self, pos: Vec2) -> Vec2 {
vec2(pos.x, self.rect.x(pos.y))
vec2(pos.x, self.tube.x(pos.y))
}
fn pos_to_local(&self, pos: Vec2) -> Vec2 {
vec2(pos.x, self.rect.u(pos.y))
vec2(pos.x, self.tube.u(pos.y))
}
fn ray_to_global(&self, ray: Ray) -> Ray {
Ray {
pos: self.pos_to_global(ray.pos),
dir: vec2(ray.dir.x, self.rect.dx(ray.pos.y) * ray.dir.y),
dir: vec2(ray.dir.x, self.tube.dx(ray.pos.y) * ray.dir.y),
}
}
fn ray_to_local(&self, ray: Ray) -> Ray {
Ray {
pos: self.pos_to_local(ray.pos),
dir: vec2(ray.dir.x, self.rect.du(ray.pos.y) * ray.dir.y),
dir: vec2(ray.dir.x, self.tube.du(ray.pos.y) * ray.dir.y),
}
}
fn local_bounds(&self) -> (Vec2, Vec2) {
(vec2(-self.rect.inner_radius, -self.rect.internal_halflength), vec2(self.rect.inner_radius, self.rect.internal_halflength))
(vec2(-self.tube.inner_radius, -self.tube.internal_halflength), vec2(self.tube.inner_radius, self.tube.internal_halflength))
}
}
#[derive(Copy, Clone, Debug)]
struct Rect {
struct Tube {
outer_radius: f32,
inner_radius: f32,
external_halflength: f32,
internal_halflength: f32,
}
impl Rect {
fn fx(&self) -> fns::RectX { fns::RectX { min: self.inner_radius, max: self.outer_radius } }
fn fy(&self) -> fns::RectY { fns::RectY { internal: self.internal_halflength, external: self.external_halflength } }
impl Tube {
fn fx(&self) -> fns::TubeX { fns::TubeX { min: self.inner_radius, max: self.outer_radius } }
fn fy(&self) -> fns::TubeY { fns::TubeY { internal: self.internal_halflength, external: self.external_halflength } }
pub fn x(&self, u: f32) -> f32 { self.fy().x(u) }
pub fn u(&self, x: f32) -> f32 { self.fy().u(x) }
@ -635,17 +635,17 @@ mod fns {
#[cfg(test)]
use approx::abs_diff_eq;
pub struct RectX {
pub struct TubeX {
pub min: f32,
pub max: f32,
}
impl RectX {
impl TubeX {
pub fn value(&self, x: f32) -> f32 { (self.min, self.max).inverse_lerp(x.abs()).clamp(0.0, 1.0) }
pub fn derivative(&self, x: f32) -> f32 { if x.abs() > self.min && x.abs() < self.max { x.signum() / (self.max - self.min) } else { 0.0 } }
}
pub struct RectY {
pub struct TubeY {
pub internal: f32,
pub external: f32,
}
@ -660,7 +660,7 @@ mod fns {
if t.abs() <= lim { f(t) } else { val }
}
impl RectY {
impl TubeY {
fn a(&self) -> f32 { -(self.external - self.internal) / self.internal.powi(2) }
fn b(&self) -> f32 { 2.0 * self.external / self.internal - 1.0 }
fn root(&self, x: f32) -> f32 { (self.b().powi(2) + 4.0 * self.a() * x.abs()).sqrt() }
@ -673,8 +673,8 @@ mod fns {
}
#[test]
fn test_rect_y() {
let testee = RectY { internal: 100.0, external: 150.0 };
fn test_tube_y() {
let testee = TubeY { internal: 100.0, external: 150.0 };
let ε = 1.0e-4f32;
let δ = 1.0 / 8.0; // Mathematically, you want this to be small. Computationally, you dont.
let margin = 1.0 / 16.0;
@ -700,39 +700,39 @@ mod fns {
}
#[test]
fn test_rect() {
let r = Rect {
fn test_tube() {
let t = Tube {
outer_radius: 50.0,
inner_radius: 20.0,
external_halflength: 100.0,
internal_halflength: 10.0,
};
assert_abs_diff_eq!(r.x(r.internal_halflength), r.external_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.x(-r.internal_halflength), -r.external_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.u(r.external_halflength), r.internal_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.u(-r.external_halflength), -r.internal_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.x(t.internal_halflength), t.external_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.x(-t.internal_halflength), -t.external_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.u(t.external_halflength), t.internal_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.u(-t.external_halflength), -t.internal_halflength, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.dx(r.internal_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.dx(-r.internal_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.du(r.external_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.du(-r.external_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.dx(t.internal_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.dx(-t.internal_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.du(t.external_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.du(-t.external_halflength), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.u(r.x(1.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.u(r.x(5.0)), 5.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.u(r.x(-5.0)), -5.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.u(r.x(10.0)), 10.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.x(r.u(10.0)), 10.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.x(r.u(50.0)), 50.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.x(r.u(-50.0)), -50.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.x(r.u(100.0)), 100.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.du(10.0) * r.dx(r.u(10.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.du(50.0) * r.dx(r.u(50.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.du(-50.0) * r.dx(r.u(-50.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.du(100.0) * r.dx(r.u(100.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.dx(1.0) * r.du(r.x(1.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.dx(5.0) * r.du(r.x(5.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.dx(-5.0) * r.du(r.x(-5.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(r.dx(10.0) * r.du(r.x(10.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.u(t.x(1.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.u(t.x(5.0)), 5.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.u(t.x(-5.0)), -5.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.u(t.x(10.0)), 10.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.x(t.u(10.0)), 10.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.x(t.u(50.0)), 50.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.x(t.u(-50.0)), -50.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.x(t.u(100.0)), 100.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.du(10.0) * t.dx(t.u(10.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.du(50.0) * t.dx(t.u(50.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.du(-50.0) * t.dx(t.u(-50.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.du(100.0) * t.dx(t.u(100.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.dx(1.0) * t.du(t.x(1.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.dx(5.0) * t.du(t.x(5.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.dx(-5.0) * t.du(t.x(-5.0)), 1.0, epsilon = 1.0e-5);
assert_abs_diff_eq!(t.dx(10.0) * t.du(t.x(10.0)), 1.0, epsilon = 1.0e-5);
}
trait FloatExt2 {
@ -745,7 +745,7 @@ impl FloatExt2 for (f32, f32) {
fn inverse_lerp(&self, y: f32) -> f32 { f32::inverse_lerp(self.0, self.1, y) }
}
impl Metric for Rect {
impl Metric for Tube {
fn sqrt_at(&self, pos: Vec2) -> Decomp2 {
let sx = self.fx().value(pos.x);
let sy = self.fy().du(pos.y);
@ -775,12 +775,12 @@ impl Metric for Rect {
}
#[test]
fn test_rect_metric_derivs() {
struct Approx(Rect);
fn test_tube_metric_derivs() {
struct Approx(Tube);
impl Metric for Approx {
fn sqrt_at(&self, pos: Vec2) -> Decomp2 { self.0.sqrt_at(pos) }
}
let testee = Rect {
let testee = Tube {
inner_radius: 30.0,
outer_radius: 50.0,
internal_halflength: 100.0,