Implement missing OuterCS APIs, and test them

This commit is contained in:
numzero 2024-06-30 12:07:09 +03:00
parent 95d46b24c8
commit dff3f94f68

View File

@ -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<Vec2> for OuterCS {}
impl FlatCoordinateSystem<Vec2> 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<Ray> for OuterCS {}
impl FlatCoordinateSystem<Location> 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) {