Skip to main content

acacia/partition/
boxes.rs

1//! Box partitioning
2
3use nalgebra::{Vector2, Vector3};
4#[cfg(any(test, feature = "arbitrary"))]
5use quickcheck::{Arbitrary, Gen};
6use partition::{Partition, Subdivide, Interval, Mid};
7use std::fmt::Debug;
8
9
10macro_rules! impl_box {
11    ($b: ident, $($param: ident),*) => (
12        impl<T> $b<T> {
13            /// Create a new box from intervals
14            pub fn new($($param: Interval<T>),*) -> $b<T> {
15                $b { $($param: $param),* }
16            }
17        }
18    )
19}
20
21macro_rules! impl_partition_for_box {
22    ($b: ident, $v: ident, $($param: ident),*) => (
23        impl<T: Mid + PartialOrd + Copy> Subdivide for $b<T> {
24            fn subdivide(&self) -> Vec<$b<T>> {
25                let mut subs = vec![];
26                $(let $param = self.$param.subdivide();)*
27                subs.extend(
28                    iproduct!($($param.iter()),*)
29                        .map(|($(&$param),*)| $b::new($($param),*))
30                );
31                subs
32            }
33        }
34
35        impl<T: Debug + Mid + PartialOrd + Copy + 'static> Partition<$v<T>> for $b<T> {
36            fn contains(&self, elem: &$v<T>) -> bool {
37                true $(&& self.$param.contains(&elem.$param))*
38            }
39        }
40    )
41}
42
43macro_rules! impl_arb_for_box {
44    ($b: ident, $($param: ident),*) => (
45        #[cfg(any(test, feature = "arbitrary"))]
46        impl<T: PartialOrd + Arbitrary> Arbitrary for $b<T> {
47            fn arbitrary<G: Gen>(g: &mut G) -> $b<T> {
48                $b { $($param: Arbitrary::arbitrary(g)),* }
49            }
50        }
51    )
52}
53
54
55/// A 2d box of intervals
56#[derive(Copy, Clone, Debug)]
57pub struct Box2<T> {
58    x: Interval<T>,
59    y: Interval<T>,
60}
61
62impl_box!(Box2, x, y);
63impl_partition_for_box!(Box2, Vector2, x, y);
64impl_arb_for_box!(Box2, x, y);
65
66
67/// A 3d box of intervals
68#[derive(Copy, Clone, Debug)]
69pub struct Box3<T> {
70    x: Interval<T>,
71    y: Interval<T>,
72    z: Interval<T>,
73}
74
75impl_box!(Box3, x, y, z);
76impl_partition_for_box!(Box3, Vector3, x, y, z);
77impl_arb_for_box!(Box3, x, y, z);
78
79
80#[cfg(test)]
81mod test {
82    pub use nalgebra::{Vector2, Vector3};
83    pub use super::*;
84
85    partition_quickcheck!(box2_f32_partition, Box2<f32>, Vector2<f32>);
86    partition_quickcheck!(box2_f64_partition, Box2<f64>, Vector2<f64>);
87    partition_quickcheck!(box3_f32_partition, Box3<f32>, Vector3<f32>);
88    partition_quickcheck!(box3_f64_partition, Box3<f64>, Vector3<f64>);
89}