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