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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
use euclid::{
default::{Rect, Transform3D},
rect, vec3, Angle,
};
use plane_split::PlaneCut;
use plane_split::{make_grid, BspSplitter, Polygon};
use std::f64::consts::FRAC_PI_4;
fn grid_impl(count: usize, splitter: &mut BspSplitter<usize>) {
let polys = make_grid(count);
let result = splitter.solve(&polys, vec3(0.0, 0.0, 1.0));
assert_eq!(result.len(), count + count * count + count * count * count);
}
#[test]
fn grid_bsp() {
grid_impl(2, &mut BspSplitter::new());
}
fn sort_rotation(splitter: &mut BspSplitter<usize>) {
let transform0: Transform3D<f64> =
Transform3D::rotation(0.0, 1.0, 0.0, Angle::radians(-FRAC_PI_4));
let transform1: Transform3D<f64> = Transform3D::rotation(0.0, 1.0, 0.0, Angle::radians(0.0));
let transform2: Transform3D<f64> =
Transform3D::rotation(0.0, 1.0, 0.0, Angle::radians(FRAC_PI_4));
let rect: Rect<f64> = rect(-10.0, -10.0, 20.0, 20.0);
let p1 = Polygon::from_transformed_rect(rect, transform0, 0);
let p2 = Polygon::from_transformed_rect(rect, transform1, 1);
let p3 = Polygon::from_transformed_rect(rect, transform2, 2);
assert!(
p1.is_some() && p2.is_some() && p3.is_some(),
"Cannot construct transformed polygons"
);
let polys = [p1.unwrap(), p2.unwrap(), p3.unwrap()];
let result = splitter.solve(&polys, vec3(0.0, 0.0, -1.0));
let ids: Vec<_> = result.iter().map(|poly| poly.anchor).collect();
assert_eq!(&ids, &[2, 1, 0, 1, 2]);
}
#[test]
fn rotation_bsp() {
sort_rotation(&mut BspSplitter::new());
}
fn sort_trivial(splitter: &mut BspSplitter<usize>) {
let anchors: Vec<_> = (0usize..10).collect();
let rect: Rect<f64> = rect(-10.0, -10.0, 20.0, 20.0);
let polys: Vec<_> = anchors
.iter()
.map(|&anchor| {
let transform: Transform3D<f64> = Transform3D::translation(0.0, 0.0, anchor as f64);
let poly = Polygon::from_transformed_rect(rect, transform, anchor);
assert!(poly.is_some(), "Cannot construct transformed polygons");
poly.unwrap()
})
.collect();
let result = splitter.solve(&polys, vec3(0.0, 0.0, -1.0));
let anchors1: Vec<_> = result.iter().map(|p| p.anchor).collect();
let mut anchors2 = anchors1.clone();
anchors2.sort_by_key(|&a| -(a as i32));
//make sure Z is sorted backwards
assert_eq!(anchors1, anchors2);
}
fn sort_external(splitter: &mut BspSplitter<usize>) {
let rect0: Rect<f64> = rect(-10.0, -10.0, 20.0, 20.0);
let poly0 = Polygon::from_rect(rect0, 0);
let poly1 = {
let transform0: Transform3D<f64> =
Transform3D::rotation(1.0, 0.0, 0.0, Angle::radians(2.0 * FRAC_PI_4));
let transform1: Transform3D<f64> = Transform3D::translation(0.0, 100.0, 0.0);
Polygon::from_transformed_rect(rect0, transform0.then(&transform1), 1).unwrap()
};
let result = splitter.solve(&[poly0, poly1], vec3(1.0, 1.0, 0.0).normalize());
let anchors: Vec<_> = result.iter().map(|p| p.anchor).collect();
// make sure the second polygon is split in half around the plane of the first one,
// even if geometrically their polygons don't intersect.
assert_eq!(anchors, vec![1, 0, 1]);
}
#[test]
fn trivial_bsp() {
sort_trivial(&mut BspSplitter::new());
}
#[test]
fn external_bsp() {
sort_external(&mut BspSplitter::new());
}
#[test]
fn test_cut() {
use smallvec::SmallVec;
let rect: Rect<f64> = rect(-10.0, -10.0, 20.0, 20.0);
let poly = Polygon::from_rect(rect, 0);
let mut poly2 = Polygon::from_rect(rect, 0);
// test robustness for positions
for p in &mut poly2.points {
p.z += 0.00000001;
}
let mut front: SmallVec<[Polygon<i32>; 2]> = SmallVec::new();
let mut back: SmallVec<[Polygon<i32>; 2]> = SmallVec::new();
assert_eq!(poly.cut(&poly2, &mut front, &mut back), PlaneCut::Sibling);
assert!(front.is_empty());
assert!(back.is_empty());
// test robustness for normal
poly2.plane.normal.z += 0.00000001;
assert_eq!(poly.cut(&poly2, &mut front, &mut back), PlaneCut::Sibling);
assert!(front.is_empty());
assert!(back.is_empty());
// test opposite normal handling
poly2.plane.normal *= -1.0;
assert_eq!(poly.cut(&poly2, &mut front, &mut back), PlaneCut::Sibling);
assert!(front.is_empty());
assert!(back.is_empty());
// test grouping front
poly2.plane.offset += 0.1;
assert_eq!(poly.cut(&poly2, &mut front, &mut back), PlaneCut::Cut);
assert_eq!(front.len(), 1);
assert!(back.is_empty());
front.clear();
// test grouping back
poly2.plane.normal *= -1.0;
assert_eq!(poly.cut(&poly2, &mut front, &mut back), PlaneCut::Cut);
assert_eq!(back.len(), 1);
assert!(front.is_empty());
}
|