From dff3f94f6841d37016afb992e649208688a52008 Mon Sep 17 00:00:00 2001 From: numzero Date: Sun, 30 Jun 2024 12:07:09 +0300 Subject: [PATCH] Implement missing OuterCS APIs, and test them --- src/bin/flat/tube/mod.rs | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/bin/flat/tube/mod.rs b/src/bin/flat/tube/mod.rs index 6237d4d..b5cac7a 100644 --- a/src/bin/flat/tube/mod.rs +++ b/src/bin/flat/tube/mod.rs @@ -1,6 +1,5 @@ use glam::{bool, f32, Mat2, Vec2, vec2}; use crate::riemann; -use crate::riemann::Metric; use Subspace::{Boundary, Inner, Outer}; use metric::Tube; use coords::{FlatCoordinateSystem, InnerCS, OuterCS}; @@ -253,18 +252,43 @@ mod coords { pub struct OuterCS(pub Tube); - impl FlatCoordinateSystem for OuterCS {} + impl FlatCoordinateSystem for OuterCS { + fn flat_to_global(&self, pos: Vec2) -> Vec2 { + let inner = Rect { size: vec2(self.0.inner_radius + 1.0, self.0.external_halflength) }; + if inner.is_inside(pos) { + let Vec2 { x, y: v } = pos; + let y = self.0.y(v - v.signum() * (self.0.external_halflength - self.0.internal_halflength)); + vec2(x, y) + } else { + pos + } + } + + fn global_to_flat(&self, pos: Vec2) -> Vec2 { + let inner = Rect { size: vec2(self.0.inner_radius + 1.0, self.0.external_halflength) }; + if inner.is_inside(pos) { + let Vec2 { x: u, y } = pos; // в основной СК + let v = self.0.v(y) + y.signum() * (self.0.external_halflength - self.0.internal_halflength); + vec2(u, v) // в плоском продолжении СК Outer на область Inner + } else { + pos + } + } + } impl FlatCoordinateSystem for OuterCS {} impl FlatCoordinateSystem for OuterCS { fn flat_to_global(&self, loc: Location) -> Location { - todo!() + Location { + pos: self.flat_to_global(loc.pos), + rot: Mat2::from(self.0.sqrt_at(loc.pos).inverse()) * loc.rot, + } } // NB: имеет разрыв в области Inner на y = 0. fn global_to_flat(&self, loc: Location) -> Location { - let inner = Rect { size: vec2(self.0.inner_radius, self.0.external_halflength) }; + let inner = Rect { size: vec2(self.0.inner_radius + 1.0, self.0.external_halflength) }; if inner.is_inside(loc.pos) { let Vec2 { x: u, y } = loc.pos; // в основной СК let v = self.0.v(y) + y.signum() * (self.0.external_halflength - self.0.internal_halflength); @@ -303,6 +327,7 @@ mod coords { } fn check_range(name_a: &str, a: Vec2, range_a: (Vec2, Vec2), name_b: &str, b: Vec2, range_b: (Vec2, Vec2)) { assert!(b.cmpge(range_b.0 - ε).all() && b.cmple(range_b.1 + ε).all(), "Assertion failed:\nAt {name_a}: {a}, from range: {range_a:?}\nGot {name_b}: {b}, which is out of range {range_b:?}"); + // TODO sort out when to check these conditions: if a.x.abs_diff_eq(&range_a.0.x, ε) { assert_abs_diff_eq!(b.x, range_b.0.x, epsilon=ε); } if a.y.abs_diff_eq(&range_a.0.y, ε) { assert_abs_diff_eq!(b.y, range_b.0.y, epsilon=ε); } if a.x.abs_diff_eq(&range_a.1.x, ε) { assert_abs_diff_eq!(b.x, range_b.1.x, epsilon=ε); } @@ -349,6 +374,11 @@ mod coords { internal_halflength: 100.0, external_halflength: 300.0, }); + // TODO replace 200.20016 with something sane + test_flat_region(&mapper, (vec2(-30.0, -300.0), vec2(30.0, -1.0)), (vec2(-30.0, -300.0), vec2(30.0, -200.20016))); + test_flat_region(&mapper, (vec2(-30.0, 1.0), vec2(30.0, 300.0)), (vec2(-30.0, 200.20016), vec2(30.0, 300.0))); + test_flat_region(&mapper, (vec2(-60.0, -400.0), vec2(60.0, -300.0)), (vec2(-60.0, -400.0), vec2(60.0, -300.0))); + test_flat_region(&mapper, (vec2(-60.0, 300.0), vec2(60.0, 400.0)), (vec2(-60.0, 300.0), vec2(60.0, 400.0))); // straight for x in linspace(-60., 60., 20) { for y in linspace(-320., 320., 20) {