packer_3d/
lib.rs

1/*! Rust Crate for 3-dimensional packing of boxes optimally along x, y or z, or all three axis.
2## Example
3```
4let mut my_boxes = vec![
5	Box3D::from_xyz_whl(0,0,0,100,200,300,1,0),
6	Box3D::from_xyz_whl(0,0,0,100,200,300,2,0),
7	Box3D::from_xyz_whl(0,0,0,100,200,300,3,0)
8];
9
10// Create our packer instance
11let mut my_instance = PackerInstance::new(
12	&mut my_boxes, // Our boxes
13	Vector3D::<u64>::new(500, 0, 500), // Our container size
14	true, // Allow rotations
15	(false, true, false), // Minimize height only
16	&Sorting::descending_volume // Our initial sorting heuristic
17);
18
19// Pack all 3 boxes
20for _ in 0..3 {
21	match my_instance.pack_next() {
22		Err(error) => println!("Error: {}", error),
23		Ok(()) => {}
24	}
25}
26
27println!("{:#?}", my_instance.boxes());
28```*/
29
30pub mod box3d;
31pub mod vector3d;
32pub mod sorting;
33
34use box3d::*;
35use vector3d::Vector3D;
36use std::cmp::Ordering;
37
38use std::collections::HashSet;
39use std::hash::BuildHasherDefault;
40use fnv::FnvHasher;
41
42/// Hash Set using [fnv](https://crates.io/crates/fnv): an implementation of the [Fowler–Noll–Vo hash function](http://www.isthe.com/chongo/tech/comp/fnv/index.html).
43/// ## Example
44/// ```rust
45/// let mut boxes = HashSetFnv::<Box3D>::default();
46/// boxes.insert(Box3D::from_xyz_whl(0, 0, 0, 100, 200, 300, 1, 0));
47/// ```
48pub type HashSetFnv<V> = HashSet<V, BuildHasherDefault<FnvHasher>>;
49
50/// # Minimize tuple
51/// Dictates which axis (x,y,z) the packer tries to minimize
52/// ## Example
53/// ```rust
54/// // x,    y,     z
55/// (true, false, true)
56/// ```
57/// Will minimize the width (x) of the container,\
58/// and the length (z) of the container\
59/// However, the height (y) of the container will be specified via container_size in [PackerInstance::new()](PackerInstance::new)
60pub type Minimize = (bool, bool, bool);
61
62fn cut(b: &Box3D, hole: &Box3D, holes: &mut HashSetFnv<Box3D>, next_hole_id: &mut usize)
63{
64	let mut new_holes = Vec::<Box3D>::default();
65
66	let x2 = b.x2();
67	let y2 = b.y2();
68	let z2 = b.z2();
69
70	let hx2 = hole.x2();
71	let hy2 = hole.y2();
72	let hz2 = hole.z2();
73
74	if
75		(b.position.x <= hole.position.x && x2 >= hx2) &&
76		(b.position.y <= hole.position.y && y2 >= hy2) &&
77		(b.position.z <= hole.position.z && z2 >= hz2)
78	{ }
79	else if
80		(b.position.x <= hole.position.x && x2 >= hx2) &&
81		(b.position.y <= hole.position.y && y2 >= hy2) &&
82		(b.position.z <= hole.position.z && z2 < hz2)
83	{
84		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 1));
85	}
86	else if
87		(b.position.x <= hole.position.x && x2 >= hx2) &&
88		(b.position.y <= hole.position.y && y2 >= hy2) &&
89		(b.position.z > hole.position.z && z2 >= hz2)
90	{
91		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 2));
92	}
93	else if
94		(b.position.x <= hole.position.x && x2 >= hx2) &&
95		(b.position.y <= hole.position.y && y2 >= hy2) &&
96		(b.position.z > hole.position.z && z2 < hz2)
97	{
98		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 3));
99		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 4));
100	}
101	else if
102		(b.position.x <= hole.position.x && x2 >= hx2) &&
103		(b.position.y <= hole.position.y && y2 < hy2) &&
104		(b.position.z <= hole.position.z && z2 >= hz2)
105	{
106		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 5));
107	}
108	else if
109		(b.position.x <= hole.position.x && x2 >= hx2) &&
110		(b.position.y <= hole.position.y && y2 < hy2) &&
111		(b.position.z <= hole.position.z && z2 < hz2)
112	{
113		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 6));
114		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 7));
115	}
116	else if
117		(b.position.x <= hole.position.x && x2 >= hx2) &&
118		(b.position.y <= hole.position.y && y2 < hy2) &&
119		(b.position.z > hole.position.z && z2 >= hz2)
120	{
121		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 8));
122		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 9));
123	}
124	else if
125		(b.position.x <= hole.position.x && x2 >= hx2) &&
126		(b.position.y <= hole.position.y && y2 < hy2) &&
127		(b.position.z > hole.position.z && z2 < hz2)
128	{
129		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 10));
130		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 11));
131		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 12));
132	}
133	else if
134		(b.position.x <= hole.position.x && x2 >= hx2) &&
135		(b.position.y > hole.position.y && y2 >= hy2) &&
136		(b.position.z <= hole.position.z && z2 >= hz2)
137	{
138		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 13));
139	}
140	else if
141		(b.position.x <= hole.position.x && x2 >= hx2) &&
142		(b.position.y > hole.position.y && y2 >= hy2) &&
143		(b.position.z <= hole.position.z && z2 < hz2)
144	{
145		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 14));
146		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 15));
147	}
148	else if
149		(b.position.x <= hole.position.x && x2 >= hx2) &&
150		(b.position.y > hole.position.y && y2 >= hy2) &&
151		(b.position.z > hole.position.z && z2 >= hz2)
152	{
153		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 16));
154		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 17));
155	}
156	else if
157		(b.position.x <= hole.position.x && x2 >= hx2) &&
158		(b.position.y > hole.position.y && y2 >= hy2) &&
159		(b.position.z > hole.position.z && z2 < hz2)
160	{
161		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 18));
162		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 19));
163		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 20));
164	}
165	else if
166		(b.position.x <= hole.position.x && x2 >= hx2) &&
167		(b.position.y > hole.position.y && y2 < hy2) &&
168		(b.position.z <= hole.position.z && z2 >= hz2)
169	{
170		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 21));
171		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 22));
172	}
173	else if
174		(b.position.x <= hole.position.x && x2 >= hx2) &&
175		(b.position.y > hole.position.y && y2 < hy2) &&
176		(b.position.z <= hole.position.z && z2 < hz2)
177	{
178		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 23));
179		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 24));
180		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 25));
181	}
182	else if
183		(b.position.x <= hole.position.x && x2 >= hx2) &&
184		(b.position.y > hole.position.y && y2 < hy2) &&
185		(b.position.z > hole.position.z && z2 >= hz2)
186	{
187		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 26));
188		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 27));
189		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 28));
190	}
191	else if
192		(b.position.x <= hole.position.x && x2 >= hx2) &&
193		(b.position.y > hole.position.y && y2 < hy2) &&
194		(b.position.z > hole.position.z && z2 < hz2)
195	{
196		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 29));
197		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 30));
198		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 31));
199		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 32));
200	}
201	else if
202		(b.position.x <= hole.position.x && x2 < hx2) &&
203		(b.position.y <= hole.position.y && y2 >= hy2) &&
204		(b.position.z <= hole.position.z && z2 >= hz2)
205	{
206		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 33));
207	}
208	else if
209		(b.position.x <= hole.position.x && x2 < hx2) &&
210		(b.position.y <= hole.position.y && y2 >= hy2) &&
211		(b.position.z <= hole.position.z && z2 < hz2)
212	{
213		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 34));
214		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 35));
215	}
216	else if
217		(b.position.x <= hole.position.x && x2 < hx2) &&
218		(b.position.y <= hole.position.y && y2 >= hy2) &&
219		(b.position.z > hole.position.z && z2 >= hz2)
220	{
221		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 36));
222		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 37));
223	}
224	else if
225		(b.position.x <= hole.position.x && x2 < hx2) &&
226		(b.position.y <= hole.position.y && y2 >= hy2) &&
227		(b.position.z > hole.position.z && z2 < hz2)
228	{
229		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 38));
230		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 39));
231		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 40));
232	}
233	else if
234		(b.position.x <= hole.position.x && x2 < hx2) &&
235		(b.position.y <= hole.position.y && y2 < hy2) &&
236		(b.position.z <= hole.position.z && z2 >= hz2)
237	{
238		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 41));
239		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 42));
240	}
241	else if
242		(b.position.x <= hole.position.x && x2 < hx2) &&
243		(b.position.y <= hole.position.y && y2 < hy2) &&
244		(b.position.z <= hole.position.z && z2 < hz2)
245	{
246		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 43));
247		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 44));
248		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 45));
249		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 46));
250		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 47));
251		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 48));
252	}
253	else if
254		(b.position.x <= hole.position.x && x2 < hx2) &&
255		(b.position.y <= hole.position.y && y2 < hy2) &&
256		(b.position.z > hole.position.z && z2 >= hz2)
257	{
258		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 49));
259		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 50));
260		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 51));
261		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 52));
262	}
263	else if
264		(b.position.x <= hole.position.x && x2 < hx2) &&
265		(b.position.y <= hole.position.y && y2 < hy2) &&
266		(b.position.z > hole.position.z && z2 < hz2)
267	{
268		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 53));
269		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 54));
270		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 55));
271		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 56));
272		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 57));
273		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 58));
274		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 59));
275		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 60));
276	}
277	else if
278		(b.position.x <= hole.position.x && x2 < hx2) &&
279		(b.position.y > hole.position.y && y2 >= hy2) &&
280		(b.position.z <= hole.position.z && z2 >= hz2)
281	{
282		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 61));
283		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 62));
284	}
285	else if
286		(b.position.x <= hole.position.x && x2 < hx2) &&
287		(b.position.y > hole.position.y && y2 >= hy2) &&
288		(b.position.z <= hole.position.z && z2 < hz2)
289	{
290		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 63));
291		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 64));
292		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 65));
293		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 66));
294	}
295	else if
296		(b.position.x <= hole.position.x && x2 < hx2) &&
297		(b.position.y > hole.position.y && y2 >= hy2) &&
298		(b.position.z > hole.position.z && z2 >= hz2)
299	{
300		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 67));
301		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 68));
302		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 69));
303		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 70));
304	}
305	else if
306		(b.position.x <= hole.position.x && x2 < hx2) &&
307		(b.position.y > hole.position.y && y2 >= hy2) &&
308		(b.position.z > hole.position.z && z2 < hz2)
309	{
310		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 71));
311		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 72));
312		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 73));
313		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 74));
314		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 75));
315	}
316	else if
317		(b.position.x <= hole.position.x && x2 < hx2) &&
318		(b.position.y > hole.position.y && y2 < hy2) &&
319		(b.position.z <= hole.position.z && z2 >= hz2)
320	{
321		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 76));
322		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 77));
323		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 78));
324	}
325	else if
326		(b.position.x <= hole.position.x && x2 < hx2) &&
327		(b.position.y > hole.position.y && y2 < hy2) &&
328		(b.position.z <= hole.position.z && z2 < hz2)
329	{
330		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 79));
331		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 80));
332		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 81));
333		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 82));
334		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 83));
335		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 84));
336		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 85));
337		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 86));
338	}
339	else if
340		(b.position.x <= hole.position.x && x2 < hx2) &&
341		(b.position.y > hole.position.y && y2 < hy2) &&
342		(b.position.z > hole.position.z && z2 >= hz2)
343	{
344		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 87));
345		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 88));
346		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 89));
347		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 90));
348		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 91));
349	}
350	else if
351		(b.position.x <= hole.position.x && x2 < hx2) &&
352		(b.position.y > hole.position.y && y2 < hy2) &&
353		(b.position.z > hole.position.z && z2 < hz2)
354	{
355		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 92));
356		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 93));
357		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 94));
358		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 95));
359		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 96));
360		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 97));
361		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 98));
362		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 99));
363		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 100));
364		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 101));
365	}
366	else if
367		(b.position.x > hole.position.x && x2 >= hx2) &&
368		(b.position.y <= hole.position.y && y2 >= hy2) &&
369		(b.position.z <= hole.position.z && z2 >= hz2)
370	{
371		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 102));
372	}
373	else if
374		(b.position.x > hole.position.x && x2 >= hx2) &&
375		(b.position.y <= hole.position.y && y2 >= hy2) &&
376		(b.position.z <= hole.position.z && z2 < hz2)
377	{
378		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 103));
379		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 104));
380	}
381	else if
382		(b.position.x > hole.position.x && x2 >= hx2) &&
383		(b.position.y <= hole.position.y && y2 >= hy2) &&
384		(b.position.z > hole.position.z && z2 >= hz2)
385	{
386		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 105));
387		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 106));
388	}
389	else if
390		(b.position.x > hole.position.x && x2 >= hx2) &&
391		(b.position.y <= hole.position.y && y2 >= hy2) &&
392		(b.position.z > hole.position.z && z2 < hz2)
393	{
394		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 107));
395		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 108));
396		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 109));
397	}
398	else if
399		(b.position.x > hole.position.x && x2 >= hx2) &&
400		(b.position.y <= hole.position.y && y2 < hy2) &&
401		(b.position.z <= hole.position.z && z2 >= hz2)
402	{
403		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 110));
404		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 111));
405	}
406	else if
407		(b.position.x > hole.position.x && x2 >= hx2) &&
408		(b.position.y <= hole.position.y && y2 < hy2) &&
409		(b.position.z <= hole.position.z && z2 < hz2)
410	{
411		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 112));
412		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 113));
413		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 114));
414		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 115));
415	}
416	else if
417		(b.position.x > hole.position.x && x2 >= hx2) &&
418		(b.position.y <= hole.position.y && y2 < hy2) &&
419		(b.position.z > hole.position.z && z2 >= hz2)
420	{
421		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 116));
422		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 117));
423		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 118));
424		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 119));
425	}
426	else if
427		(b.position.x > hole.position.x && x2 >= hx2) &&
428		(b.position.y <= hole.position.y && y2 < hy2) &&
429		(b.position.z > hole.position.z && z2 < hz2)
430	{
431		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 120));
432		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 121));
433		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 122));
434		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 123));
435		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 124));
436	}
437	else if
438		(b.position.x > hole.position.x && x2 >= hx2) &&
439		(b.position.y > hole.position.y && y2 >= hy2) &&
440		(b.position.z <= hole.position.z && z2 >= hz2)
441	{
442		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 125));
443		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 126));
444	}
445	else if
446		(b.position.x > hole.position.x && x2 >= hx2) &&
447		(b.position.y > hole.position.y && y2 >= hy2) &&
448		(b.position.z <= hole.position.z && z2 < hz2)
449	{
450		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 127));
451		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 128));
452		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 129));
453		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 130));
454	}
455	else if
456		(b.position.x > hole.position.x && x2 >= hx2) &&
457		(b.position.y > hole.position.y && y2 >= hy2) &&
458		(b.position.z > hole.position.z && z2 >= hz2)
459	{
460		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 131));
461		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 132));
462		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 133));
463	}
464	else if
465		(b.position.x > hole.position.x && x2 >= hx2) &&
466		(b.position.y > hole.position.y && y2 >= hy2) &&
467		(b.position.z > hole.position.z && z2 < hz2)
468	{
469		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 134));
470		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 135));
471		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 136));
472		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 137));
473		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 138));
474	}
475	else if
476		(b.position.x > hole.position.x && x2 >= hx2) &&
477		(b.position.y > hole.position.y && y2 < hy2) &&
478		(b.position.z <= hole.position.z && z2 >= hz2)
479	{
480		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 139));
481		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 140));
482		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 141));
483	}
484	else if
485		(b.position.x > hole.position.x && x2 >= hx2) &&
486		(b.position.y > hole.position.y && y2 < hy2) &&
487		(b.position.z <= hole.position.z && z2 < hz2)
488	{
489		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 142));
490		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 143));
491		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 144));
492		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 145));
493		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 146));
494	}
495	else if
496		(b.position.x > hole.position.x && x2 >= hx2) &&
497		(b.position.y > hole.position.y && y2 < hy2) &&
498		(b.position.z > hole.position.z && z2 >= hz2)
499	{
500		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 147));
501		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 148));
502		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 149));
503		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 150));
504		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 151));
505	}
506	else if
507		(b.position.x > hole.position.x && x2 >= hx2) &&
508		(b.position.y > hole.position.y && y2 < hy2) &&
509		(b.position.z > hole.position.z && z2 < hz2)
510	{
511		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 152));
512		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 153));
513		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 154));
514		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 155));
515		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 156));
516		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 157));
517		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 158));
518	}
519	else if
520		(b.position.x > hole.position.x && x2 < hx2) &&
521		(b.position.y <= hole.position.y && y2 >= hy2) &&
522		(b.position.z <= hole.position.z && z2 >= hz2)
523	{
524		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 159));
525		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 160));
526	}
527	else if
528		(b.position.x > hole.position.x && x2 < hx2) &&
529		(b.position.y <= hole.position.y && y2 >= hy2) &&
530		(b.position.z <= hole.position.z && z2 < hz2)
531	{
532		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 161));
533		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 162));
534		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 163));
535	}
536	else if
537		(b.position.x > hole.position.x && x2 < hx2) &&
538		(b.position.y <= hole.position.y && y2 >= hy2) &&
539		(b.position.z > hole.position.z && z2 >= hz2)
540	{
541		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 164));
542		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 165));
543		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 166));
544	}
545	else if
546		(b.position.x > hole.position.x && x2 < hx2) &&
547		(b.position.y <= hole.position.y && y2 >= hy2) &&
548		(b.position.z > hole.position.z && z2 < hz2)
549	{
550		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 167));
551		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 168));
552		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 169));
553		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 170));
554	}
555	else if
556		(b.position.x > hole.position.x && x2 < hx2) &&
557		(b.position.y <= hole.position.y && y2 < hy2) &&
558		(b.position.z <= hole.position.z && z2 >= hz2)
559	{
560		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 171));
561		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 172));
562		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 173));
563	}
564	else if
565		(b.position.x > hole.position.x && x2 < hx2) &&
566		(b.position.y <= hole.position.y && y2 < hy2) &&
567		(b.position.z <= hole.position.z && z2 < hz2)
568	{
569		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 174));
570		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 175));
571		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 176));
572		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 177));
573		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 178));
574		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 179));
575		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 180));
576		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 181));
577	}
578	else if
579		(b.position.x > hole.position.x && x2 < hx2) &&
580		(b.position.y <= hole.position.y && y2 < hy2) &&
581		(b.position.z > hole.position.z && z2 >= hz2)
582	{
583		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 182));
584		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 183));
585		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 184));
586		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 185));
587		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 186));
588	}
589	else if
590		(b.position.x > hole.position.x && x2 < hx2) &&
591		(b.position.y <= hole.position.y && y2 < hy2) &&
592		(b.position.z > hole.position.z && z2 < hz2)
593	{
594		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 187));
595		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 188));
596		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 189));
597		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 190));
598		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 191));
599		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 192));
600		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 193));
601		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 194));
602		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 195));
603		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 196));
604	}
605	else if
606		(b.position.x > hole.position.x && x2 < hx2) &&
607		(b.position.y > hole.position.y && y2 >= hy2) &&
608		(b.position.z <= hole.position.z && z2 >= hz2)
609	{
610		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 197));
611		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 198));
612		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 199));
613	}
614	else if
615		(b.position.x > hole.position.x && x2 < hx2) &&
616		(b.position.y > hole.position.y && y2 >= hy2) &&
617		(b.position.z <= hole.position.z && z2 < hz2)
618	{
619		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 200));
620		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 201));
621		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 202));
622		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 203));
623		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 204));
624		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 205));
625	}
626	else if
627		(b.position.x > hole.position.x && x2 < hx2) &&
628		(b.position.y > hole.position.y && y2 >= hy2) &&
629		(b.position.z > hole.position.z && z2 >= hz2)
630	{
631		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 206));
632		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 207));
633		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 208));
634		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 209));
635		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 210));
636	}
637	else if
638		(b.position.x > hole.position.x && x2 < hx2) &&
639		(b.position.y > hole.position.y && y2 >= hy2) &&
640		(b.position.z > hole.position.z && z2 < hz2)
641	{
642		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 211));
643		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 212));
644		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 213));
645		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 214));
646		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 215));
647		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 216));
648		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 217));
649	}
650	else if
651		(b.position.x > hole.position.x && x2 < hx2) &&
652		(b.position.y > hole.position.y && y2 < hy2) &&
653		(b.position.z <= hole.position.z && z2 >= hz2)
654	{
655		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 218));
656		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 219));
657		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 220));
658		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 221));
659	}
660	else if
661		(b.position.x > hole.position.x && x2 < hx2) &&
662		(b.position.y > hole.position.y && y2 < hy2) &&
663		(b.position.z <= hole.position.z && z2 < hz2)
664	{
665		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 222));
666		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 223));
667		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 224));
668		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 225));
669		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 226));
670		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 227));
671		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 228));
672		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 229));
673		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 230));
674		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 231));
675	}
676	else if
677		(b.position.x > hole.position.x && x2 < hx2) &&
678		(b.position.y > hole.position.y && y2 < hy2) &&
679		(b.position.z > hole.position.z && z2 >= hz2)
680	{
681		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 232));
682		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 233));
683		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 234));
684		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 235));
685		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 236));
686		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 237));
687		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 238));
688	}
689	else if
690		(b.position.x > hole.position.x && x2 < hx2) &&
691		(b.position.y > hole.position.y && y2 < hy2) &&
692		(b.position.z > hole.position.z && z2 < hz2)
693	{
694		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 239));
695		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,b.position.x-hole.position.x,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 240));
696		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,hy2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 241));
697		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,hz2-hole.position.z, *next_hole_id, 242));
698		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,y2-hole.position.y,b.position.z-hole.position.z, *next_hole_id, 243));
699		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,hole.position.z,hx2-hole.position.x,b.position.y-hole.position.y,z2-hole.position.z, *next_hole_id, 244));
700		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,hy2-hole.position.y,hz2-z2, *next_hole_id, 245));
701		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,hole.position.y,z2,hx2-hole.position.x,y2-hole.position.y,hz2-z2, *next_hole_id, 246));
702		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,hz2-hole.position.z, *next_hole_id, 247));
703		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(hole.position.x,y2,hole.position.z,hx2-hole.position.x,hy2-y2,z2-hole.position.z, *next_hole_id, 248));
704		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,hz2-hole.position.z, *next_hole_id, 249));
705		*next_hole_id += 1; new_holes.push(Box3D::from_xyz_whl(x2,hole.position.y,hole.position.z,hx2-x2,hy2-hole.position.y,z2-hole.position.z, *next_hole_id, 250));
706	}
707
708	for new_hole in new_holes {
709		holes.insert(new_hole);
710	}
711}
712
713fn update_holes(b: &mut Box3D, holes: &mut HashSetFnv<Box3D>, mut next_hole_id: usize)
714-> usize
715{
716	// Cut holes
717	let mut new_holes = HashSetFnv::<Box3D>::default();
718
719	for hole in holes.iter() {
720		// If the Current Box3D overlaps with a hole, we break the hole into new holes
721		if b.intersects(hole) {
722			cut(b, hole, &mut new_holes, &mut next_hole_id);
723		} else if !hole.is_covered_among(&new_holes) {
724			new_holes.insert(*hole);
725		}
726	}
727
728	*holes = new_holes;
729
730	next_hole_id
731}
732
733fn get_new_w(hole: &Box3D, b: &Box3D) -> u64 {
734	hole.position.x + b.size.x
735}
736fn get_new_h(hole: &Box3D, b: &Box3D) -> u64 {
737	hole.position.y + b.size.y
738}
739fn get_new_l(hole: &Box3D, b: &Box3D) -> u64 {
740	hole.position.z + b.size.z
741}
742
743fn is_better_hole(b: &Box3D, hole: &Box3D, best_hole: Option<Box3D>, min_w: u64, min_h: u64, min_l: u64, minimize: Minimize) -> bool
744{
745	if !b.fits_in(hole) { return false; } // Box3D fits in the hole
746
747	let Some(best_hole) = best_hole else { return true; };
748
749	let hole_perfect = b.size.x == hole.size.x && b.size.y == hole.size.y && b.size.z == hole.size.z;
750	let best_hole_perfect = b.size.x == best_hole.size.x && b.size.y == best_hole.size.y && b.size.z == best_hole.size.z;
751
752	// Best hole is a perfect fit ...
753	if best_hole_perfect && !hole_perfect { return false; }
754
755	// Hole is a perfect fit !
756	if hole_perfect && !best_hole_perfect { return true; }
757
758	let current_w = if minimize.0 { get_new_w(hole, b) } else { 0 };
759	let current_h = if minimize.1 { get_new_h(hole, b) } else { 0 };
760	let current_l = if minimize.2 { get_new_l(hole, b) } else { 0 };
761
762	match minimize {
763		// Minimize Width
764		(true, false, false) => {
765			(current_w, hole.position.x, hole.position.y, hole.position.z, hole.size.x, hole.size.y, hole.size.z, hole.id) <
766			(min_w, best_hole.position.x, best_hole.position.y, best_hole.position.z, best_hole.size.x, best_hole.size.y, best_hole.size.z, best_hole.id)
767		}
768		// Minimize Height
769		(false, true, false) => {
770			(current_h, hole.position.y, hole.position.x, hole.position.z, hole.size.y, hole.size.x, hole.size.z, hole.id) <
771			(min_h, best_hole.position.y, best_hole.position.x, best_hole.position.z, best_hole.size.y, best_hole.size.x, best_hole.size.z, best_hole.id)
772		}
773		// Minimize Length
774		(false, false, true) => {
775			(current_l, hole.position.z, hole.position.x, hole.position.y, hole.size.z, hole.size.x, hole.size.y, hole.id) <
776			(min_l, best_hole.position.z, best_hole.position.x, best_hole.position.y, best_hole.size.z, best_hole.size.x, best_hole.size.y, best_hole.id)
777		}
778		// Minimize Width & Height
779		(true, true, false) => {
780			(current_w.max(current_h), hole.position.x.max(hole.position.y), hole.position.z, hole.size.x.max(hole.size.y), hole.size.z, hole.id) <
781			(min_w.max(min_h), best_hole.position.x.max(best_hole.position.y), best_hole.position.z, best_hole.size.x.max(best_hole.size.y), best_hole.size.z, best_hole.id)
782		}
783		// Minimize Width & Length
784		(true, false, true) => {
785			(current_w.max(current_l), hole.position.x.max(hole.position.z), hole.position.y, hole.size.x.max(hole.size.z), hole.size.y, hole.id) <
786			(min_w.max(min_l), best_hole.position.x.max(best_hole.position.z), best_hole.position.y, best_hole.size.x.max(best_hole.size.z), best_hole.size.y, best_hole.id)
787		}
788		// Minimize Height & Length
789		(false, true, true) => {
790			(current_h.max(current_l), hole.position.y.max(hole.position.z), hole.position.x, hole.size.y.max(hole.size.z), hole.size.x, hole.id) <
791			(min_h.max(min_l), best_hole.position.y.max(best_hole.position.z), best_hole.position.x, best_hole.size.y.max(best_hole.size.z), best_hole.size.x, best_hole.id)
792		}
793		// Minimize all three
794		(true, true, true) => {
795			(current_w.max(current_h).max(current_l), hole.position.x.max(hole.position.y).max(hole.position.z), hole.size.x.max(hole.size.y).max(hole.size.z), hole.id) <
796			(min_w.max(min_h).max(min_l), best_hole.position.x.max(best_hole.position.y).max(best_hole.position.z), best_hole.size.x.max(best_hole.size.y).max(best_hole.size.z), best_hole.id)
797		}
798		// No minimization, use a default Bottom-Left-Front heuristic
799		(false, false, false) => {
800			(hole.position.y, hole.position.x, hole.position.z, hole.id) <
801			(best_hole.position.y, best_hole.position.x, best_hole.position.z, best_hole.id)
802		}
803	}
804}
805
806fn get_best_hole(b: &Box3D, holes: &mut HashSetFnv<Box3D>, do_rotations: bool, minimize: Minimize) -> (Box3D, Option<Box3D>)
807{
808	let mut new_box = *b;
809	let mut best_hole: Option<Box3D> = None;
810
811	let mut min_w = u64::MAX;
812	let mut min_h = u64::MAX;
813	let mut min_l = u64::MAX;
814
815	let rotations_to_check = if do_rotations { b.get_rotations() } else { vec![*b] };
816
817	for hole in holes.iter() {
818		for rotation in &rotations_to_check {
819			if !rotation.fits_in(hole) {
820				continue;
821			}
822
823			if is_better_hole(rotation, hole, best_hole, min_w, min_h, min_l, minimize) {
824				new_box = *rotation;
825				min_w = get_new_w(hole, rotation);
826				min_h = get_new_h(hole, rotation);
827				min_l = get_new_l(hole, rotation);
828				best_hole = Some(*hole);
829			}
830		}
831	}
832
833	(new_box, best_hole)
834}
835
836/**
837## Example
838```
839let mut my_instance = PackerInstance::new(
840	&mut my_boxes, // Our boxes
841	Vector3D::<u64>::new(500, 0, 500), // Our container size
842	true, // Allow rotations
843	(false, true, false), // Minimize height only
844	&Sorting::descending_volume // Our initial sorting heuristic
845);
846```*/
847#[derive(Default, Debug, Clone)]
848pub struct PackerInstance {
849	pub do_rotations: bool,
850	pub minimize: Minimize,
851
852	container_size: Vector3D::<u64>,
853	boxes: Vec<Box3D>,
854	holes: HashSetFnv<Box3D>,
855	next_box_id: usize,
856	next_hole_id: usize,
857}
858
859impl PackerInstance {
860	pub fn container_size(&self) -> Vector3D<u64> {
861		self.container_size
862	}
863
864	pub fn boxes(&self) -> &Vec<Box3D> {
865		&self.boxes
866	}
867
868	pub fn holes(&self) -> &HashSetFnv<Box3D> {
869		&self.holes
870	}
871
872	pub fn finished(&self) -> bool {
873		self.next_box_id >= self.boxes.len()
874	}
875
876	pub fn next_box_id(&self) -> usize {
877		self.next_box_id
878	}
879
880	pub fn next_hole_id(&self) -> usize {
881		self.next_hole_id
882	}
883
884	/// Setup the packer
885	pub fn new(boxes: &[Box3D], container_size: Vector3D::<u64>, do_rotations: bool, minimize: Minimize, sorting_func: &dyn Fn(&Box3D,&Box3D) -> Ordering)
886	-> PackerInstance
887	{
888		let mut boxes: Vec<Box3D> = boxes.to_owned();
889		boxes.sort_by(sorting_func);
890
891		let mut holes = HashSetFnv::<Box3D>::default();
892		holes.insert(Box3D::from_xyz_whl(0, 0, 0,
893			if minimize.0 {u64::MAX} else {container_size.x},
894			if minimize.1 {u64::MAX} else {container_size.y},
895			if minimize.2 {u64::MAX} else {container_size.z},
896			0,
897			0
898		));
899
900		PackerInstance {
901			container_size,
902			do_rotations,
903			minimize,
904			boxes,
905			holes,
906			next_box_id: 0,
907			next_hole_id: 1
908		}
909	}
910
911	/// Do next packing iteration
912	pub fn pack_next(&mut self) -> Result<(), String>
913	{
914		if self.next_box_id >= self.boxes.len() {
915			return Err("No more boxes to pack".into());
916		}
917
918		let b = &mut self.boxes[self.next_box_id];
919		if b.size.x == 0 || b.size.y == 0 || b.size.z == 0
920		{
921			self.next_box_id += 1;
922			return Err(format!("Box {} has invalid size", b.id));
923		}
924
925		let (best_box, best_hole) = get_best_hole(b, &mut self.holes, self.do_rotations, self.minimize);
926		if best_hole.is_none()
927		{
928			self.next_box_id += 1;
929			return Err(format!("Could not find hole for Box {}", b.id));
930		}
931		let best_hole = best_hole.unwrap();
932
933		// Place and rotate (switch sizes) box
934		b.size = best_box.size;
935		b.position = best_hole.position;
936
937		// Update container size
938		if self.minimize.0 {
939			self.container_size.x = self.container_size.x.max(get_new_w(&best_hole, b));
940		};
941		if self.minimize.1 {
942			self.container_size.y = self.container_size.y.max(get_new_h(&best_hole, b));
943		};
944		if self.minimize.2 {
945			self.container_size.z = self.container_size.z.max(get_new_l(&best_hole, b));
946		};
947
948		// Update the holes
949		self.next_hole_id = update_holes(b, &mut self.holes, self.next_hole_id);
950
951		// Change for next box id
952		self.next_box_id += 1;
953
954		Ok(())
955	}
956}