1use super::primitives::{Point2, Point3};
11
12#[inline]
18pub fn distance_sq_2d(a: Point2, b: Point2) -> f64 {
19 let dx = a.x - b.x;
20 let dy = a.y - b.y;
21 dx * dx + dy * dy
22}
23
24#[inline]
26pub fn distance_2d(a: Point2, b: Point2) -> f64 {
27 distance_sq_2d(a, b).sqrt()
28}
29
30#[inline]
32pub fn point_segment_distance_sq_2d(p: Point2, a: Point2, b: Point2) -> f64 {
33 let abx = b.x - a.x;
34 let aby = b.y - a.y;
35 let apx = p.x - a.x;
36 let apy = p.y - a.y;
37 let ab_sq = abx * abx + aby * aby;
38 if ab_sq == 0.0 {
39 return apx * apx + apy * apy;
41 }
42 let t = (apx * abx + apy * aby) / ab_sq;
43 let t = t.clamp(0.0, 1.0);
44 let cx = a.x + t * abx;
45 let cy = a.y + t * aby;
46 let dx = p.x - cx;
47 let dy = p.y - cy;
48 dx * dx + dy * dy
49}
50
51#[inline]
53pub fn point_segment_distance_2d(p: Point2, a: Point2, b: Point2) -> f64 {
54 point_segment_distance_sq_2d(p, a, b).sqrt()
55}
56
57#[inline]
59pub fn point_line_distance_sq_2d(p: Point2, a: Point2, b: Point2) -> f64 {
60 let abx = b.x - a.x;
61 let aby = b.y - a.y;
62 let ab_sq = abx * abx + aby * aby;
63 if ab_sq == 0.0 {
64 let dx = p.x - a.x;
65 let dy = p.y - a.y;
66 return dx * dx + dy * dy;
67 }
68 let cross = (b.x - a.x) * (p.y - a.y) - (b.y - a.y) * (p.x - a.x);
69 cross * cross / ab_sq
70}
71
72#[inline]
78pub fn distance_sq_3d(a: Point3, b: Point3) -> f64 {
79 let dx = a.x - b.x;
80 let dy = a.y - b.y;
81 let dz = a.z - b.z;
82 dx * dx + dy * dy + dz * dz
83}
84
85#[inline]
87pub fn distance_3d(a: Point3, b: Point3) -> f64 {
88 distance_sq_3d(a, b).sqrt()
89}
90
91#[inline]
93pub fn point_segment_distance_sq_3d(p: Point3, a: Point3, b: Point3) -> f64 {
94 let abx = b.x - a.x;
95 let aby = b.y - a.y;
96 let abz = b.z - a.z;
97 let apx = p.x - a.x;
98 let apy = p.y - a.y;
99 let apz = p.z - a.z;
100 let ab_sq = abx * abx + aby * aby + abz * abz;
101 if ab_sq == 0.0 {
102 return apx * apx + apy * apy + apz * apz;
103 }
104 let t = (apx * abx + apy * aby + apz * abz) / ab_sq;
105 let t = t.clamp(0.0, 1.0);
106 let cx = a.x + t * abx;
107 let cy = a.y + t * aby;
108 let cz = a.z + t * abz;
109 let dx = p.x - cx;
110 let dy = p.y - cy;
111 let dz = p.z - cz;
112 dx * dx + dy * dy + dz * dz
113}
114
115pub fn point_triangle_distance_sq_3d(p: Point3, a: Point3, b: Point3, c: Point3) -> f64 {
121 let ab = Point3::new(b.x - a.x, b.y - a.y, b.z - a.z);
122 let ac = Point3::new(c.x - a.x, c.y - a.y, c.z - a.z);
123 let ap = Point3::new(p.x - a.x, p.y - a.y, p.z - a.z);
124
125 let d1 = dot_3d(ab, ap);
126 let d2 = dot_3d(ac, ap);
127 if d1 <= 0.0 && d2 <= 0.0 {
128 return dot_3d(ap, ap);
130 }
131
132 let bp = Point3::new(p.x - b.x, p.y - b.y, p.z - b.z);
133 let d3 = dot_3d(ab, bp);
134 let d4 = dot_3d(ac, bp);
135 if d3 >= 0.0 && d4 <= d3 {
136 return dot_3d(bp, bp);
138 }
139
140 let cp = Point3::new(p.x - c.x, p.y - c.y, p.z - c.z);
141 let d5 = dot_3d(ab, cp);
142 let d6 = dot_3d(ac, cp);
143 if d6 >= 0.0 && d5 <= d6 {
144 return dot_3d(cp, cp);
146 }
147
148 let vc = d1 * d4 - d3 * d2;
150 if vc <= 0.0 && d1 >= 0.0 && d3 <= 0.0 {
151 let t = d1 / (d1 - d3);
152 let cx = a.x + t * ab.x;
153 let cy = a.y + t * ab.y;
154 let cz = a.z + t * ab.z;
155 let dx = p.x - cx;
156 let dy = p.y - cy;
157 let dz = p.z - cz;
158 return dx * dx + dy * dy + dz * dz;
159 }
160
161 let vb = d5 * d2 - d1 * d6;
163 if vb <= 0.0 && d2 >= 0.0 && d6 <= 0.0 {
164 let t = d2 / (d2 - d6);
165 let cx = a.x + t * ac.x;
166 let cy = a.y + t * ac.y;
167 let cz = a.z + t * ac.z;
168 let dx = p.x - cx;
169 let dy = p.y - cy;
170 let dz = p.z - cz;
171 return dx * dx + dy * dy + dz * dz;
172 }
173
174 let va = d3 * d6 - d5 * d4;
176 if va <= 0.0 && (d4 - d3) >= 0.0 && (d5 - d6) >= 0.0 {
177 let t = (d4 - d3) / ((d4 - d3) + (d5 - d6));
178 let bcx = c.x - b.x;
179 let bcy = c.y - b.y;
180 let bcz = c.z - b.z;
181 let cx = b.x + t * bcx;
182 let cy = b.y + t * bcy;
183 let cz = b.z + t * bcz;
184 let dx = p.x - cx;
185 let dy = p.y - cy;
186 let dz = p.z - cz;
187 return dx * dx + dy * dy + dz * dz;
188 }
189
190 let denom = 1.0 / (va + vb + vc);
192 let v = vb * denom;
193 let w = vc * denom;
194 let cx = a.x + ab.x * v + ac.x * w;
195 let cy = a.y + ab.y * v + ac.y * w;
196 let cz = a.z + ab.z * v + ac.z * w;
197 let dx = p.x - cx;
198 let dy = p.y - cy;
199 let dz = p.z - cz;
200 dx * dx + dy * dy + dz * dz
201}
202
203#[inline]
204fn dot_3d(a: Point3, b: Point3) -> f64 {
205 a.x * b.x + a.y * b.y + a.z * b.z
206}
207
208#[derive(Debug, Clone, Copy, PartialEq, Eq)]
214pub enum SegmentIntersection2d {
215 Disjoint,
217 Point,
219 Overlap,
221 Touching,
223}
224
225pub fn segment_segment_intersect_2d(
230 a: Point2,
231 b: Point2,
232 c: Point2,
233 d: Point2,
234) -> SegmentIntersection2d {
235 use super::primitives::orientation_2;
236
237 let o1 = orientation_2(a, b, c);
238 let o2 = orientation_2(a, b, d);
239 let o3 = orientation_2(c, d, a);
240 let o4 = orientation_2(c, d, b);
241
242 if o1 != o2 && o3 != o4 {
244 return SegmentIntersection2d::Point;
245 }
246
247 if o1 == super::primitives::Orientation::Collinear
249 && o2 == super::primitives::Orientation::Collinear
250 {
251 let (a_t, b_t) = if (b.x - a.x).abs() >= (b.y - a.y).abs() {
254 (a.x, b.x)
255 } else {
256 (a.y, b.y)
257 };
258 let (c_t, d_t) = if (b.x - a.x).abs() >= (b.y - a.y).abs() {
259 (c.x, d.x)
260 } else {
261 (c.y, d.y)
262 };
263
264 let (lo_ab, hi_ab) = (a_t.min(b_t), a_t.max(b_t));
265 let (lo_cd, hi_cd) = (c_t.min(d_t), c_t.max(d_t));
266
267 if hi_ab < lo_cd || hi_cd < lo_ab {
268 return SegmentIntersection2d::Disjoint;
269 }
270 if hi_ab == lo_cd || hi_cd == lo_ab {
272 return SegmentIntersection2d::Touching;
273 }
274 return SegmentIntersection2d::Overlap;
275 }
276
277 if o1 == super::primitives::Orientation::Collinear && on_segment_2d(a, b, c) {
279 return SegmentIntersection2d::Touching;
280 }
281 if o2 == super::primitives::Orientation::Collinear && on_segment_2d(a, b, d) {
282 return SegmentIntersection2d::Touching;
283 }
284 if o3 == super::primitives::Orientation::Collinear && on_segment_2d(c, d, a) {
285 return SegmentIntersection2d::Touching;
286 }
287 if o4 == super::primitives::Orientation::Collinear && on_segment_2d(c, d, b) {
288 return SegmentIntersection2d::Touching;
289 }
290
291 SegmentIntersection2d::Disjoint
292}
293
294#[inline]
296fn on_segment_2d(a: Point2, b: Point2, p: Point2) -> bool {
297 p.x >= a.x.min(b.x) && p.x <= a.x.max(b.x) && p.y >= a.y.min(b.y) && p.y <= a.y.max(b.y)
298}
299
300#[derive(Debug, Clone, Copy, PartialEq)]
306pub struct RayTriangleHit {
307 pub t: f64,
309 pub u: f64,
311 pub v: f64,
313}
314
315#[derive(Debug, Clone, Copy, PartialEq)]
317pub enum RayTriangleResult {
318 Hit(RayTriangleHit),
320 Miss,
322 Parallel,
324 DegenerateTriangle,
326}
327
328pub fn ray_triangle_intersect_3d(
336 origin: Point3,
337 direction: Point3,
338 a: Point3,
339 b: Point3,
340 c: Point3,
341) -> RayTriangleResult {
342 let edge1 = Point3::new(b.x - a.x, b.y - a.y, b.z - a.z);
343 let edge2 = Point3::new(c.x - a.x, c.y - a.y, c.z - a.z);
344
345 let h = cross_3d(direction, edge2);
346 let det = dot_3d(edge1, h);
347
348 if det.abs() < f64::EPSILON {
350 let edge1_sq = dot_3d(edge1, edge1);
352 let edge2_sq = dot_3d(edge2, edge2);
353 if edge1_sq == 0.0 || edge2_sq == 0.0 {
354 return RayTriangleResult::DegenerateTriangle;
355 }
356 return RayTriangleResult::Parallel;
357 }
358
359 let inv_det = 1.0 / det;
360 let s = Point3::new(origin.x - a.x, origin.y - a.y, origin.z - a.z);
361 let u = inv_det * dot_3d(s, h);
362
363 if u < 0.0 || u > 1.0 {
364 return RayTriangleResult::Miss;
365 }
366
367 let q = cross_3d(s, edge1);
368 let v = inv_det * dot_3d(direction, q);
369
370 if v < 0.0 || u + v > 1.0 {
371 return RayTriangleResult::Miss;
372 }
373
374 let t = inv_det * dot_3d(edge2, q);
375 RayTriangleResult::Hit(RayTriangleHit { t, u, v })
376}
377
378#[inline]
379fn cross_3d(a: Point3, b: Point3) -> Point3 {
380 Point3::new(
381 a.y * b.z - a.z * b.y,
382 a.z * b.x - a.x * b.z,
383 a.x * b.y - a.y * b.x,
384 )
385}
386
387#[derive(Debug, Clone, Copy, PartialEq)]
393pub struct Aabb {
394 pub min: Point3,
395 pub max: Point3,
396}
397
398impl Aabb {
399 #[inline]
400 pub fn new(min: Point3, max: Point3) -> Self {
401 Self { min, max }
402 }
403
404 #[inline]
405 pub fn overlaps(&self, other: &Aabb) -> bool {
406 self.min.x <= other.max.x
407 && self.max.x >= other.min.x
408 && self.min.y <= other.max.y
409 && self.max.y >= other.min.y
410 && self.min.z <= other.max.z
411 && self.max.z >= other.min.z
412 }
413
414 #[inline]
415 pub fn contains_point(&self, p: Point3) -> bool {
416 p.x >= self.min.x
417 && p.x <= self.max.x
418 && p.y >= self.min.y
419 && p.y <= self.max.y
420 && p.z >= self.min.z
421 && p.z <= self.max.z
422 }
423
424 #[inline]
426 pub fn distance_sq_to_point(&self, p: Point3) -> f64 {
427 let dx = (self.min.x - p.x).max(0.0).max(p.x - self.max.x);
428 let dy = (self.min.y - p.y).max(0.0).max(p.y - self.max.y);
429 let dz = (self.min.z - p.z).max(0.0).max(p.z - self.max.z);
430 dx * dx + dy * dy + dz * dz
431 }
432
433 #[inline]
435 pub fn center(&self) -> Point3 {
436 Point3::new(
437 0.5 * (self.min.x + self.max.x),
438 0.5 * (self.min.y + self.max.y),
439 0.5 * (self.min.z + self.max.z),
440 )
441 }
442
443 #[inline]
445 pub fn surface_area(&self) -> f64 {
446 let dx = self.max.x - self.min.x;
447 let dy = self.max.y - self.min.y;
448 let dz = self.max.z - self.min.z;
449 2.0 * (dx * dy + dy * dz + dz * dx)
450 }
451
452 #[inline]
454 pub fn union(&self, other: &Aabb) -> Aabb {
455 Aabb::new(
456 Point3::new(
457 self.min.x.min(other.min.x),
458 self.min.y.min(other.min.y),
459 self.min.z.min(other.min.z),
460 ),
461 Point3::new(
462 self.max.x.max(other.max.x),
463 self.max.y.max(other.max.y),
464 self.max.z.max(other.max.z),
465 ),
466 )
467 }
468}
469
470#[cfg(test)]
475mod tests {
476 use super::*;
477
478 #[test]
481 fn distance_2d_basic() {
482 let a = Point2::new(0.0, 0.0);
483 let b = Point2::new(3.0, 4.0);
484 assert_eq!(distance_2d(a, b), 5.0);
485 assert_eq!(distance_sq_2d(a, b), 25.0);
486 }
487
488 #[test]
489 fn point_segment_distance_2d_interior() {
490 let p = Point2::new(0.5, 1.0);
491 let a = Point2::new(0.0, 0.0);
492 let b = Point2::new(1.0, 0.0);
493 assert!((point_segment_distance_2d(p, a, b) - 1.0).abs() < 1e-12);
494 }
495
496 #[test]
497 fn point_segment_distance_2d_endpoint() {
498 let p = Point2::new(2.0, 0.0);
499 let a = Point2::new(0.0, 0.0);
500 let b = Point2::new(1.0, 0.0);
501 assert!((point_segment_distance_2d(p, a, b) - 1.0).abs() < 1e-12);
502 }
503
504 #[test]
505 fn point_segment_distance_2d_degenerate() {
506 let p = Point2::new(1.0, 1.0);
507 let a = Point2::new(0.0, 0.0);
508 let b = Point2::new(0.0, 0.0); assert!((point_segment_distance_2d(p, a, b) - 2.0f64.sqrt()).abs() < 1e-12);
510 }
511
512 #[test]
513 fn point_line_distance_2d() {
514 let p = Point2::new(0.0, 1.0);
515 let a = Point2::new(-1.0, 0.0);
516 let b = Point2::new(1.0, 0.0);
517 assert!((point_line_distance_sq_2d(p, a, b) - 1.0).abs() < 1e-12);
518 }
519
520 #[test]
523 fn distance_3d_basic() {
524 let a = Point3::new(0.0, 0.0, 0.0);
525 let b = Point3::new(1.0, 2.0, 2.0);
526 assert!((distance_3d(a, b) - 3.0).abs() < 1e-12);
527 }
528
529 #[test]
530 fn point_segment_distance_3d() {
531 let p = Point3::new(0.5, 0.0, 1.0);
532 let a = Point3::new(0.0, 0.0, 0.0);
533 let b = Point3::new(1.0, 0.0, 0.0);
534 assert!((point_segment_distance_sq_3d(p, a, b) - 1.0).abs() < 1e-12);
535 }
536
537 #[test]
538 fn point_triangle_distance_3d_interior() {
539 let a = Point3::new(0.0, 0.0, 0.0);
541 let b = Point3::new(1.0, 0.0, 0.0);
542 let c = Point3::new(0.0, 1.0, 0.0);
543 let p = Point3::new(1.0 / 3.0, 1.0 / 3.0, 2.0);
544 assert!((point_triangle_distance_sq_3d(p, a, b, c) - 4.0).abs() < 1e-12);
545 }
546
547 #[test]
548 fn point_triangle_distance_3d_vertex() {
549 let a = Point3::new(0.0, 0.0, 0.0);
550 let b = Point3::new(1.0, 0.0, 0.0);
551 let c = Point3::new(0.0, 1.0, 0.0);
552 let p = Point3::new(-1.0, -1.0, 0.0);
553 let d = point_triangle_distance_sq_3d(p, a, b, c);
554 assert!((d - 2.0).abs() < 1e-12, "d={d}");
555 }
556
557 #[test]
560 fn segments_cross_properly() {
561 let a = Point2::new(0.0, 0.0);
562 let b = Point2::new(1.0, 1.0);
563 let c = Point2::new(0.0, 1.0);
564 let d = Point2::new(1.0, 0.0);
565 assert_eq!(
566 segment_segment_intersect_2d(a, b, c, d),
567 SegmentIntersection2d::Point
568 );
569 }
570
571 #[test]
572 fn segments_disjoint() {
573 let a = Point2::new(0.0, 0.0);
574 let b = Point2::new(1.0, 0.0);
575 let c = Point2::new(2.0, 0.0);
576 let d = Point2::new(3.0, 0.0);
577 assert_eq!(
578 segment_segment_intersect_2d(a, b, c, d),
579 SegmentIntersection2d::Disjoint
580 );
581 }
582
583 #[test]
584 fn segments_collinear_overlap() {
585 let a = Point2::new(0.0, 0.0);
586 let b = Point2::new(2.0, 0.0);
587 let c = Point2::new(1.0, 0.0);
588 let d = Point2::new(3.0, 0.0);
589 assert_eq!(
590 segment_segment_intersect_2d(a, b, c, d),
591 SegmentIntersection2d::Overlap
592 );
593 }
594
595 #[test]
596 fn segments_collinear_touching() {
597 let a = Point2::new(0.0, 0.0);
598 let b = Point2::new(1.0, 0.0);
599 let c = Point2::new(1.0, 0.0);
600 let d = Point2::new(2.0, 0.0);
601 assert_eq!(
602 segment_segment_intersect_2d(a, b, c, d),
603 SegmentIntersection2d::Touching
604 );
605 }
606
607 #[test]
608 fn segments_collinear_disjoint() {
609 let a = Point2::new(0.0, 0.0);
610 let b = Point2::new(1.0, 0.0);
611 let c = Point2::new(2.0, 0.0);
612 let d = Point2::new(3.0, 0.0);
613 assert_eq!(
614 segment_segment_intersect_2d(a, b, c, d),
615 SegmentIntersection2d::Disjoint
616 );
617 }
618
619 #[test]
620 fn segments_touching_at_endpoint() {
621 let a = Point2::new(0.0, 0.0);
624 let b = Point2::new(1.0, 0.0);
625 let c = Point2::new(1.0, 0.0);
626 let d = Point2::new(1.0, 1.0);
627 assert_eq!(
630 segment_segment_intersect_2d(a, b, c, d),
631 SegmentIntersection2d::Point
632 );
633 }
634
635 #[test]
638 fn ray_hits_triangle() {
639 let origin = Point3::new(0.0, 0.0, 1.0);
640 let dir = Point3::new(0.0, 0.0, -1.0);
641 let a = Point3::new(-1.0, -1.0, 0.0);
642 let b = Point3::new(1.0, -1.0, 0.0);
643 let c = Point3::new(0.0, 1.0, 0.0);
644 match ray_triangle_intersect_3d(origin, dir, a, b, c) {
645 RayTriangleResult::Hit(hit) => {
646 assert!((hit.t - 1.0).abs() < 1e-12);
647 assert!(hit.u >= 0.0 && hit.u <= 1.0);
648 assert!(hit.v >= 0.0 && hit.u + hit.v <= 1.0);
649 }
650 _ => panic!("expected hit"),
651 }
652 }
653
654 #[test]
655 fn ray_misses_triangle() {
656 let origin = Point3::new(5.0, 5.0, 1.0);
657 let dir = Point3::new(0.0, 0.0, -1.0);
658 let a = Point3::new(-1.0, -1.0, 0.0);
659 let b = Point3::new(1.0, -1.0, 0.0);
660 let c = Point3::new(0.0, 1.0, 0.0);
661 assert_eq!(
662 ray_triangle_intersect_3d(origin, dir, a, b, c),
663 RayTriangleResult::Miss
664 );
665 }
666
667 #[test]
668 fn ray_parallel_to_triangle() {
669 let origin = Point3::new(0.0, 0.0, 1.0);
670 let dir = Point3::new(1.0, 0.0, 0.0); let a = Point3::new(-1.0, -1.0, 0.0);
672 let b = Point3::new(1.0, -1.0, 0.0);
673 let c = Point3::new(0.0, 1.0, 0.0);
674 assert_eq!(
675 ray_triangle_intersect_3d(origin, dir, a, b, c),
676 RayTriangleResult::Parallel
677 );
678 }
679
680 #[test]
681 fn ray_hits_degenerate_triangle() {
682 let origin = Point3::new(0.0, 0.0, 1.0);
683 let dir = Point3::new(0.0, 0.0, -1.0);
684 let a = Point3::new(0.0, 0.0, 0.0);
685 let b = Point3::new(0.0, 0.0, 0.0); let c = Point3::new(1.0, 0.0, 0.0);
687 assert_eq!(
688 ray_triangle_intersect_3d(origin, dir, a, b, c),
689 RayTriangleResult::DegenerateTriangle
690 );
691 }
692
693 #[test]
696 fn aabb_overlaps() {
697 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 1.0, 1.0));
698 let b = Aabb::new(Point3::new(0.5, 0.5, 0.5), Point3::new(2.0, 2.0, 2.0));
699 assert!(a.overlaps(&b));
700 }
701
702 #[test]
703 fn aabb_disjoint() {
704 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 1.0, 1.0));
705 let b = Aabb::new(Point3::new(2.0, 2.0, 2.0), Point3::new(3.0, 3.0, 3.0));
706 assert!(!a.overlaps(&b));
707 }
708
709 #[test]
710 fn aabb_touching_overlaps() {
711 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 1.0, 1.0));
713 let b = Aabb::new(Point3::new(1.0, 0.0, 0.0), Point3::new(2.0, 1.0, 1.0));
714 assert!(a.overlaps(&b));
715 }
716
717 #[test]
718 fn aabb_contains_point() {
719 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 1.0, 1.0));
720 assert!(a.contains_point(Point3::new(0.5, 0.5, 0.5)));
721 assert!(!a.contains_point(Point3::new(1.5, 0.5, 0.5)));
722 }
723
724 #[test]
725 fn aabb_distance_sq_to_point_inside() {
726 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 1.0, 1.0));
727 assert_eq!(a.distance_sq_to_point(Point3::new(0.5, 0.5, 0.5)), 0.0);
728 }
729
730 #[test]
731 fn aabb_distance_sq_to_point_outside() {
732 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 1.0, 1.0));
733 let d = a.distance_sq_to_point(Point3::new(2.0, 0.5, 0.5));
734 assert!((d - 1.0).abs() < 1e-12);
735 }
736
737 #[test]
738 fn aabb_surface_area() {
739 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 2.0, 3.0));
740 assert!((a.surface_area() - 22.0).abs() < 1e-12);
742 }
743
744 #[test]
745 fn aabb_union() {
746 let a = Aabb::new(Point3::new(0.0, 0.0, 0.0), Point3::new(1.0, 1.0, 1.0));
747 let b = Aabb::new(Point3::new(0.5, 0.5, 0.5), Point3::new(2.0, 2.0, 2.0));
748 let u = a.union(&b);
749 assert_eq!(u.min, Point3::new(0.0, 0.0, 0.0));
750 assert_eq!(u.max, Point3::new(2.0, 2.0, 2.0));
751 }
752}