1use std::ops::{Add, Mul, Sub};
14
15#[derive(Debug, Clone, Copy, PartialEq)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
18pub struct Point2 {
19 pub x: f64,
20 pub y: f64,
21}
22
23impl Point2 {
24 #[inline]
26 pub fn new(x: f64, y: f64) -> Self {
27 Self { x, y }
28 }
29
30 pub const ORIGIN: Self = Self { x: 0.0, y: 0.0 };
32
33 #[inline]
38 pub fn distance_to(&self, other: &Self) -> f64 {
39 let dx = self.x - other.x;
40 let dy = self.y - other.y;
41 (dx * dx + dy * dy).sqrt()
42 }
43
44 #[inline]
46 pub fn distance_sq(&self, other: &Self) -> f64 {
47 let dx = self.x - other.x;
48 let dy = self.y - other.y;
49 dx * dx + dy * dy
50 }
51
52 #[inline]
54 pub fn to_tuple(self) -> (f64, f64) {
55 (self.x, self.y)
56 }
57
58 #[inline]
60 pub fn from_tuple(t: (f64, f64)) -> Self {
61 Self { x: t.0, y: t.1 }
62 }
63}
64
65impl From<(f64, f64)> for Point2 {
66 fn from(t: (f64, f64)) -> Self {
67 Self::from_tuple(t)
68 }
69}
70
71impl From<Point2> for (f64, f64) {
72 fn from(p: Point2) -> Self {
73 p.to_tuple()
74 }
75}
76
77impl Sub for Point2 {
78 type Output = Vector2;
79
80 fn sub(self, rhs: Self) -> Vector2 {
81 Vector2::new(self.x - rhs.x, self.y - rhs.y)
82 }
83}
84
85impl Add<Vector2> for Point2 {
86 type Output = Point2;
87
88 fn add(self, rhs: Vector2) -> Point2 {
89 Point2::new(self.x + rhs.x, self.y + rhs.y)
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq)]
95#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
96pub struct Vector2 {
97 pub x: f64,
98 pub y: f64,
99}
100
101impl Vector2 {
102 #[inline]
104 pub fn new(x: f64, y: f64) -> Self {
105 Self { x, y }
106 }
107
108 pub const ZERO: Self = Self { x: 0.0, y: 0.0 };
110
111 #[inline]
113 pub fn length(&self) -> f64 {
114 (self.x * self.x + self.y * self.y).sqrt()
115 }
116
117 #[inline]
119 pub fn length_sq(&self) -> f64 {
120 self.x * self.x + self.y * self.y
121 }
122
123 #[inline]
125 pub fn normalized(&self) -> Self {
126 let len = self.length();
127 if len < 1e-15 {
128 Self::ZERO
129 } else {
130 Self::new(self.x / len, self.y / len)
131 }
132 }
133
134 #[inline]
139 pub fn cross(&self, other: &Self) -> f64 {
140 self.x * other.y - self.y * other.x
141 }
142
143 #[inline]
145 pub fn dot(&self, other: &Self) -> f64 {
146 self.x * other.x + self.y * other.y
147 }
148
149 #[inline]
151 pub fn perp(&self) -> Self {
152 Self::new(-self.y, self.x)
153 }
154}
155
156impl Add for Vector2 {
157 type Output = Self;
158
159 fn add(self, rhs: Self) -> Self {
160 Self::new(self.x + rhs.x, self.y + rhs.y)
161 }
162}
163
164impl Sub for Vector2 {
165 type Output = Self;
166
167 fn sub(self, rhs: Self) -> Self {
168 Self::new(self.x - rhs.x, self.y - rhs.y)
169 }
170}
171
172impl Mul<f64> for Vector2 {
173 type Output = Self;
174
175 fn mul(self, rhs: f64) -> Self {
176 Self::new(self.x * rhs, self.y * rhs)
177 }
178}
179
180#[derive(Debug, Clone, Copy, PartialEq)]
182#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
183pub struct Segment2 {
184 pub start: Point2,
185 pub end: Point2,
186}
187
188impl Segment2 {
189 pub fn new(start: Point2, end: Point2) -> Self {
191 Self { start, end }
192 }
193
194 #[inline]
196 pub fn length(&self) -> f64 {
197 self.start.distance_to(&self.end)
198 }
199
200 #[inline]
202 pub fn length_sq(&self) -> f64 {
203 self.start.distance_sq(&self.end)
204 }
205
206 #[inline]
208 pub fn direction(&self) -> Vector2 {
209 self.end - self.start
210 }
211
212 #[inline]
214 pub fn midpoint(&self) -> Point2 {
215 Point2::new(
216 (self.start.x + self.end.x) * 0.5,
217 (self.start.y + self.end.y) * 0.5,
218 )
219 }
220}
221
222#[derive(Debug, Clone, Copy, PartialEq)]
227#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
228pub struct AABB2 {
229 pub min: Point2,
231 pub max: Point2,
233}
234
235impl AABB2 {
236 pub fn new(min_x: f64, min_y: f64, max_x: f64, max_y: f64) -> Self {
238 Self {
239 min: Point2::new(min_x, min_y),
240 max: Point2::new(max_x, max_y),
241 }
242 }
243
244 pub fn from_points(points: &[Point2]) -> Option<Self> {
251 let first = points.first()?;
252 let mut min_x = first.x;
253 let mut min_y = first.y;
254 let mut max_x = first.x;
255 let mut max_y = first.y;
256
257 for p in points.iter().skip(1) {
258 min_x = min_x.min(p.x);
259 min_y = min_y.min(p.y);
260 max_x = max_x.max(p.x);
261 max_y = max_y.max(p.y);
262 }
263
264 Some(Self::new(min_x, min_y, max_x, max_y))
265 }
266
267 #[inline]
269 pub fn width(&self) -> f64 {
270 self.max.x - self.min.x
271 }
272
273 #[inline]
275 pub fn height(&self) -> f64 {
276 self.max.y - self.min.y
277 }
278
279 #[inline]
281 pub fn area(&self) -> f64 {
282 self.width() * self.height()
283 }
284
285 #[inline]
287 pub fn center(&self) -> Point2 {
288 Point2::new(
289 (self.min.x + self.max.x) * 0.5,
290 (self.min.y + self.max.y) * 0.5,
291 )
292 }
293
294 #[inline]
296 pub fn contains_point(&self, p: &Point2) -> bool {
297 p.x >= self.min.x && p.x <= self.max.x && p.y >= self.min.y && p.y <= self.max.y
298 }
299
300 #[inline]
302 pub fn intersects(&self, other: &Self) -> bool {
303 self.min.x <= other.max.x
304 && self.max.x >= other.min.x
305 && self.min.y <= other.max.y
306 && self.max.y >= other.min.y
307 }
308
309 pub fn intersection(&self, other: &Self) -> Option<Self> {
311 if !self.intersects(other) {
312 return None;
313 }
314 Some(Self::new(
315 self.min.x.max(other.min.x),
316 self.min.y.max(other.min.y),
317 self.max.x.min(other.max.x),
318 self.max.y.min(other.max.y),
319 ))
320 }
321
322 pub fn union(&self, other: &Self) -> Self {
324 Self::new(
325 self.min.x.min(other.min.x),
326 self.min.y.min(other.min.y),
327 self.max.x.max(other.max.x),
328 self.max.y.max(other.max.y),
329 )
330 }
331
332 pub fn expand(&self, margin: f64) -> Self {
334 Self::new(
335 self.min.x - margin,
336 self.min.y - margin,
337 self.max.x + margin,
338 self.max.y + margin,
339 )
340 }
341}
342
343#[derive(Debug, Clone, Copy, PartialEq)]
347#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
348pub struct Point3 {
349 pub x: f64,
350 pub y: f64,
351 pub z: f64,
352}
353
354impl Point3 {
355 #[inline]
357 pub fn new(x: f64, y: f64, z: f64) -> Self {
358 Self { x, y, z }
359 }
360
361 pub const ORIGIN: Self = Self {
363 x: 0.0,
364 y: 0.0,
365 z: 0.0,
366 };
367
368 #[inline]
373 pub fn distance_to(&self, other: &Self) -> f64 {
374 self.distance_sq(other).sqrt()
375 }
376
377 #[inline]
379 pub fn distance_sq(&self, other: &Self) -> f64 {
380 let dx = self.x - other.x;
381 let dy = self.y - other.y;
382 let dz = self.z - other.z;
383 dx * dx + dy * dy + dz * dz
384 }
385
386 #[inline]
388 pub fn to_tuple(self) -> (f64, f64, f64) {
389 (self.x, self.y, self.z)
390 }
391
392 #[inline]
394 pub fn from_tuple(t: (f64, f64, f64)) -> Self {
395 Self {
396 x: t.0,
397 y: t.1,
398 z: t.2,
399 }
400 }
401
402 #[inline]
404 pub fn to_array(self) -> [f64; 3] {
405 [self.x, self.y, self.z]
406 }
407
408 #[inline]
410 pub fn from_array(a: [f64; 3]) -> Self {
411 Self {
412 x: a[0],
413 y: a[1],
414 z: a[2],
415 }
416 }
417}
418
419impl From<(f64, f64, f64)> for Point3 {
420 fn from(t: (f64, f64, f64)) -> Self {
421 Self::from_tuple(t)
422 }
423}
424
425impl From<Point3> for (f64, f64, f64) {
426 fn from(p: Point3) -> Self {
427 p.to_tuple()
428 }
429}
430
431impl From<[f64; 3]> for Point3 {
432 fn from(a: [f64; 3]) -> Self {
433 Self::from_array(a)
434 }
435}
436
437impl Sub for Point3 {
438 type Output = Vector3;
439
440 fn sub(self, rhs: Self) -> Vector3 {
441 Vector3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
442 }
443}
444
445impl Add<Vector3> for Point3 {
446 type Output = Point3;
447
448 fn add(self, rhs: Vector3) -> Point3 {
449 Point3::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
450 }
451}
452
453impl Sub<Vector3> for Point3 {
454 type Output = Point3;
455
456 fn sub(self, rhs: Vector3) -> Point3 {
457 Point3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
458 }
459}
460
461#[derive(Debug, Clone, Copy, PartialEq)]
463#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
464pub struct Vector3 {
465 pub x: f64,
466 pub y: f64,
467 pub z: f64,
468}
469
470impl Vector3 {
471 #[inline]
473 pub fn new(x: f64, y: f64, z: f64) -> Self {
474 Self { x, y, z }
475 }
476
477 pub const ZERO: Self = Self {
479 x: 0.0,
480 y: 0.0,
481 z: 0.0,
482 };
483
484 pub const UNIT_X: Self = Self {
486 x: 1.0,
487 y: 0.0,
488 z: 0.0,
489 };
490
491 pub const UNIT_Y: Self = Self {
493 x: 0.0,
494 y: 1.0,
495 z: 0.0,
496 };
497
498 pub const UNIT_Z: Self = Self {
500 x: 0.0,
501 y: 0.0,
502 z: 1.0,
503 };
504
505 #[inline]
507 pub fn length(&self) -> f64 {
508 self.length_sq().sqrt()
509 }
510
511 #[inline]
513 pub fn length_sq(&self) -> f64 {
514 self.x * self.x + self.y * self.y + self.z * self.z
515 }
516
517 #[inline]
519 pub fn normalized(&self) -> Self {
520 let len = self.length();
521 if len < 1e-15 {
522 Self::ZERO
523 } else {
524 Self::new(self.x / len, self.y / len, self.z / len)
525 }
526 }
527
528 #[inline]
536 pub fn cross(&self, other: &Self) -> Self {
537 Self::new(
538 self.y * other.z - self.z * other.y,
539 self.z * other.x - self.x * other.z,
540 self.x * other.y - self.y * other.x,
541 )
542 }
543
544 #[inline]
546 pub fn dot(&self, other: &Self) -> f64 {
547 self.x * other.x + self.y * other.y + self.z * other.z
548 }
549
550 #[inline]
552 pub fn to_array(self) -> [f64; 3] {
553 [self.x, self.y, self.z]
554 }
555}
556
557impl Add for Vector3 {
558 type Output = Self;
559
560 fn add(self, rhs: Self) -> Self {
561 Self::new(self.x + rhs.x, self.y + rhs.y, self.z + rhs.z)
562 }
563}
564
565impl Sub for Vector3 {
566 type Output = Self;
567
568 fn sub(self, rhs: Self) -> Self {
569 Self::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
570 }
571}
572
573impl Mul<f64> for Vector3 {
574 type Output = Self;
575
576 fn mul(self, rhs: f64) -> Self {
577 Self::new(self.x * rhs, self.y * rhs, self.z * rhs)
578 }
579}
580
581#[derive(Debug, Clone, Copy, PartialEq)]
589#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
590pub struct AABB3 {
591 pub min: Point3,
593 pub max: Point3,
595}
596
597impl AABB3 {
598 pub fn new(min_x: f64, min_y: f64, min_z: f64, max_x: f64, max_y: f64, max_z: f64) -> Self {
600 Self {
601 min: Point3::new(min_x, min_y, min_z),
602 max: Point3::new(max_x, max_y, max_z),
603 }
604 }
605
606 pub fn from_min_size(min: Point3, width: f64, depth: f64, height: f64) -> Self {
608 Self {
609 min,
610 max: Point3::new(min.x + width, min.y + depth, min.z + height),
611 }
612 }
613
614 pub fn from_points(points: &[Point3]) -> Option<Self> {
621 let first = points.first()?;
622 let mut min_x = first.x;
623 let mut min_y = first.y;
624 let mut min_z = first.z;
625 let mut max_x = first.x;
626 let mut max_y = first.y;
627 let mut max_z = first.z;
628
629 for p in points.iter().skip(1) {
630 min_x = min_x.min(p.x);
631 min_y = min_y.min(p.y);
632 min_z = min_z.min(p.z);
633 max_x = max_x.max(p.x);
634 max_y = max_y.max(p.y);
635 max_z = max_z.max(p.z);
636 }
637
638 Some(Self::new(min_x, min_y, min_z, max_x, max_y, max_z))
639 }
640
641 #[inline]
643 pub fn width(&self) -> f64 {
644 self.max.x - self.min.x
645 }
646
647 #[inline]
649 pub fn depth(&self) -> f64 {
650 self.max.y - self.min.y
651 }
652
653 #[inline]
655 pub fn height(&self) -> f64 {
656 self.max.z - self.min.z
657 }
658
659 #[inline]
661 pub fn volume(&self) -> f64 {
662 self.width() * self.depth() * self.height()
663 }
664
665 #[inline]
669 pub fn surface_area(&self) -> f64 {
670 let w = self.width();
671 let d = self.depth();
672 let h = self.height();
673 2.0 * (w * d + w * h + d * h)
674 }
675
676 #[inline]
678 pub fn center(&self) -> Point3 {
679 Point3::new(
680 (self.min.x + self.max.x) * 0.5,
681 (self.min.y + self.max.y) * 0.5,
682 (self.min.z + self.max.z) * 0.5,
683 )
684 }
685
686 #[inline]
688 pub fn contains_point(&self, p: &Point3) -> bool {
689 p.x >= self.min.x
690 && p.x <= self.max.x
691 && p.y >= self.min.y
692 && p.y <= self.max.y
693 && p.z >= self.min.z
694 && p.z <= self.max.z
695 }
696
697 #[inline]
699 pub fn contains(&self, other: &Self) -> bool {
700 self.min.x <= other.min.x
701 && self.min.y <= other.min.y
702 && self.min.z <= other.min.z
703 && self.max.x >= other.max.x
704 && self.max.y >= other.max.y
705 && self.max.z >= other.max.z
706 }
707
708 #[inline]
713 pub fn intersects(&self, other: &Self) -> bool {
714 self.min.x <= other.max.x
715 && self.max.x >= other.min.x
716 && self.min.y <= other.max.y
717 && self.max.y >= other.min.y
718 && self.min.z <= other.max.z
719 && self.max.z >= other.min.z
720 }
721
722 pub fn intersection(&self, other: &Self) -> Option<Self> {
724 if !self.intersects(other) {
725 return None;
726 }
727 Some(Self::new(
728 self.min.x.max(other.min.x),
729 self.min.y.max(other.min.y),
730 self.min.z.max(other.min.z),
731 self.max.x.min(other.max.x),
732 self.max.y.min(other.max.y),
733 self.max.z.min(other.max.z),
734 ))
735 }
736
737 pub fn union(&self, other: &Self) -> Self {
739 Self::new(
740 self.min.x.min(other.min.x),
741 self.min.y.min(other.min.y),
742 self.min.z.min(other.min.z),
743 self.max.x.max(other.max.x),
744 self.max.y.max(other.max.y),
745 self.max.z.max(other.max.z),
746 )
747 }
748
749 pub fn expand(&self, margin: f64) -> Self {
751 Self::new(
752 self.min.x - margin,
753 self.min.y - margin,
754 self.min.z - margin,
755 self.max.x + margin,
756 self.max.y + margin,
757 self.max.z + margin,
758 )
759 }
760}
761
762#[cfg(test)]
763mod tests {
764 use super::*;
765
766 #[test]
767 fn test_point2_distance() {
768 let a = Point2::new(0.0, 0.0);
769 let b = Point2::new(3.0, 4.0);
770 assert!((a.distance_to(&b) - 5.0).abs() < 1e-10);
771 }
772
773 #[test]
774 fn test_point2_sub_gives_vector() {
775 let a = Point2::new(3.0, 5.0);
776 let b = Point2::new(1.0, 2.0);
777 let v = a - b;
778 assert!((v.x - 2.0).abs() < 1e-10);
779 assert!((v.y - 3.0).abs() < 1e-10);
780 }
781
782 #[test]
783 fn test_point2_add_vector() {
784 let p = Point2::new(1.0, 2.0);
785 let v = Vector2::new(3.0, 4.0);
786 let q = p + v;
787 assert!((q.x - 4.0).abs() < 1e-10);
788 assert!((q.y - 6.0).abs() < 1e-10);
789 }
790
791 #[test]
792 fn test_vector2_operations() {
793 let v = Vector2::new(3.0, 4.0);
794 assert!((v.length() - 5.0).abs() < 1e-10);
795 assert!((v.length_sq() - 25.0).abs() < 1e-10);
796
797 let n = v.normalized();
798 assert!((n.length() - 1.0).abs() < 1e-10);
799 }
800
801 #[test]
802 fn test_vector2_cross() {
803 let a = Vector2::new(1.0, 0.0);
804 let b = Vector2::new(0.0, 1.0);
805 assert!((a.cross(&b) - 1.0).abs() < 1e-10);
806 assert!((b.cross(&a) - (-1.0)).abs() < 1e-10);
807 }
808
809 #[test]
810 fn test_vector2_dot() {
811 let a = Vector2::new(1.0, 2.0);
812 let b = Vector2::new(3.0, 4.0);
813 assert!((a.dot(&b) - 11.0).abs() < 1e-10);
814 }
815
816 #[test]
817 fn test_vector2_perp() {
818 let v = Vector2::new(1.0, 0.0);
819 let p = v.perp();
820 assert!((p.x - 0.0).abs() < 1e-10);
821 assert!((p.y - 1.0).abs() < 1e-10);
822 }
823
824 #[test]
825 fn test_vector2_normalized_zero() {
826 let v = Vector2::ZERO;
827 let n = v.normalized();
828 assert!((n.length()).abs() < 1e-10);
829 }
830
831 #[test]
832 fn test_segment2() {
833 let s = Segment2::new(Point2::new(0.0, 0.0), Point2::new(3.0, 4.0));
834 assert!((s.length() - 5.0).abs() < 1e-10);
835 let mid = s.midpoint();
836 assert!((mid.x - 1.5).abs() < 1e-10);
837 assert!((mid.y - 2.0).abs() < 1e-10);
838 }
839
840 #[test]
841 fn test_aabb2_from_points() {
842 let points = vec![
843 Point2::new(0.0, 0.0),
844 Point2::new(10.0, 5.0),
845 Point2::new(3.0, 8.0),
846 ];
847 let aabb = AABB2::from_points(&points).unwrap();
848 assert!((aabb.min.x - 0.0).abs() < 1e-10);
849 assert!((aabb.min.y - 0.0).abs() < 1e-10);
850 assert!((aabb.max.x - 10.0).abs() < 1e-10);
851 assert!((aabb.max.y - 8.0).abs() < 1e-10);
852 }
853
854 #[test]
855 fn test_aabb2_from_points_empty() {
856 assert!(AABB2::from_points(&[]).is_none());
857 }
858
859 #[test]
860 fn test_aabb2_area() {
861 let aabb = AABB2::new(0.0, 0.0, 10.0, 20.0);
862 assert!((aabb.area() - 200.0).abs() < 1e-10);
863 }
864
865 #[test]
866 fn test_aabb2_contains() {
867 let aabb = AABB2::new(0.0, 0.0, 10.0, 10.0);
868 assert!(aabb.contains_point(&Point2::new(5.0, 5.0)));
869 assert!(aabb.contains_point(&Point2::new(0.0, 0.0))); assert!(!aabb.contains_point(&Point2::new(11.0, 5.0)));
871 }
872
873 #[test]
874 fn test_aabb2_intersection() {
875 let a = AABB2::new(0.0, 0.0, 10.0, 10.0);
876 let b = AABB2::new(5.0, 5.0, 15.0, 15.0);
877 let int = a.intersection(&b).unwrap();
878 assert!((int.min.x - 5.0).abs() < 1e-10);
879 assert!((int.min.y - 5.0).abs() < 1e-10);
880 assert!((int.max.x - 10.0).abs() < 1e-10);
881 assert!((int.max.y - 10.0).abs() < 1e-10);
882
883 let c = AABB2::new(20.0, 20.0, 30.0, 30.0);
884 assert!(a.intersection(&c).is_none());
885 }
886
887 #[test]
888 fn test_aabb2_union() {
889 let a = AABB2::new(0.0, 0.0, 10.0, 10.0);
890 let b = AABB2::new(5.0, 5.0, 15.0, 15.0);
891 let u = a.union(&b);
892 assert!((u.min.x - 0.0).abs() < 1e-10);
893 assert!((u.min.y - 0.0).abs() < 1e-10);
894 assert!((u.max.x - 15.0).abs() < 1e-10);
895 assert!((u.max.y - 15.0).abs() < 1e-10);
896 }
897
898 #[test]
899 fn test_aabb2_expand() {
900 let aabb = AABB2::new(5.0, 5.0, 10.0, 10.0);
901 let expanded = aabb.expand(1.0);
902 assert!((expanded.min.x - 4.0).abs() < 1e-10);
903 assert!((expanded.min.y - 4.0).abs() < 1e-10);
904 assert!((expanded.max.x - 11.0).abs() < 1e-10);
905 assert!((expanded.max.y - 11.0).abs() < 1e-10);
906 }
907
908 #[test]
909 fn test_point2_from_tuple() {
910 let p: Point2 = (3.0, 4.0).into();
911 assert!((p.x - 3.0).abs() < 1e-10);
912 assert!((p.y - 4.0).abs() < 1e-10);
913
914 let t: (f64, f64) = p.into();
915 assert!((t.0 - 3.0).abs() < 1e-10);
916 }
917
918 #[test]
921 fn test_point3_distance() {
922 let a = Point3::new(0.0, 0.0, 0.0);
923 let b = Point3::new(1.0, 2.0, 2.0);
924 assert!((a.distance_to(&b) - 3.0).abs() < 1e-10);
925 }
926
927 #[test]
928 fn test_point3_sub_gives_vector() {
929 let a = Point3::new(3.0, 5.0, 7.0);
930 let b = Point3::new(1.0, 2.0, 3.0);
931 let v = a - b;
932 assert!((v.x - 2.0).abs() < 1e-10);
933 assert!((v.y - 3.0).abs() < 1e-10);
934 assert!((v.z - 4.0).abs() < 1e-10);
935 }
936
937 #[test]
938 fn test_point3_add_vector() {
939 let p = Point3::new(1.0, 2.0, 3.0);
940 let v = Vector3::new(4.0, 5.0, 6.0);
941 let q = p + v;
942 assert!((q.x - 5.0).abs() < 1e-10);
943 assert!((q.y - 7.0).abs() < 1e-10);
944 assert!((q.z - 9.0).abs() < 1e-10);
945 }
946
947 #[test]
948 fn test_point3_sub_vector() {
949 let p = Point3::new(5.0, 7.0, 9.0);
950 let v = Vector3::new(1.0, 2.0, 3.0);
951 let q = p - v;
952 assert!((q.x - 4.0).abs() < 1e-10);
953 assert!((q.y - 5.0).abs() < 1e-10);
954 assert!((q.z - 6.0).abs() < 1e-10);
955 }
956
957 #[test]
958 fn test_point3_conversions() {
959 let p = Point3::new(1.0, 2.0, 3.0);
960 let t: (f64, f64, f64) = p.into();
961 assert!((t.0 - 1.0).abs() < 1e-10);
962 assert!((t.1 - 2.0).abs() < 1e-10);
963 assert!((t.2 - 3.0).abs() < 1e-10);
964
965 let p2: Point3 = (4.0, 5.0, 6.0).into();
966 assert!((p2.x - 4.0).abs() < 1e-10);
967
968 let a = p.to_array();
969 assert!((a[0] - 1.0).abs() < 1e-10);
970 let p3 = Point3::from_array([7.0, 8.0, 9.0]);
971 assert!((p3.z - 9.0).abs() < 1e-10);
972 }
973
974 #[test]
975 fn test_vector3_operations() {
976 let v = Vector3::new(1.0, 2.0, 2.0);
977 assert!((v.length() - 3.0).abs() < 1e-10);
978 assert!((v.length_sq() - 9.0).abs() < 1e-10);
979
980 let n = v.normalized();
981 assert!((n.length() - 1.0).abs() < 1e-10);
982 }
983
984 #[test]
985 fn test_vector3_cross() {
986 let x = Vector3::UNIT_X;
987 let y = Vector3::UNIT_Y;
988 let z = x.cross(&y);
989 assert!((z.x - 0.0).abs() < 1e-10);
990 assert!((z.y - 0.0).abs() < 1e-10);
991 assert!((z.z - 1.0).abs() < 1e-10);
992
993 let neg_z = y.cross(&x);
995 assert!((neg_z.z - (-1.0)).abs() < 1e-10);
996 }
997
998 #[test]
999 fn test_vector3_dot() {
1000 let a = Vector3::new(1.0, 2.0, 3.0);
1001 let b = Vector3::new(4.0, 5.0, 6.0);
1002 assert!((a.dot(&b) - 32.0).abs() < 1e-10); }
1004
1005 #[test]
1006 fn test_vector3_normalized_zero() {
1007 let v = Vector3::ZERO;
1008 let n = v.normalized();
1009 assert!(n.length() < 1e-10);
1010 }
1011
1012 #[test]
1013 fn test_vector3_arithmetic() {
1014 let a = Vector3::new(1.0, 2.0, 3.0);
1015 let b = Vector3::new(4.0, 5.0, 6.0);
1016 let sum = a + b;
1017 assert!((sum.x - 5.0).abs() < 1e-10);
1018 let diff = b - a;
1019 assert!((diff.x - 3.0).abs() < 1e-10);
1020 let scaled = a * 2.0;
1021 assert!((scaled.z - 6.0).abs() < 1e-10);
1022 }
1023
1024 #[test]
1025 fn test_aabb3_basics() {
1026 let aabb = AABB3::new(0.0, 0.0, 0.0, 10.0, 20.0, 30.0);
1027 assert!((aabb.width() - 10.0).abs() < 1e-10);
1028 assert!((aabb.depth() - 20.0).abs() < 1e-10);
1029 assert!((aabb.height() - 30.0).abs() < 1e-10);
1030 assert!((aabb.volume() - 6000.0).abs() < 1e-10);
1031 assert!((aabb.surface_area() - 2200.0).abs() < 1e-10); }
1033
1034 #[test]
1035 fn test_aabb3_from_min_size() {
1036 let aabb = AABB3::from_min_size(Point3::new(1.0, 2.0, 3.0), 4.0, 5.0, 6.0);
1037 assert!((aabb.max.x - 5.0).abs() < 1e-10);
1038 assert!((aabb.max.y - 7.0).abs() < 1e-10);
1039 assert!((aabb.max.z - 9.0).abs() < 1e-10);
1040 }
1041
1042 #[test]
1043 fn test_aabb3_from_points() {
1044 let points = vec![
1045 Point3::new(0.0, 0.0, 0.0),
1046 Point3::new(10.0, 5.0, 3.0),
1047 Point3::new(3.0, 8.0, 7.0),
1048 ];
1049 let aabb = AABB3::from_points(&points).unwrap();
1050 assert!((aabb.min.x - 0.0).abs() < 1e-10);
1051 assert!((aabb.max.y - 8.0).abs() < 1e-10);
1052 assert!((aabb.max.z - 7.0).abs() < 1e-10);
1053 }
1054
1055 #[test]
1056 fn test_aabb3_from_points_empty() {
1057 assert!(AABB3::from_points(&[]).is_none());
1058 }
1059
1060 #[test]
1061 fn test_aabb3_contains_point() {
1062 let aabb = AABB3::new(0.0, 0.0, 0.0, 10.0, 10.0, 10.0);
1063 assert!(aabb.contains_point(&Point3::new(5.0, 5.0, 5.0)));
1064 assert!(aabb.contains_point(&Point3::new(0.0, 0.0, 0.0))); assert!(!aabb.contains_point(&Point3::new(11.0, 5.0, 5.0)));
1066 }
1067
1068 #[test]
1069 fn test_aabb3_contains_aabb() {
1070 let outer = AABB3::new(0.0, 0.0, 0.0, 10.0, 10.0, 10.0);
1071 let inner = AABB3::new(2.0, 2.0, 2.0, 8.0, 8.0, 8.0);
1072 assert!(outer.contains(&inner));
1073 assert!(!inner.contains(&outer));
1074 }
1075
1076 #[test]
1077 fn test_aabb3_intersects() {
1078 let a = AABB3::new(0.0, 0.0, 0.0, 10.0, 10.0, 10.0);
1079 let b = AABB3::new(5.0, 5.0, 5.0, 15.0, 15.0, 15.0);
1080 assert!(a.intersects(&b));
1081
1082 let c = AABB3::new(20.0, 20.0, 20.0, 30.0, 30.0, 30.0);
1083 assert!(!a.intersects(&c));
1084 }
1085
1086 #[test]
1087 fn test_aabb3_intersection() {
1088 let a = AABB3::new(0.0, 0.0, 0.0, 10.0, 10.0, 10.0);
1089 let b = AABB3::new(5.0, 5.0, 5.0, 15.0, 15.0, 15.0);
1090 let int = a.intersection(&b).unwrap();
1091 assert!((int.min.x - 5.0).abs() < 1e-10);
1092 assert!((int.max.z - 10.0).abs() < 1e-10);
1093 assert!((int.volume() - 125.0).abs() < 1e-10); let c = AABB3::new(20.0, 20.0, 20.0, 30.0, 30.0, 30.0);
1096 assert!(a.intersection(&c).is_none());
1097 }
1098
1099 #[test]
1100 fn test_aabb3_union() {
1101 let a = AABB3::new(0.0, 0.0, 0.0, 10.0, 10.0, 10.0);
1102 let b = AABB3::new(5.0, 5.0, 5.0, 15.0, 15.0, 15.0);
1103 let u = a.union(&b);
1104 assert!((u.min.x - 0.0).abs() < 1e-10);
1105 assert!((u.max.x - 15.0).abs() < 1e-10);
1106 assert!((u.volume() - 3375.0).abs() < 1e-10); }
1108
1109 #[test]
1110 fn test_aabb3_expand() {
1111 let aabb = AABB3::new(5.0, 5.0, 5.0, 10.0, 10.0, 10.0);
1112 let expanded = aabb.expand(1.0);
1113 assert!((expanded.min.x - 4.0).abs() < 1e-10);
1114 assert!((expanded.max.z - 11.0).abs() < 1e-10);
1115 }
1116
1117 #[test]
1118 fn test_aabb3_center() {
1119 let aabb = AABB3::new(0.0, 0.0, 0.0, 10.0, 20.0, 30.0);
1120 let c = aabb.center();
1121 assert!((c.x - 5.0).abs() < 1e-10);
1122 assert!((c.y - 10.0).abs() < 1e-10);
1123 assert!((c.z - 15.0).abs() < 1e-10);
1124 }
1125
1126 #[cfg(feature = "serde")]
1129 mod serde_tests {
1130 use super::*;
1131
1132 #[test]
1133 fn test_point2_roundtrip() {
1134 let p = Point2::new(3.14, 2.72);
1135 let json = serde_json::to_string(&p).unwrap();
1136 let p2: Point2 = serde_json::from_str(&json).unwrap();
1137 assert_eq!(p, p2);
1138 }
1139
1140 #[test]
1141 fn test_vector2_roundtrip() {
1142 let v = Vector2::new(-1.0, 5.5);
1143 let json = serde_json::to_string(&v).unwrap();
1144 let v2: Vector2 = serde_json::from_str(&json).unwrap();
1145 assert_eq!(v, v2);
1146 }
1147
1148 #[test]
1149 fn test_segment2_roundtrip() {
1150 let s = Segment2::new(Point2::new(0.0, 0.0), Point2::new(10.0, 20.0));
1151 let json = serde_json::to_string(&s).unwrap();
1152 let s2: Segment2 = serde_json::from_str(&json).unwrap();
1153 assert_eq!(s, s2);
1154 }
1155
1156 #[test]
1157 fn test_aabb2_roundtrip() {
1158 let aabb = AABB2::new(1.0, 2.0, 10.0, 20.0);
1159 let json = serde_json::to_string(&aabb).unwrap();
1160 let aabb2: AABB2 = serde_json::from_str(&json).unwrap();
1161 assert_eq!(aabb, aabb2);
1162 }
1163
1164 #[test]
1165 fn test_point3_roundtrip() {
1166 let p = Point3::new(1.0, 2.0, 3.0);
1167 let json = serde_json::to_string(&p).unwrap();
1168 let p2: Point3 = serde_json::from_str(&json).unwrap();
1169 assert_eq!(p, p2);
1170 }
1171
1172 #[test]
1173 fn test_vector3_roundtrip() {
1174 let v = Vector3::new(4.0, 5.0, 6.0);
1175 let json = serde_json::to_string(&v).unwrap();
1176 let v2: Vector3 = serde_json::from_str(&json).unwrap();
1177 assert_eq!(v, v2);
1178 }
1179
1180 #[test]
1181 fn test_aabb3_roundtrip() {
1182 let aabb = AABB3::new(0.0, 0.0, 0.0, 10.0, 20.0, 30.0);
1183 let json = serde_json::to_string(&aabb).unwrap();
1184 let aabb2: AABB3 = serde_json::from_str(&json).unwrap();
1185 assert_eq!(aabb, aabb2);
1186 }
1187 }
1188}