mazth/
rbox.rs

1use i_bound::IBound;
2use i_shape::{IShape, ShapeType};
3use i_vicinity::IVicinity;
4
5use bound::AxisAlignedBBox;
6use mat::Mat3x1;
7
8#[derive(Debug, Clone)]
9pub struct RecBox {
10    pub _ori: Mat3x1<f64>,
11    pub _size: f64,
12    pub _bound: AxisAlignedBBox,
13    pub _vicinity: f64,
14}
15
16impl RecBox {
17    pub fn init(origin: &[f64], size: f64) -> RecBox {
18        assert!(origin.len() == 3);
19        RecBox {
20            _ori: Mat3x1 {
21                _val: [origin[0], origin[1], origin[2]],
22            },
23            _size: size, //half of the length of box edge
24            _bound: AxisAlignedBBox::init(ShapeType::Box, &[&origin[0..3], &[size]].concat()),
25            _vicinity: 0.000001f64,
26        }
27    }
28}
29
30impl IShape for RecBox {
31    fn get_shape_data(&self) -> Vec<f64> {
32        vec![self._ori[0], self._ori[1], self._ori[2], self._size]
33    }
34    fn get_type(&self) -> ShapeType {
35        ShapeType::Box
36    }
37    fn get_bound(&self) -> &dyn IBound {
38        &self._bound
39    }
40    // this shall test for intersection of bounding shapes first before procedding to test intersection using algorithms of higher complexity
41    fn get_intersect(&self, other: &dyn IShape) -> (bool, Option<Mat3x1<f64>>) {
42        if !self.get_bound().intersect(other.get_bound()) {
43            return (false, None);
44        } else {
45            match other.get_type() {
46                ShapeType::Point => {
47                    //covered by bbox test
48                    let other_shape_data = other.get_shape_data();
49                    let b_off = Mat3x1 {
50                        _val: [
51                            other_shape_data[0],
52                            other_shape_data[1],
53                            other_shape_data[2],
54                        ],
55                    };
56                    return (true, Some(b_off));
57                }
58                _ => {
59                    unimplemented!();
60                }
61            }
62        }
63    }
64    fn get_support(&self, v: &Mat3x1<f64>) -> Option<Mat3x1<f64>> {
65        if v.magnitude() != Some(0f64) {
66            //get a furthest point in the given direction v
67            let points = [
68                Mat3x1 {
69                    _val: [self._size, self._size, self._size],
70                },
71                Mat3x1 {
72                    _val: [-self._size, self._size, self._size],
73                },
74                Mat3x1 {
75                    _val: [self._size, -self._size, self._size],
76                },
77                Mat3x1 {
78                    _val: [-self._size, -self._size, self._size],
79                },
80                Mat3x1 {
81                    _val: [self._size, self._size, -self._size],
82                },
83                Mat3x1 {
84                    _val: [-self._size, self._size, -self._size],
85                },
86                Mat3x1 {
87                    _val: [self._size, -self._size, -self._size],
88                },
89                Mat3x1 {
90                    _val: [-self._size, -self._size, -self._size],
91                },
92            ];
93
94            let furthest = points
95                .iter()
96                .map(|x| x.dot(v).unwrap())
97                .enumerate()
98                .max_by(|a, b| a.1.partial_cmp(&b.1).unwrap())
99                .unwrap();
100
101            let o = self
102                ._ori
103                .plus(&points[furthest.0])
104                .expect("support operation unsuccessful.");
105            Some(o)
106        } else {
107            None
108        }
109    }
110}
111
112impl IVicinity<f64> for RecBox {
113    fn set_vicinity(&mut self, epsilon: f64) {
114        self._vicinity = epsilon.abs();
115    }
116    fn within_vicinity(&self, a: f64, b: f64) -> bool {
117        if a + self._vicinity >= b && a - self._vicinity <= b {
118            true
119        } else {
120            false
121        }
122    }
123}