From 2ee64fb177f3ce15c8f39d42472911e7e9a8ce3d Mon Sep 17 00:00:00 2001 From: numzero Date: Tue, 7 May 2024 14:34:26 +0300 Subject: [PATCH] Much better this time --- src/bin/flat.rs | 131 ++++++++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 72 deletions(-) diff --git a/src/bin/flat.rs b/src/bin/flat.rs index 65b8a96..8c1eba5 100644 --- a/src/bin/flat.rs +++ b/src/bin/flat.rs @@ -31,7 +31,7 @@ pub fn main() { Box::new(Inside { space: space.clone() }), ]; - //parts.draw_fan(gc, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0); + parts.draw_fan(gc, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0); // parts.draw_fan(gc, vec2(-20.0, -500.0), vec2(0.1, 0.9), 1.0); //parts.draw_ray(gc, vec2(-20.0, -500.0), vec2(0.1, 0.9)); }); @@ -73,15 +73,7 @@ impl SpaceVisual for Inside { } fn globalize_loc(&self, pos: Vec2) -> Vec2 { - todo!() - // let off = self.space.r.y + self.space.m - self.space.r.y / self.space.scale - self.space.m / (self.space.scale + 1.0) * 2.0; - // if pos.y.abs() * self.space.scale <= self.space.r.y { - // vec2(pos.x, pos.y * self.space.scale) - // } else { - // let t = pos.y.abs() - self.space.r.y / self.space.scale; - // let f = t + (self.space.scale - 1.0) * t * t * t + 0.5 * (1.0 - self.space.scale) * t * t * t * t; - // vec2(0.0, 0.0) - // } + vec2(pos.x, self.space.x(pos.y)) } } @@ -182,9 +174,9 @@ impl Renderable for Rect { gc.stroke_color(Color::Rgba(1.0, 0.5, 0.0, 1.0)); self.draw_fan(gc, vec2(-500.0, 0.0), vec2(1.0, 0.0), 1.0); gc.stroke_color(Color::Rgba(0.0, 0.5, 1.0, 1.0)); - self.draw_fan(gc, vec2(0.0, -0.5 * self.external_halflength), vec2(1.0, 1.0), 1.0); + // self.draw_fan(gc, vec2(0.0, -0.5 * self.external_halflength), vec2(1.0, 1.0), 1.0); gc.stroke_color(Color::Rgba(0.2, 0.7, 0.0, 1.0)); - self.draw_fan(gc, vec2(-0.5 * self.inner_radius, -1.2 * self.external_halflength), vec2(0.0, 1.0), 1.0); + // self.draw_fan(gc, vec2(-0.5 * self.inner_radius, -1.2 * self.external_halflength), vec2(0.0, 1.0), 1.0); } } @@ -228,22 +220,18 @@ impl Rect { fn b(&self) -> f32 { 2.0 * self.γ() - 1.0 } fn root(&self, x: f32) -> f32 { ((2.0 * self.γ() - 1.0).powi(2) + 4.0 * (1.0 - self.γ()) * x / self.ri()).sqrt() } + fn d(&self, u: f32) -> f32 { 2.0 * self.a() * u.abs() + self.b() } fn x(&self, u: f32) -> f32 { (self.a() * u.abs() + self.b()) * u } fn u(&self, x: f32) -> f32 { 0.5 * self.ri() * (1.0 - 2.0 * self.γ() + self.root(x.abs())) / (1.0 - self.γ()) * x.signum() } + fn dx(&self, u: f32, du: f32) -> f32 { du * self.d(u) } + fn du(&self, x: f32, dx: f32) -> f32 { dx / self.d(self.u(x)) } } impl Metric for Rect { fn halfmetric(&self, pos: Vec2) -> Decomp2 { - let γ = self.γ(); - let re = self.re(); - let ri = self.ri(); - let a = self.a(); - let b = self.b(); let x = pos.y.abs(); - let u = 0.5 * ri * (1.0 - 2.0 * γ + self.root(x)) / (1.0 - γ); let sx = ((pos.x.abs() - self.inner_radius) / (self.outer_radius - self.inner_radius)).clamp(0.0, 1.0); - let sy = if x <= re { 1.0 / (2.0 * a * u + b) } else { 1.0 }; - let sy = if x <= re { 1.0 / self.root(x) } else { 1.0 }; + let sy = if x <= self.external_halflength { 1.0 / self.root(x) } else { 1.0 }; assert!(sx.is_finite()); assert!(sy.is_finite()); assert!(sy > 0.0); @@ -279,25 +267,22 @@ struct Inside { impl boundary::Boundary for Outside { fn next(&self, base: Vec2, dir: Vec2, limit: f32) -> Option<(boundary::Id, Vec2, Vec2)> { - todo!() - // let osize = self.space.r + self.space.m; - // let isize = self.space.r; - // let bnd = Loop(vec![ - // vec2(-osize.x, -osize.y), vec2(-isize.x, -osize.y), vec2(isize.x, -osize.y), vec2(osize.x, -osize.y), - // vec2(osize.x, osize.y), vec2(isize.x, osize.y), vec2(-isize.x, osize.y), vec2(-osize.x, osize.y), - // ]); - // let (side, dist) = bnd.hit(base, dir)?; - // if dist <= limit { - // let bnds = [0, 1, 0, 0, 0, 2, 0, 0]; - // let off = self.space.r.y + self.space.m - self.space.r.y / self.space.scale - self.space.m / (self.space.scale + 1.0) * 2.0; - // return match bnds[side] { - // 0 => Some((boundary::Id(1), base + dist * dir, dir)), - // 1 => Some((boundary::Id(2), base + dist * dir + vec2(0.0, off), dir)), - // 2 => Some((boundary::Id(2), base + dist * dir - vec2(0.0, off), dir)), - // _ => panic!(), - // }; - // } - // None + let or = self.space.outer_radius; + let ir = self.space.inner_radius; + let hl = self.space.external_halflength; + let bnd = Loop(vec![ + vec2(-or, -hl), vec2(-ir, -hl), vec2(ir, -hl), vec2(or, -hl), + vec2(or, hl), vec2(ir, hl), vec2(-ir, hl), vec2(-or, hl), + ]); + let (side, dist) = bnd.hit(base, dir)?; + if dist <= limit { + let pt = base + dist * dir; + return match side { + 1 | 5 => Some((boundary::Id(2), vec2(pt.x, self.space.u(pt.y)), vec2(dir.x, self.space.du(pt.x, dir.y)))), + _ => Some((boundary::Id(1), pt, dir)), + }; + } + None } } @@ -309,26 +294,26 @@ impl Metric for Outside { impl boundary::Boundary for Wall { fn next(&self, base: Vec2, dir: Vec2, limit: f32) -> Option<(boundary::Id, Vec2, Vec2)> { - todo!() - // let osize = self.space.r + self.space.m; - // let isize = self.space.r; - // let obnd = Loop(vec![vec2(-osize.x, -osize.y), vec2(-osize.x, osize.y), vec2(osize.x, osize.y), vec2(osize.x, -osize.y)]); - // let ibnd = Loop(vec![vec2(-isize.x, -isize.y), vec2(isize.x, -isize.y), vec2(isize.x, isize.y), vec2(-isize.x, isize.y)]); - // if let Some((_, dist)) = ibnd.hit(base, dir) { - // if dist <= limit { - // let p = base + dist * dir; - // let v = dir; - // let p = vec2(p.x, p.y / self.space.scale); - // let v = vec2(v.x, v.y / self.space.scale); - // return Some((boundary::Id(2), p, v)); - // } - // } - // if let Some((_, dist)) = obnd.hit(base, dir) { - // if dist <= limit { - // return Some((boundary::Id(0), base + dist * dir, dir)); - // } - // } - // None + let or = self.space.outer_radius; + let ir = self.space.inner_radius; + let hl = self.space.external_halflength; + let obnd = Loop(vec![vec2(-or, -hl), vec2(-or, hl), vec2(or, hl), vec2(or, -hl)]); + let ibnd = Loop(vec![vec2(-ir, -hl), vec2(ir, -hl), vec2(ir, hl), vec2(-ir, hl)]); + if let Some((_, dist)) = ibnd.hit(base, dir) { + if dist <= limit { + let p = base + dist * dir; + let v = dir; + let v = vec2(v.x, self.space.du(p.y, v.y)); + let p = vec2(p.x, self.space.u(p.y)); + return Some((boundary::Id(2), p, v)); + } + } + if let Some((_, dist)) = obnd.hit(base, dir) { + if dist <= limit { + return Some((boundary::Id(0), base + dist * dir, dir)); + } + } + None } } @@ -340,19 +325,21 @@ impl Metric for Wall { impl boundary::Boundary for Inside { fn next(&self, base: Vec2, dir: Vec2, limit: f32) -> Option<(boundary::Id, Vec2, Vec2)> { - todo!() - // let size = self.space.r; - // let size = vec2(size.x, size.y / self.space.scale); - // let bnd = Loop(vec![vec2(-size.x, -size.y), vec2(-size.x, size.y), vec2(size.x, size.y), vec2(size.x, -size.y)]); - // let (_, dist) = bnd.hit(base, dir)?; - // if dist <= limit { - // let p = base + dist * dir; - // let v = dir; - // let p = vec2(p.x, p.y * self.space.scale); - // let v = vec2(v.x, v.y * self.space.scale); - // return Some((boundary::Id(1), p, v)); - // } - // None + let size = vec2(self.space.inner_radius, self.space.internal_halflength); + let bnd = Loop(vec![vec2(-size.x, -size.y), vec2(-size.x, size.y), vec2(size.x, size.y), vec2(size.x, -size.y)]); + let (side, dist) = bnd.hit(base, dir)?; + if dist <= limit { + let p = base + dist * dir; + let v = dir; + let v = vec2(v.x, self.space.dx(p.y, v.y)); + let p = vec2(p.x, self.space.x(p.y)); + return match side { + 0 | 2 => Some((boundary::Id(1), p, v)), + 1 | 3 => Some((boundary::Id(0), p, v)), + _ => panic!() + }; + } + None } }