diff --git a/src/bin/flat/tube/mod.rs b/src/bin/flat/tube/mod.rs index eefa4b3..70b85cb 100644 --- a/src/bin/flat/tube/mod.rs +++ b/src/bin/flat/tube/mod.rs @@ -4,6 +4,7 @@ use crate::riemann::Metric; use Subspace::{Boundary, Inner, Outer}; use metric::Tube; use coords::{FlatCoordinateSystem, InnerCS, OuterCS}; +use crate::tube::coords::FlatRegion; use crate::types::{FlatTraceResult, Hit, Location, Object, Ray}; pub mod metric; @@ -56,23 +57,17 @@ impl Space { pub fn trace_inner(&self, ray: Ray) -> FlatTraceResult { assert_eq!(self.which_subspace(ray.pos), Inner); - let cs = InnerCS(self.tube); - let inner = Rect { size: vec2(self.tube.inner_radius, self.tube.internal_halflength) }; - let ray = cs.global_to_flat(ray); - assert!(inner.is_inside(ray.pos)); - let dist = inner.trace_out_of(ray); - self.trace_flat(cs, ray, dist) + self.trace_flat(InnerCS(self.tube), ray) } pub fn trace_outer(&self, ray: Ray) -> FlatTraceResult { assert_eq!(self.which_subspace(ray.pos), Outer); - let cs = OuterCS(self.tube); - let outer = Rect { size: vec2(self.tube.outer_radius, self.tube.external_halflength) }; - let dist = outer.trace_into(ray); - self.trace_flat(cs, ray, dist) + self.trace_flat(OuterCS(self.tube), ray) } - fn trace_flat(&self, cs: impl FlatCoordinateSystem + FlatCoordinateSystem + FlatCoordinateSystem, ray: Ray, dist: Option) -> FlatTraceResult { + fn trace_flat(&self, cs: impl FlatRegion, ray: Ray) -> FlatTraceResult { + let ray = cs.global_to_flat(ray); + let dist = cs.distance_to_boundary(ray); let objs = self.list_objects(|loc| cs.global_to_flat(loc)); FlatTraceResult { end: dist.map(|dist| cs.flat_to_global(ray.forward(dist))), @@ -200,6 +195,11 @@ mod coords { fn global_to_flat(&self, v: T) -> T { v } } + pub trait FlatRegion: FlatCoordinateSystem + FlatCoordinateSystem + FlatCoordinateSystem { + // Измеряет расстояние до выхода за пределы области вдоль луча ray. Луч задаётся в плоской СК. + fn distance_to_boundary(&self, _ray: Ray) -> Option { None } + } + pub struct InnerCS(pub Tube); impl FlatCoordinateSystem for InnerCS { @@ -241,6 +241,12 @@ mod coords { } } + impl FlatRegion for InnerCS { + fn distance_to_boundary(&self, ray: Ray) -> Option { + Rect { size: vec2(self.0.inner_radius, self.0.internal_halflength) }.trace_out_of(ray) + } + } + pub struct OuterCS(pub Tube); impl FlatCoordinateSystem for OuterCS {} @@ -268,6 +274,12 @@ mod coords { } } + impl FlatRegion for OuterCS { + fn distance_to_boundary(&self, ray: Ray) -> Option { + Rect { size: vec2(self.0.outer_radius, self.0.external_halflength) }.trace_into(ray) + } + } + #[cfg(test)] mod test { use super::{Location, Tube, OuterCS, FlatCoordinateSystem};