1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
use alga::general::RealField;
use na;
use num_traits::Float;
use {BoundingBox, Object};
#[derive(Clone, Debug, PartialEq)]
pub struct Sphere<S: RealField> {
radius: S,
bbox: BoundingBox<S>,
}
impl<S: RealField + Float> Sphere<S> {
pub fn new(r: S) -> Self {
Sphere {
radius: r,
bbox: BoundingBox::new(&na::Point3::new(-r, -r, -r), &na::Point3::new(r, r, r)),
}
}
}
impl<S: ::std::fmt::Debug + RealField + Float + From<f32>> Object<S> for Sphere<S> {
fn approx_value(&self, p: &na::Point3<S>, slack: S) -> S {
let approx = self.bbox.distance(p);
if approx <= slack {
na::Vector3::new(p.x, p.y, p.z).norm() - self.radius
} else {
approx
}
}
fn bbox(&self) -> &BoundingBox<S> {
&self.bbox
}
fn normal(&self, p: &na::Point3<S>) -> na::Vector3<S> {
na::Vector3::new(p.x, p.y, p.z).normalize()
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn simple() {
let s = Sphere::new(1.);
assert_ulps_eq!(s.approx_value(&na::Point3::new(0., 0., 0.), 0.), -1.);
assert_ulps_eq!(s.approx_value(&na::Point3::new(1., 0., 0.), 0.), 0.);
assert_ulps_eq!(s.approx_value(&na::Point3::new(2., 0., 0.), 0.), 1.);
}
}