Make the tube actually cylindrical

This commit is contained in:
numzero 2024-11-07 02:42:52 +03:00
parent 401b10faae
commit e57692587a
3 changed files with 41 additions and 35 deletions

View File

@ -3,7 +3,7 @@ use glam::{vec3, Mat3, Vec3};
use crate::riemann::Metric; use crate::riemann::Metric;
use crate::types::{Location, Ray}; use crate::types::{Location, Ray};
use super::{Rect, Tube}; use super::{Tube, YCylinder};
pub trait FlatCoordinateSystem<T> { pub trait FlatCoordinateSystem<T> {
fn flat_to_global(&self, v: T) -> T; fn flat_to_global(&self, v: T) -> T;
@ -80,8 +80,9 @@ impl FlatCoordinateSystem<Vec3> for InnerCS {
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 { YCylinder {
size: vec3(self.0.inner_radius, self.0.internal_halflength, self.0.inner_radius), radius: self.0.inner_radius,
half_length: self.0.internal_halflength,
} }
.trace_out_of(ray) .trace_out_of(ray)
} }
@ -97,12 +98,9 @@ impl MetricCS for OuterCS {
impl FlatCoordinateSystem<Vec3> for OuterCS { impl FlatCoordinateSystem<Vec3> for OuterCS {
fn flat_to_global(&self, pos: Vec3) -> Vec3 { fn flat_to_global(&self, pos: Vec3) -> Vec3 {
let inner = Rect { let inner = YCylinder {
size: vec3( radius: self.0.inner_radius + 1.0,
self.0.inner_radius + 1.0, half_length: self.0.external_halflength,
self.0.external_halflength,
self.0.inner_radius + 1.0,
),
}; };
if inner.is_inside(pos) { if inner.is_inside(pos) {
let Vec3 { x, y: v, z } = pos; let Vec3 { x, y: v, z } = pos;
@ -116,12 +114,9 @@ impl FlatCoordinateSystem<Vec3> for OuterCS {
} }
fn global_to_flat(&self, pos: Vec3) -> Vec3 { fn global_to_flat(&self, pos: Vec3) -> Vec3 {
let inner = Rect { let inner = YCylinder {
size: vec3( radius: self.0.inner_radius + 1.0,
self.0.inner_radius + 1.0, half_length: self.0.external_halflength,
self.0.external_halflength,
self.0.inner_radius + 1.0,
),
}; };
if inner.is_inside(pos) { if inner.is_inside(pos) {
let Vec3 { x: u, y, z: w } = pos; // в основной СК let Vec3 { x: u, y, z: w } = pos; // в основной СК
@ -135,8 +130,9 @@ impl FlatCoordinateSystem<Vec3> for OuterCS {
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 { YCylinder {
size: vec3(self.0.outer_radius, self.0.external_halflength, self.0.outer_radius), radius: self.0.outer_radius,
half_length: self.0.external_halflength,
} }
.trace_into(ray) .trace_into(ray)
} }
@ -346,15 +342,16 @@ mod tests {
external_halflength: 300.0, external_halflength: 300.0,
}); });
// TODO replace 200.20016 with something sane // TODO replace 200.20016 with something sane
// NOTE it cant test 30..30 as that area intersects the boundary
test_flat_region( test_flat_region(
&mapper, &mapper,
(vec3(-30.0, -300.0, -30.0), vec3(30.0, -1.0, 30.0)), (vec3(-20.0, -300.0, -20.0), vec3(20.0, -1.0, 20.0)),
(vec3(-30.0, -300.0, -30.0), vec3(30.0, -200.20016, 30.0)), (vec3(-20.0, -300.0, -20.0), vec3(20.0, -200.20016, 20.0)),
); );
test_flat_region( test_flat_region(
&mapper, &mapper,
(vec3(-30.0, 1.0, -30.0), vec3(30.0, 300.0, 30.0)), (vec3(-20.0, 1.0, -20.0), vec3(20.0, 300.0, 20.0)),
(vec3(-30.0, 200.20016, -30.0), vec3(30.0, 300.0, 30.0)), (vec3(-20.0, 200.20016, -20.0), vec3(20.0, 300.0, 20.0)),
); );
test_flat_region( test_flat_region(
&mapper, &mapper,
@ -451,9 +448,9 @@ mod tests {
} }
} }
// accelerating // accelerating
for x in linspace(-29., 29., 20) { for x in linspace(-21., 21., 20) {
for y in linspace(1., 299., 20) { for y in linspace(1., 299., 20) {
for z in linspace(-29., 29., 20) { for z in linspace(-21., 21., 20) {
let v = mapper let v = mapper
.global_to_flat(Location { .global_to_flat(Location {
pos: vec3(x, y, z), pos: vec3(x, y, z),

View File

@ -42,10 +42,11 @@ impl Tube {
impl Metric for Tube { impl Metric for Tube {
fn sqrt_at(&self, pos: Vec3) -> Decomp3 { fn sqrt_at(&self, pos: Vec3) -> Decomp3 {
let sx = self.fx().value(pos.x); let r = f32::hypot(pos.x, pos.z);
let sr = self.fx().value(r);
let sy = self.fy().du(pos.y); let sy = self.fy().du(pos.y);
let s = sx + sy - sx * sy; let s = sr + sy - sr * sy;
assert!(sx.is_finite()); assert!(sr.is_finite());
assert!(sy.is_finite()); assert!(sy.is_finite());
assert!(sy > 0.0); assert!(sy > 0.0);
Decomp3 { Decomp3 {
@ -55,17 +56,23 @@ impl Metric for Tube {
} }
fn part_derivs_at(&self, pos: Vec3) -> Tens3 { fn part_derivs_at(&self, pos: Vec3) -> Tens3 {
let sx = self.fx().value(pos.x); let r = f32::hypot(pos.x, pos.z);
let sr = self.fx().value(r);
let sy = self.fy().du(pos.y); let sy = self.fy().du(pos.y);
let s = sx + sy - sx * sy; let s = sr + sy - sr * sy;
let dsx_dx = self.fx().derivative(pos.x); let dsr_dr = self.fx().derivative(r);
let dsy_dy = self.fy().d2u(pos.y); let dsy_dy = self.fy().d2u(pos.y);
let ds2_dx = 2.0 * s * (1.0 - sy) * dsx_dx; let ds2_dr = 2.0 * s * (1.0 - sy) * dsr_dr;
let ds2_dy = 2.0 * s * (1.0 - sx) * dsy_dy; let ds2_dy = 2.0 * s * (1.0 - sr) * dsy_dy;
let (ds2_dx, ds2_dz) = if ds2_dr.abs() < 1e-5 {
(0., 0.)
} else {
(ds2_dr * pos.x / r, ds2_dr * pos.z / r)
};
[ [
Mat3::from_cols_array(&[0., 0., 0., 0., ds2_dx, 0., 0., 0., 0.]), Mat3::from_cols_array(&[0., 0., 0., 0., ds2_dx, 0., 0., 0., 0.]),
Mat3::from_cols_array(&[0., 0., 0., 0., ds2_dy, 0., 0., 0., 0.]), Mat3::from_cols_array(&[0., 0., 0., 0., ds2_dy, 0., 0., 0., 0.]),
Mat3::from_cols_array(&[0., 0., 0., 0., 0., 0., 0., 0., 0.]), Mat3::from_cols_array(&[0., 0., 0., 0., ds2_dz, 0., 0., 0., 0.]),
] ]
} }
} }

View File

@ -28,10 +28,12 @@ pub enum Subspace {
impl Space { impl Space {
fn which_subspace(&self, pt: Vec3) -> Subspace { fn which_subspace(&self, pt: Vec3) -> Subspace {
if pt.y.abs() > self.tube.external_halflength { if pt.y.abs() > self.tube.external_halflength {
return Outer;
}
let r = f32::hypot(pt.x, pt.z);
if r > self.tube.outer_radius {
Outer Outer
} else if pt.x.abs() > self.tube.outer_radius { } else if r > self.tube.inner_radius {
Outer
} else if pt.x.abs() > self.tube.inner_radius {
Boundary Boundary
} else { } else {
Inner Inner