From f737a4c9163be696effd1c53e84a3160e0529f0f Mon Sep 17 00:00:00 2001 From: colin Date: Thu, 1 Sep 2022 18:39:32 -0700 Subject: [PATCH] region: add an ElongatedTorus type this is needed for when we want to couple some cores, but require a narrower space to do so in. --- crates/coremem/src/geom/region/constructed.rs | 97 +++++++++++++++++++ crates/coremem/src/geom/region/mod.rs | 42 ++++++++ 2 files changed, 139 insertions(+) create mode 100644 crates/coremem/src/geom/region/constructed.rs diff --git a/crates/coremem/src/geom/region/constructed.rs b/crates/coremem/src/geom/region/constructed.rs new file mode 100644 index 0000000..d464026 --- /dev/null +++ b/crates/coremem/src/geom/region/constructed.rs @@ -0,0 +1,97 @@ +use crate::geom::Meters; +use super::{ + and_not, + Cube, + HasCrossSection, + Intersection, + InvertedRegion, + Region, + Torus, + Union, + Union4, +}; +use coremem_cross::vec::Vec3; + +/// it's a torus, but elongated around its axis to resemble a pill shape. +/// +/// ``` +/// _______ +/// / \ +/// | | +/// \_______/ +/// ``` +pub struct ElongatedTorus(Union4< + Intersection>, // rounded top + Intersection>, // rounded bottom + Cube, // left connection between top/bot + Cube, // right connection between top/bot +>); + +impl ElongatedTorus { + pub fn new_xz(center: Meters, length: f32, major_rad: f32, minor_rad: f32) -> Self { + let body = Cube::new_centered( + center, + Meters::new(2.0 * (major_rad + minor_rad), 2.0 * minor_rad, length), + ); + let top = and_not( + Torus::new_xz( + center + Meters::new(0.0, 0.0, length), + major_rad, + minor_rad, + ), + body, + ); + let bot = and_not( + Torus::new_xz( + center - Meters::new(0.0, 0.0, length), + major_rad, + minor_rad, + ), + body, + ); + // TODO: these should be cylinders + let left = Cube::new_centered( + center - Meters::new(major_rad, 0.0, 0.0), + Meters::new(2.0 * minor_rad, 2.0 * minor_rad, length), + ); + let right = Cube::new_centered( + center + Meters::new(major_rad, 0.0, 0.0), + Meters::new(2.0 * minor_rad, 2.0 * minor_rad, length), + ); + Self(Union::new4( + top, + bot, + left, + right, + )) + } +} + +impl Region for ElongatedTorus { + fn contains(&self, p: Meters) -> bool { + self.0.contains(p) + } +} + +impl HasCrossSection for ElongatedTorus { + fn cross_section_normal(&self, p: Meters) -> Vec3 { + let top = self.0.region0_of_4(); + let bot = self.0.region1_of_4(); + let right = self.0.region3_of_4(); + let left = self.0.region2_of_4(); + let bridge_area = + (right.x_range().end - right.x_range().start) + * (right.y_range().start - right.y_range().end); + if top.contains(p) { + top.region0_of_2().cross_section_normal(p) + } else if bot.contains(p) { + bot.region0_of_2().cross_section_normal(p) + } else if right.contains(p) { + Vec3::new(0.0, 0.0, bridge_area) + } else if left.contains(p) { + Vec3::new(0.0, 0.0, -bridge_area) + } else { + Vec3::default() + } + } +} diff --git a/crates/coremem/src/geom/region/mod.rs b/crates/coremem/src/geom/region/mod.rs index 29d48ee..bafec4d 100644 --- a/crates/coremem/src/geom/region/mod.rs +++ b/crates/coremem/src/geom/region/mod.rs @@ -7,6 +7,8 @@ use serde::{Serialize, Deserialize}; use std::collections::BTreeSet; use std::sync::Arc; +mod constructed; +pub use constructed::*; mod primitives; pub use primitives::*; @@ -118,6 +120,40 @@ impl Union { } } +impl Union { + pub fn region0_of_2(&self) -> &R0 { + &self.0 + } + pub fn region1_of_2(&self) -> &R1 { + &self.1 + } +} +impl Union3 { + pub fn region0_of_3(&self) -> &R0 { + self.0.region0_of_2() + } + pub fn region1_of_3(&self) -> &R1 { + self.0.region1_of_2() + } + pub fn region2_of_3(&self) -> &R2 { + &self.1 + } +} +impl Union4 { + pub fn region0_of_4(&self) -> &R0 { + self.0.region0_of_3() + } + pub fn region1_of_4(&self) -> &R1 { + self.0.region1_of_3() + } + pub fn region2_of_4(&self) -> &R2 { + self.0.region2_of_3() + } + pub fn region3_of_4(&self) -> &R3 { + &self.1 + } +} + impl Region for Union { fn contains(&self, p: Meters) -> bool { self.0.contains(p) || self.1.contains(p) @@ -135,6 +171,12 @@ impl Intersection { pub fn new2(r1: R1, r2: R2) -> Self { Self(r1, r2) } + pub fn region0_of_2(&self) -> &R1 { + &self.0 + } + pub fn region1_of_2(&self) -> &R2 { + &self.1 + } } impl Region for Intersection {