Define a Torus region.

I mean, actual core memories are usually toroids, so...
This commit is contained in:
2020-11-29 17:43:32 -08:00
parent abac9be49c
commit 9dddf6406a
2 changed files with 53 additions and 0 deletions

View File

@@ -213,3 +213,46 @@ impl Display for CylinderZ {
write!(f, "d({:.1e}, {:.1e}) <= {:.1e}", self.center.x(), self.center.y(), self.radius) write!(f, "d({:.1e}, {:.1e}) <= {:.1e}", self.center.x(), self.center.y(), self.radius)
} }
} }
#[derive(Copy, Clone, Serialize, Deserialize)]
pub struct Torus {
center: Meters,
/// Unit-length vector describing the axis of the torus
normal: Meters,
/// Distance from origin to the "center" of the solid part of the torus
major_rad: Real,
/// Distance from a center-point of the torus to its surface
minor_rad: Real,
}
impl Torus {
pub fn new(center: Meters, normal: Meters, major_rad: Flt, minor_rad: Flt) -> Self {
Self {
center,
normal,
major_rad: Real::from_inner(major_rad),
minor_rad: Real::from_inner(minor_rad),
}
}
pub fn new_xy(center: Meters, major_rad: Flt, minor_rad: Flt) -> Self {
Self::new(center, Meters(Vec3::new(0.0, 0.0, 1.0)), major_rad, minor_rad)
}
pub fn new_xz(center: Meters, major_rad: Flt, minor_rad: Flt) -> Self {
Self::new(center, Meters(Vec3::new(0.0, 1.0, 0.0)), major_rad, minor_rad)
}
}
impl Region for Torus {
fn contains(&self, p: Meters) -> bool {
// a torus is the set of all points < distance `r` from the circle of radius `R`,
// where `r`= minor_rad, `R` = major_rad, and `center` and `normal` define the center and
// plane of the circle.
// 1. Project `p` onto the plane of the circle.
// 2. Find the point `q` on the circle which is nearest to `p`.
// 3. Consider the distance from `p` to `q`.
let p_on_plane = *p - self.normal.with_mag(self.normal.dot(*p));
let q = (p_on_plane - *self.center).with_mag(self.major_rad.into_inner());
let distance_to_circle = (*p - q).mag();
distance_to_circle < self.minor_rad.into_inner()
}
}

View File

@@ -179,6 +179,16 @@ impl Vec3 {
z: self.z / other.z, z: self.z / other.z,
} }
} }
pub fn with_mag(&self, new_mag: Flt) -> Vec3 {
if new_mag == 0.0 {
// avoid div-by-zero if self.mag() == 0 and new_mag == 0
Self::zero()
} else {
let scale = Real::from_inner(new_mag) / self.mag();
self.clone() * scale.into_inner()
}
}
} }
impl Into<(Flt, Flt, Flt)> for Vec3 { impl Into<(Flt, Flt, Flt)> for Vec3 {