1use core::ops::{Add, Sub};
4use crate::vec::{Vec2, Vec3};
5use crate::Float;
6
7#[derive(Debug, Clone, Copy, PartialEq)]
9pub struct Point2<T: Float> {
10 pub x: T,
12 pub y: T,
14}
15
16impl<T: Float> Point2<T> {
17 pub fn new(x: T, y: T) -> Self { Self { x, y } }
19}
20
21impl<T: Float> Sub for Point2<T> {
23 type Output = Vec2<T>;
24 fn sub(self, rhs: Point2<T>) -> Vec2<T> {
25 Vec2::new(self.x - rhs.x, self.y - rhs.y)
26 }
27}
28
29impl<T: Float> Add<Vec2<T>> for Point2<T> {
31 type Output = Point2<T>;
32 fn add(self, v: Vec2<T>) -> Point2<T> {
33 Point2::new(self.x + v.x, self.y + v.y)
34 }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq)]
39pub struct Point3<T: Float> {
40 pub x: T,
42 pub y: T,
44 pub z: T,
46}
47
48impl<T: Float> Point3<T> {
49 pub fn new(x: T, y: T, z: T) -> Self { Self { x, y, z } }
51}
52
53impl<T: Float> Sub for Point3<T> {
54 type Output = Vec3<T>;
55 fn sub(self, rhs: Point3<T>) -> Vec3<T> {
56 Vec3::new(self.x - rhs.x, self.y - rhs.y, self.z - rhs.z)
57 }
58}
59
60impl<T: Float> Add<Vec3<T>> for Point3<T> {
61 type Output = Point3<T>;
62 fn add(self, v: Vec3<T>) -> Point3<T> {
63 Point3::new(self.x + v.x, self.y + v.y, self.z + v.z)
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use crate::{Point2, Point3, Vec3};
70
71 #[test]
72 fn roundtrip_point3_vector_ops() {
73 let p = Point3::new(1.0, 2.0, 3.0);
74 let q = Point3::new(4.0, 6.0, 5.0);
75 let v = q - p;
76 assert_eq!(v, Vec3::new(3.0, 4.0, 2.0));
78 assert_eq!(p + v, q);
80 }
81
82 #[test]
83 fn point2_sub_add_consistency() {
84 let p = Point2::new(0.5, 1.5);
85 let q = Point2::new(-1.0, 4.0);
86 let v = q - p;
87 assert_eq!(p + v, q);
88 }
89}