diff --git a/src/bin/flat/tube/mod.rs b/src/bin/flat/tube/mod.rs index 5a3ff2e..b8b5b03 100644 --- a/src/bin/flat/tube/mod.rs +++ b/src/bin/flat/tube/mod.rs @@ -3,7 +3,7 @@ use crate::riemann; use crate::riemann::Metric; use Subspace::{Boundary, Inner, Outer}; use metric::Tube; -use coords::Mapper; +use coords::{MapperInner, MapperOuter}; use crate::types::{FlatTraceResult, Hit, Location, Object, Ray}; pub mod metric; @@ -64,11 +64,11 @@ impl Space { pub fn trace_inner(&self, ray: Ray) -> FlatTraceResult { assert_eq!(self.which_subspace(ray.pos), Inner); - let size = vec2(self.tube.inner_radius, self.tube.internal_halflength); - let ray = self.tube.outer_to_inner(ray); - assert!(ray.pos.abs().cmple(size).all()); + let inner = Rect { size: vec2(self.tube.inner_radius, self.tube.internal_halflength) }; + let ray = self.tube.global_to_inner(ray); + assert!(inner.is_inside(ray.pos)); let objs = self.list_objects_inner(); - let dist = Rect { size }.trace_out_of(ray).expect("Can't get outta here!"); + let dist = inner.trace_out_of(ray).expect("Can't get outta here!"); FlatTraceResult { end: Some(self.tube.inner_to_global(ray.forward(dist))), objects: Self::hit_objects(objs.as_slice(), ray, dist, |pos| self.tube.inner_to_global(pos)), @@ -101,30 +101,16 @@ impl Space { fn list_objects_outer(&self) -> Vec { self.list_objects(|loc| match self.which_subspace(loc.pos) { - Outer => loc, - Inner => { - let Vec2 { x: u, y } = loc.pos; // в основной СК - let v = self.tube.v(y) + y.signum() * (self.tube.external_halflength - self.tube.internal_halflength); - Location { - pos: vec2(u, v), // в плоском продолжении СК Outer на область Inner - rot: self.global_to_flat(loc.pos) * loc.rot, - } - } + Inner | Outer => self.tube.global_to_outer(loc), Boundary => panic!("Object at {} was destroyed by the space curvature", loc.pos), }) } fn list_objects_inner(&self) -> Vec { - self.list_objects(|Location { pos, rot }| - match self.which_subspace(pos) { - Inner | Outer => { - // NB: не работает для частей Outer с |y| < external_halflength. Но они и не нужны. - Location { - pos: vec2(pos.x, self.tube.v(pos.y)), // в плоской СК для Inner или её продолжении на Outer - rot: self.global_to_flat(pos) * rot, - } - } - Boundary => panic!("Object at {pos} was destroyed by the space curvature"), + self.list_objects(|loc| + match self.which_subspace(loc.pos) { + Inner | Outer => self.tube.global_to_inner(loc), + Boundary => panic!("Object at {} was destroyed by the space curvature", loc.pos), }) } @@ -225,16 +211,22 @@ fn test_rect() { } mod coords { - use glam::{Vec2, vec2}; - use crate::types::Ray; - use super::Tube; + use glam::{Mat2, Vec2, vec2}; + use crate::riemann::Metric; + use crate::types::{Location, Ray}; + use super::{Rect, Tube}; - pub trait Mapper { + pub trait MapperInner { fn inner_to_global(self, v: T) -> T; fn global_to_inner(self, v: T) -> T; } - impl Mapper for Tube { + pub trait MapperOuter { + fn outer_to_global(self, v: T) -> T; + fn global_to_outer(self, v: T) -> T; + } + + impl MapperInner for Tube { fn inner_to_global(self, pos: Vec2) -> Vec2 { vec2(pos.x, self.y(pos.y)) } @@ -244,7 +236,7 @@ mod coords { } } - impl Mapper for Tube { + impl MapperInner for Tube { fn inner_to_global(self, ray: Ray) -> Ray { Ray { pos: self.inner_to_global(ray.pos), @@ -259,4 +251,49 @@ mod coords { } } } + + impl Tube { + fn flat_to_global(&self, at: Vec2) -> Mat2 { + Mat2::from(self.sqrt_at(at).inverse()) + } + + fn global_to_flat(&self, at: Vec2) -> Mat2 { + Mat2::from(self.sqrt_at(at)) + } + } + + impl MapperInner for Tube { + fn inner_to_global(self, loc: Location) -> Location { + todo!() + } + + // NB: не работает для частей Outer с |y| < external_halflength. Но они и не нужны. + fn global_to_inner(self, loc: Location) -> Location { + Location { + pos: vec2(loc.pos.x, self.v(loc.pos.y)), // в плоской СК для Inner или её продолжении на Outer + rot: self.global_to_flat(loc.pos) * loc.rot, + } + } + } + + impl MapperOuter for Tube { + fn outer_to_global(self, loc: Location) -> Location { + todo!() + } + + // NB: имеет разрыв в области Inner на y = 0. + fn global_to_outer(self, loc: Location) -> Location { + let inner = Rect { size: vec2(self.inner_radius, self.internal_halflength) }; + if inner.is_inside(loc.pos) { + let Vec2 { x: u, y } = loc.pos; // в основной СК + let v = self.v(y) + y.signum() * (self.external_halflength - self.internal_halflength); + Location { + pos: vec2(u, v), // в плоском продолжении СК Outer на область Inner + rot: self.global_to_flat(loc.pos) * loc.rot, + } + } else { + loc + } + } + } }