From 4caa260a344dc7d94dd8c518e95e709de4f80e2a Mon Sep 17 00:00:00 2001 From: numzero Date: Tue, 25 Jun 2024 13:20:52 +0300 Subject: [PATCH] Remove single-implementation traits --- src/bin/flat/tube/mod.rs | 144 +++++++++++++++------------------------ 1 file changed, 55 insertions(+), 89 deletions(-) diff --git a/src/bin/flat/tube/mod.rs b/src/bin/flat/tube/mod.rs index 5f50b55..434caf8 100644 --- a/src/bin/flat/tube/mod.rs +++ b/src/bin/flat/tube/mod.rs @@ -3,7 +3,6 @@ use crate::riemann; use crate::riemann::Metric; use Subspace::{Boundary, Inner, Outer}; use metric::Tube; -use shape::Shape; use crate::types::{FlatTraceResult, Hit, Location, Object, Ray}; pub mod metric; @@ -76,7 +75,7 @@ impl Space { pub fn trace_outer(&self, ray: Ray) -> FlatTraceResult { assert_eq!(self.which_subspace(ray.pos), Outer); - let cell = basic_shapes::Rect { size: vec2(self.tube.outer_radius, self.tube.external_halflength) }; + let cell = Rect { size: vec2(self.tube.outer_radius, self.tube.external_halflength) }; let objs = self.list_objects_outer(); let lim = cell.trace_into(ray); let dist = lim.unwrap_or(f32::INFINITY); @@ -163,107 +162,81 @@ impl Space { } } -mod basic_shapes { - use glam::{Vec2, vec2}; - use crate::types::Ray; - use super::shape::Shape; +struct Rect { + pub size: Vec2, +} - pub struct Rect { - pub size: Vec2, +impl Rect { + /// Отражает луч, чтобы все координаты направления были положительны (допустимо благодаря симметрии Rect). + fn flip_ray(ray: Ray) -> Ray { + Ray { pos: ray.pos * ray.dir.signum(), dir: ray.dir.abs() } } - impl Rect { - /// Отражает луч, чтобы все координаты направления были положительны (допустимо благодаря симметрии Rect). - fn flip_ray(ray: Ray) -> Ray { - Ray { pos: ray.pos * ray.dir.signum(), dir: ray.dir.abs() } - } + fn is_inside(&self, pt: Vec2) -> bool { + pt.abs().cmplt(self.size).all() } - impl Shape for Rect { - fn is_inside(&self, pt: Vec2) -> bool { - pt.abs().cmplt(self.size).all() - } - - fn trace_into(&self, ray: Ray) -> Option { - let ray = Self::flip_ray(ray); - // ray.pos.x + t * ray.dir.x = −size.x - let ts = (-self.size - ray.pos) / ray.dir; - let t = ts.max_element(); - let pt = ray.pos + t * ray.dir; - if t < 0.0 { return None; } - if pt.cmpgt(self.size).any() { return None; } - Some(t) - } - - fn trace_out_of(&self, ray: Ray) -> Option { - let ray = Self::flip_ray(ray); - // ray.pos.x + t * ray.dir.x = +size.x - let ts = (self.size - ray.pos) / ray.dir; - let t = ts.min_element(); - Some(t) - } - - fn visualise(&self) -> Vec { - vec![vec2(-self.size.x, -self.size.y), vec2(self.size.x, -self.size.y), vec2(self.size.x, self.size.y), vec2(-self.size.x, self.size.y)] - } + fn trace_into(&self, ray: Ray) -> Option { + let ray = Self::flip_ray(ray); + // ray.pos.x + t * ray.dir.x = −size.x + let ts = (-self.size - ray.pos) / ray.dir; + let t = ts.max_element(); + let pt = ray.pos + t * ray.dir; + if t < 0.0 { return None; } + if pt.cmpgt(self.size).any() { return None; } + Some(t) } - #[test] - fn test_rect() { - assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 5.0) }), Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 5.0) }); - assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(-4.0, 5.0) }), Ray { pos: vec2(-2.0, 3.0), dir: vec2(4.0, 5.0) }); - assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, -5.0) }), Ray { pos: vec2(2.0, -3.0), dir: vec2(4.0, 5.0) }); - assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 0.0) }), Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 0.0) }); + fn trace_out_of(&self, ray: Ray) -> Option { + let ray = Self::flip_ray(ray); + // ray.pos.x + t * ray.dir.x = +size.x + let ts = (self.size - ray.pos) / ray.dir; + let t = ts.min_element(); + Some(t) + } - let r = Rect { size: vec2(2.0, 3.0) }; - - assert_eq!(r.trace_into(Ray { pos: vec2(3.0, 3.0), dir: vec2(1.0, 1.0) }), None); - assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 2.0), dir: vec2(1.0, 0.0) }), Some(1.0)); - assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 2.0), dir: vec2(-1.0, 0.0) }), None); - assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 1.0), dir: vec2(2.0, 2.0) }), Some(0.5)); - assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 2.1), dir: vec2(2.0, 2.0) }), None); - - assert_eq!(r.trace_into(Ray { pos: vec2(2.0, 3.0), dir: vec2(1.0, 1.0) }), None); - assert_eq!(r.trace_into(Ray { pos: vec2(-2.0, 3.0), dir: vec2(-1.0, 1.0) }), None); - assert_eq!(r.trace_into(Ray { pos: vec2(2.0, 3.0), dir: vec2(-1.0, -1.0) }), Some(0.0)); - assert_eq!(r.trace_into(Ray { pos: vec2(2.0, -3.0), dir: vec2(-1.0, 1.0) }), Some(0.0)); - - assert_eq!(r.trace_out_of(Ray { pos: vec2(0.0, 0.0), dir: vec2(1.0, 1.0) }), Some(2.0)); - assert_eq!(r.trace_out_of(Ray { pos: vec2(0.0, 0.0), dir: vec2(0.0, 1.0) }), Some(3.0)); - assert_eq!(r.trace_out_of(Ray { pos: vec2(0.0, 1.0), dir: vec2(0.0, -1.0) }), Some(4.0)); - assert_eq!(r.trace_out_of(Ray { pos: vec2(1.0, 1.0), dir: vec2(0.0, -1.0) }), Some(4.0)); - assert_eq!(r.trace_out_of(Ray { pos: vec2(2.0, 3.0), dir: vec2(1.0, 1.0) }), Some(0.0)); + fn visualise(&self) -> Vec { + vec![vec2(-self.size.x, -self.size.y), vec2(self.size.x, -self.size.y), vec2(self.size.x, self.size.y), vec2(-self.size.x, self.size.y)] } } -mod shape { - use glam::Vec2; - use crate::types::Ray; +#[test] +fn test_rect() { + assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 5.0) }), Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 5.0) }); + assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(-4.0, 5.0) }), Ray { pos: vec2(-2.0, 3.0), dir: vec2(4.0, 5.0) }); + assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, -5.0) }), Ray { pos: vec2(2.0, -3.0), dir: vec2(4.0, 5.0) }); + assert_eq!(Rect::flip_ray(Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 0.0) }), Ray { pos: vec2(2.0, 3.0), dir: vec2(4.0, 0.0) }); - pub trait Shape { - fn is_inside(&self, pt: Vec2) -> bool; + let r = Rect { size: vec2(2.0, 3.0) }; - /// Ищет ближайшее пересечение луча с границей в направлении внутрь контура. Возвращает расстояние (в ray.dir). - fn trace_into(&self, ray: Ray) -> Option; - /// Ищет ближайшее пересечение луча с границей в направлении вовне контура. Возвращает расстояние (в ray.dir). - fn trace_out_of(&self, ray: Ray) -> Option; + assert_eq!(r.trace_into(Ray { pos: vec2(3.0, 3.0), dir: vec2(1.0, 1.0) }), None); + assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 2.0), dir: vec2(1.0, 0.0) }), Some(1.0)); + assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 2.0), dir: vec2(-1.0, 0.0) }), None); + assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 1.0), dir: vec2(2.0, 2.0) }), Some(0.5)); + assert_eq!(r.trace_into(Ray { pos: vec2(-3.0, 2.1), dir: vec2(2.0, 2.0) }), None); - /// Возвращает визуальное представление контура, для отладки. - fn visualise(&self) -> Vec; - } + assert_eq!(r.trace_into(Ray { pos: vec2(2.0, 3.0), dir: vec2(1.0, 1.0) }), None); + assert_eq!(r.trace_into(Ray { pos: vec2(-2.0, 3.0), dir: vec2(-1.0, 1.0) }), None); + assert_eq!(r.trace_into(Ray { pos: vec2(2.0, 3.0), dir: vec2(-1.0, -1.0) }), Some(0.0)); + assert_eq!(r.trace_into(Ray { pos: vec2(2.0, -3.0), dir: vec2(-1.0, 1.0) }), Some(0.0)); + + assert_eq!(r.trace_out_of(Ray { pos: vec2(0.0, 0.0), dir: vec2(1.0, 1.0) }), Some(2.0)); + assert_eq!(r.trace_out_of(Ray { pos: vec2(0.0, 0.0), dir: vec2(0.0, 1.0) }), Some(3.0)); + assert_eq!(r.trace_out_of(Ray { pos: vec2(0.0, 1.0), dir: vec2(0.0, -1.0) }), Some(4.0)); + assert_eq!(r.trace_out_of(Ray { pos: vec2(1.0, 1.0), dir: vec2(0.0, -1.0) }), Some(4.0)); + assert_eq!(r.trace_out_of(Ray { pos: vec2(2.0, 3.0), dir: vec2(1.0, 1.0) }), Some(0.0)); } -trait FlatCell: std::fmt::Debug { - fn pos_to_global(&self, pos: Vec2) -> Vec2; - fn pos_to_local(&self, pos: Vec2) -> Vec2; - fn ray_to_global(&self, ray: Ray) -> Ray; - fn ray_to_local(&self, ray: Ray) -> Ray; +#[derive(Debug)] +struct TubeInside { + tube: Tube, +} +impl TubeInside { fn is_inside(&self, pos: Vec2) -> bool { let bnd = self.local_bounds(); pos.cmpge(bnd.0).all() && pos.cmple(bnd.1).all() } - fn local_bounds(&self) -> (Vec2, Vec2); fn to_boundary(&self, ray: Ray) -> Option { assert!(self.is_inside(ray.pos)); @@ -288,14 +261,7 @@ trait FlatCell: std::fmt::Debug { None } } -} -#[derive(Debug)] -struct TubeInside { - tube: Tube, -} - -impl FlatCell for TubeInside { fn pos_to_global(&self, pos: Vec2) -> Vec2 { vec2(pos.x, self.tube.y(pos.y)) }