1use crate::Polygon;
7
8pub trait BspVisitor {
16 fn visit(&mut self, polygons: &[Polygon]);
21}
22
23#[derive(Debug, Default)]
25pub struct CollectingVisitor {
26 collected: Vec<Polygon>,
27}
28
29impl CollectingVisitor {
30 pub fn new() -> Self {
32 Self::default()
33 }
34
35 pub fn into_polygons(self) -> Vec<Polygon> {
37 self.collected
38 }
39
40 pub fn polygons(&self) -> &[Polygon] {
42 &self.collected
43 }
44}
45
46impl BspVisitor for CollectingVisitor {
47 fn visit(&mut self, polygons: &[Polygon]) {
48 self.collected.extend(polygons.iter().cloned());
49 }
50}
51
52pub struct FnVisitor<F>
54where
55 F: FnMut(&[Polygon]),
56{
57 func: F,
58}
59
60impl<F> FnVisitor<F>
61where
62 F: FnMut(&[Polygon]),
63{
64 pub fn new(func: F) -> Self {
66 Self { func }
67 }
68}
69
70impl<F> BspVisitor for FnVisitor<F>
71where
72 F: FnMut(&[Polygon]),
73{
74 fn visit(&mut self, polygons: &[Polygon]) {
75 (self.func)(polygons);
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82 use nalgebra::Point3;
83
84 fn make_triangle(a: [f32; 3], b: [f32; 3], c: [f32; 3]) -> Polygon {
85 Polygon::new(vec![
86 Point3::new(a[0], a[1], a[2]),
87 Point3::new(b[0], b[1], b[2]),
88 Point3::new(c[0], c[1], c[2]),
89 ])
90 }
91
92 #[test]
93 fn collecting_visitor_empty() {
94 let visitor = CollectingVisitor::new();
95 assert!(visitor.polygons().is_empty());
96 }
97
98 #[test]
99 fn collecting_visitor_collects() {
100 let mut visitor = CollectingVisitor::new();
101 let poly1 = make_triangle([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
102 let poly2 = make_triangle([0.0, 0.0, 1.0], [1.0, 0.0, 1.0], [0.0, 1.0, 1.0]);
103
104 visitor.visit(&[poly1.clone()]);
105 visitor.visit(&[poly2.clone()]);
106
107 let collected = visitor.into_polygons();
108 assert_eq!(collected.len(), 2);
109 assert_eq!(collected[0], poly1);
110 assert_eq!(collected[1], poly2);
111 }
112
113 #[test]
114 fn fn_visitor_calls_closure() {
115 let mut count = 0;
116 {
117 let mut visitor = FnVisitor::new(|polys: &[Polygon]| {
118 count += polys.len();
119 });
120
121 let poly = make_triangle([0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]);
122 visitor.visit(&[poly.clone(), poly]);
123 }
124 assert_eq!(count, 2);
125 }
126}