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