Unify FCS<Location>

This commit is contained in:
numzero 2024-06-30 12:17:40 +03:00
parent b58dcbd4a9
commit 1c96c87173

View File

@ -199,8 +199,31 @@ mod coords {
fn distance_to_boundary(&self, _ray: Ray) -> Option<f32> { None } fn distance_to_boundary(&self, _ray: Ray) -> Option<f32> { None }
} }
trait MetricCS {
fn global_metric(&self) -> &impl Metric;
}
impl<T: FlatCoordinateSystem<Vec2> + MetricCS> FlatCoordinateSystem<Location> for T {
fn flat_to_global(&self, loc: Location) -> Location {
let pos = self.flat_to_global(loc.pos);
Location {
pos,
rot: Mat2::from(self.global_metric().sqrt_at(pos).inverse()) * loc.rot,
}
}
fn global_to_flat(&self, loc: Location) -> Location {
Location {
pos: self.global_to_flat(loc.pos), // в плоской СК для Inner или её продолжении на Outer
rot: Mat2::from(self.global_metric().sqrt_at(loc.pos)) * loc.rot,
}
}
}
pub struct InnerCS(pub Tube); pub struct InnerCS(pub Tube);
impl MetricCS for InnerCS { fn global_metric(&self) -> &impl Metric { &self.0 } }
impl FlatCoordinateSystem<Vec2> for InnerCS { impl FlatCoordinateSystem<Vec2> for InnerCS {
fn flat_to_global(&self, pos: Vec2) -> Vec2 { fn flat_to_global(&self, pos: Vec2) -> Vec2 {
vec2(pos.x, self.0.y(pos.y)) vec2(pos.x, self.0.y(pos.y))
@ -228,23 +251,6 @@ mod coords {
} }
} }
impl FlatCoordinateSystem<Location> for InnerCS {
fn flat_to_global(&self, loc: Location) -> Location {
let pos = self.flat_to_global(loc.pos);
Location {
pos,
rot: Mat2::from(self.0.sqrt_at(pos).inverse()) * loc.rot,
}
}
fn global_to_flat(&self, loc: Location) -> Location {
Location {
pos: self.global_to_flat(loc.pos), // в плоской СК для Inner или её продолжении на Outer
rot: Mat2::from(self.0.sqrt_at(loc.pos)) * loc.rot,
}
}
}
impl FlatRegion for InnerCS { impl FlatRegion for InnerCS {
fn distance_to_boundary(&self, ray: Ray) -> Option<f32> { fn distance_to_boundary(&self, ray: Ray) -> Option<f32> {
Rect { size: vec2(self.0.inner_radius, self.0.internal_halflength) }.trace_out_of(ray) Rect { size: vec2(self.0.inner_radius, self.0.internal_halflength) }.trace_out_of(ray)
@ -253,6 +259,8 @@ mod coords {
pub struct OuterCS(pub Tube); pub struct OuterCS(pub Tube);
impl MetricCS for OuterCS { fn global_metric(&self) -> &impl Metric { &self.0 } }
impl FlatCoordinateSystem<Vec2> for OuterCS { impl FlatCoordinateSystem<Vec2> for OuterCS {
fn flat_to_global(&self, pos: Vec2) -> Vec2 { fn flat_to_global(&self, pos: Vec2) -> Vec2 {
let inner = Rect { size: vec2(self.0.inner_radius + 1.0, self.0.external_halflength) }; let inner = Rect { size: vec2(self.0.inner_radius + 1.0, self.0.external_halflength) };
@ -279,31 +287,6 @@ mod coords {
impl FlatCoordinateSystem<Ray> for OuterCS {} impl FlatCoordinateSystem<Ray> for OuterCS {}
impl FlatCoordinateSystem<Location> for OuterCS {
fn flat_to_global(&self, loc: Location) -> Location {
let pos = self.flat_to_global(loc.pos);
Location {
pos,
rot: Mat2::from(self.0.sqrt_at(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 + 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);
Location {
pos: vec2(u, v), // в плоском продолжении СК Outer на область Inner
rot: Mat2::from(self.0.sqrt_at(loc.pos)) * loc.rot,
}
} else {
loc
}
}
}
impl FlatRegion for OuterCS { impl FlatRegion for OuterCS {
fn distance_to_boundary(&self, ray: Ray) -> Option<f32> { fn distance_to_boundary(&self, ray: Ray) -> Option<f32> {
Rect { size: vec2(self.0.outer_radius, self.0.external_halflength) }.trace_into(ray) Rect { size: vec2(self.0.outer_radius, self.0.external_halflength) }.trace_into(ray)