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:
97
crates/coremem/src/geom/region/constructed.rs
Normal file
97
crates/coremem/src/geom/region/constructed.rs
Normal file
@@ -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::collections::BTreeSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
mod constructed;
|
||||||
|
pub use constructed::*;
|
||||||
mod primitives;
|
mod primitives;
|
||||||
pub use 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> {
|
impl<R1: Region, R2: Region> Region for Union<R1, R2> {
|
||||||
fn contains(&self, p: Meters) -> bool {
|
fn contains(&self, p: Meters) -> bool {
|
||||||
self.0.contains(p) || self.1.contains(p)
|
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 {
|
pub fn new2(r1: R1, r2: R2) -> Self {
|
||||||
Self(r1, r2)
|
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> {
|
impl<R1: Region, R2: Region> Region for Intersection<R1, R2> {
|
||||||
|
Reference in New Issue
Block a user