implement a Spiral region
this isn't 100% what i need for my buffer, but i should be able to create some morph that wraps this cylinder-like spiral into a torus spiral.
This commit is contained in:
@@ -157,6 +157,36 @@ impl Region for Cube {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// a Spiral traces out a circle on the xy plane as z increases.
|
||||||
|
#[derive(Copy, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct Spiral {
|
||||||
|
/// radius of the spiral
|
||||||
|
major: f32,
|
||||||
|
/// effective "width" of the spiral.
|
||||||
|
/// any point within this distance from the 1-dimensional spiral is considered to be in the
|
||||||
|
/// region.
|
||||||
|
minor: f32,
|
||||||
|
/// determines how stretched the spiral is in z-space.
|
||||||
|
/// the xy plane at z=0 looks identical again at t=period.
|
||||||
|
period: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Spiral {
|
||||||
|
pub fn new(major: f32, minor: f32, period: f32) -> Self {
|
||||||
|
Self { major, minor, period }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[typetag::serde]
|
||||||
|
impl Region for Spiral {
|
||||||
|
fn contains(&self, p: Meters) -> bool {
|
||||||
|
let revs = p.z() / self.period;
|
||||||
|
let expected_angle = (revs % 1.0) * std::f32::consts::PI * 2.0;
|
||||||
|
let expected = Meters::new(self.major * expected_angle.cos(), self.major * expected_angle.sin(), p.z());
|
||||||
|
p.distance_sq(*expected) < self.minor * self.minor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
@@ -286,6 +316,62 @@ mod test {
|
|||||||
assert!(tor.contains(Meters::new(1.0, 2.0, 12.0)));
|
assert!(tor.contains(Meters::new(1.0, 2.0, 12.0)));
|
||||||
assert!(!tor.contains(Meters::new(1.0, 2.0, 13.0)));
|
assert!(!tor.contains(Meters::new(1.0, 2.0, 13.0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_spiral_doesnt_contain_zero() {
|
||||||
|
let spiral = Spiral::new(10.0, 1.0, 4.0);
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 0.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 1.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 2.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 3.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 4.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 5.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 6.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 7.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 8.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 9.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 10.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(0.0, 0.0, 11.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_spiral_exactly_on_course() {
|
||||||
|
let spiral = Spiral::new(10.0, 1.0, 4.0);
|
||||||
|
assert!(spiral.contains(Meters::new(10.0, 0.0, 0.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(0.0, 10.0, 1.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(-10.0, 0.0, 2.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(0.0, -10.0, 3.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(10.0, 0.0, 4.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(0.0, 10.0, 5.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_spiral_exactly_on_course_negative() {
|
||||||
|
let spiral = Spiral::new(10.0, 1.0, 4.0);
|
||||||
|
assert!(spiral.contains(Meters::new(0.0, -10.0, -1.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(-10.0, 0.0, -2.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(0.0, 10.0, -3.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(10.0, 0.0, -4.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(0.0, -10.0, -5.0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_spiral_within_minor_radius() {
|
||||||
|
let spiral = Spiral::new(10.0, 1.0, 4.0);
|
||||||
|
assert!(spiral.contains(Meters::new(10.5, 0.0, 0.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(10.5, -0.5, 0.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(9.1, 0.0, 0.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(8.9, 0.0, 0.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(9.1, 0.9, 0.0)));
|
||||||
|
|
||||||
|
assert!(spiral.contains(Meters::new(0.5, 10.5, 1.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(-0.9, 10.0, 1.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(-0.9, 10.9, 1.0)));
|
||||||
|
|
||||||
|
assert!(spiral.contains(Meters::new(-10.9, 0.0, 2.0)));
|
||||||
|
assert!(spiral.contains(Meters::new(-10.0, 0.6, 2.0)));
|
||||||
|
assert!(!spiral.contains(Meters::new(-10.8, 0.8, 2.0)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user