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.
This commit is contained in:
parent
19ff08ada8
commit
f737a4c916
|
@ -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<Torus, InvertedRegion<Cube>>, // rounded top
|
||||
Intersection<Torus, InvertedRegion<Cube>>, // 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<f32> {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<R1, R2> Union<R1, R2> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R0, R1> Union<R0, R1> {
|
||||
pub fn region0_of_2(&self) -> &R0 {
|
||||
&self.0
|
||||
}
|
||||
pub fn region1_of_2(&self) -> &R1 {
|
||||
&self.1
|
||||
}
|
||||
}
|
||||
impl<R0, R1, R2> Union3<R0, R1, R2> {
|
||||
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<R0, R1, R2, R3> Union4<R0, R1, R2, R3> {
|
||||
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<R1: Region, R2: Region> Region for Union<R1, R2> {
|
||||
fn contains(&self, p: Meters) -> bool {
|
||||
self.0.contains(p) || self.1.contains(p)
|
||||
|
@ -135,6 +171,12 @@ impl<R1, R2> Intersection<R1, R2> {
|
|||
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<R1: Region, R2: Region> Region for Intersection<R1, R2> {
|
||||
|
|
Loading…
Reference in New Issue