bracket_geometry/
point3.rs

1use std::convert::{From, TryInto};
2use std::ops;
3use ultraviolet::Vec3;
4
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6#[derive(Eq, PartialEq, Copy, Clone, Debug)]
7/// Helper struct defining a 2D point in space.
8pub struct Point3 {
9    /// The 3D point's X location
10    pub x: i32,
11    /// The 3D point's Y location
12    pub y: i32,
13    /// The 3D point's Z location
14    pub z: i32,
15}
16
17#[cfg(feature = "specs")]
18impl specs::prelude::Component for Point3 {
19    type Storage = specs::prelude::VecStorage<Self>;
20}
21
22#[cfg(feature = "bevy")]
23impl bevy::ecs::component::Component for Point3 {
24    type Storage = bevy::ecs::component::TableStorage;
25}
26
27impl Point3 {
28    /// Create a new point from an x/y/z coordinate.
29    pub fn new<T>(x: T, y: T, z: T) -> Self
30    where
31        T: TryInto<i32>,
32    {
33        Self {
34            x: x.try_into().ok().unwrap(),
35            y: y.try_into().ok().unwrap(),
36            z: z.try_into().ok().unwrap(),
37        }
38    }
39
40    /// Create a point from an x/y/z tuple
41    #[must_use]
42    pub fn from_tuple(t: (i32, i32, i32)) -> Self {
43        Self {
44            x: t.0,
45            y: t.1,
46            z: t.2,
47        }
48    }
49
50    /// Converts into an UltraViolet Vec3
51    pub fn to_vec3(&self) -> Vec3 {
52        Vec3::new(self.x as f32, self.y as f32, self.z as f32)
53    }
54
55    /*
56    /// Converts into an UltraViolet Vec3
57    pub fn to_vec3i(&self) -> Vec3i {
58        Vec3i::new(self.x, self.y, self.z)
59    }
60    */
61}
62
63impl From<Vec3> for Point3 {
64    fn from(item: Vec3) -> Self {
65        Self {
66            x: item.x as i32,
67            y: item.y as i32,
68            z: item.z as i32,
69        }
70    }
71}
72
73/*
74impl From<Vec3i> for Point3 {
75    fn from(item: Vec3i) -> Self {
76        Self {
77            x: item.x,
78            y: item.y,
79            z: item.z,
80        }
81    }
82}
83*/
84
85///////////////////////////////////////////////////////////////////////////////////////
86/// Overloads: We support basic point math
87
88/// Support adding a point to a point
89impl ops::Add<Point3> for Point3 {
90    type Output = Point3;
91    fn add(mut self, rhs: Point3) -> Point3 {
92        self.x += rhs.x;
93        self.y += rhs.y;
94        self.z += rhs.z;
95        self
96    }
97}
98
99/// Support adding an int to a point
100impl ops::Add<i32> for Point3 {
101    type Output = Point3;
102    fn add(mut self, rhs: i32) -> Point3 {
103        self.x += rhs;
104        self.y += rhs;
105        self.z += rhs;
106        self
107    }
108}
109
110/// Support subtracting a point from a point
111impl ops::Sub<Point3> for Point3 {
112    type Output = Point3;
113    fn sub(mut self, rhs: Point3) -> Point3 {
114        self.x -= rhs.x;
115        self.y -= rhs.y;
116        self.z -= rhs.z;
117        self
118    }
119}
120
121/// Support subtracting an int from a point
122impl ops::Sub<i32> for Point3 {
123    type Output = Point3;
124    fn sub(mut self, rhs: i32) -> Point3 {
125        self.x -= rhs;
126        self.y -= rhs;
127        self.z -= rhs;
128        self
129    }
130}
131
132/// Support multiplying a point by a point
133impl ops::Mul<Point3> for Point3 {
134    type Output = Point3;
135    fn mul(mut self, rhs: Point3) -> Point3 {
136        self.x *= rhs.x;
137        self.y *= rhs.y;
138        self.z *= rhs.z;
139        self
140    }
141}
142
143/// Support multiplying a point by an int
144impl ops::Mul<i32> for Point3 {
145    type Output = Point3;
146    fn mul(mut self, rhs: i32) -> Point3 {
147        self.x *= rhs;
148        self.y *= rhs;
149        self.z *= rhs;
150        self
151    }
152}
153
154/// Support multiplying a point by an f32
155impl ops::Mul<f32> for Point3 {
156    type Output = Point3;
157    fn mul(mut self, rhs: f32) -> Point3 {
158        self.x = (self.x as f32 * rhs) as i32;
159        self.y = (self.y as f32 * rhs) as i32;
160        self.z = (self.z as f32 * rhs) as i32;
161        self
162    }
163}
164
165/// Support dividing a point by a point
166impl ops::Div<Point3> for Point3 {
167    type Output = Point3;
168    fn div(mut self, rhs: Point3) -> Point3 {
169        self.x /= rhs.x;
170        self.y /= rhs.y;
171        self.z /= rhs.z;
172        self
173    }
174}
175
176/// Support dividing a point by an int
177impl ops::Div<i32> for Point3 {
178    type Output = Point3;
179    fn div(mut self, rhs: i32) -> Point3 {
180        self.x /= rhs;
181        self.y /= rhs;
182        self.z /= rhs;
183        self
184    }
185}
186
187/// Support dividing a point by an f32
188impl ops::Div<f32> for Point3 {
189    type Output = Point3;
190    fn div(mut self, rhs: f32) -> Point3 {
191        self.x = (self.x as f32 / rhs) as i32;
192        self.y = (self.y as f32 / rhs) as i32;
193        self.z = (self.z as f32 / rhs) as i32;
194        self
195    }
196}
197
198// Support AddAssign for Point3
199impl ops::AddAssign for Point3 {
200    fn add_assign(&mut self, other: Self) {
201        *self = Self {
202            x: self.x + other.x,
203            y: self.y + other.y,
204            z: self.z + other.z,
205        };
206    }
207}
208
209// Support SubAssign for Point3
210impl ops::SubAssign for Point3 {
211    fn sub_assign(&mut self, other: Self) {
212        *self = Self {
213            x: self.x - other.x,
214            y: self.y - other.y,
215            z: self.z - other.z,
216        };
217    }
218}
219
220// Support MulAssign for Point3
221impl ops::MulAssign for Point3 {
222    fn mul_assign(&mut self, other: Self) {
223        *self = Self {
224            x: self.x * other.x,
225            y: self.y * other.y,
226            z: self.z * other.z,
227        };
228    }
229}
230
231// Support DivAssign for Point3
232impl ops::DivAssign for Point3 {
233    fn div_assign(&mut self, other: Self) {
234        *self = Self {
235            x: self.x / other.x,
236            y: self.y / other.y,
237            z: self.z / other.z,
238        };
239    }
240}
241
242// Unit tests
243#[cfg(test)]
244mod tests {
245    use super::Point3;
246
247    #[test]
248    fn new_point3() {
249        let pt = Point3::new(1, 2, 3);
250        assert_eq!(pt.x, 1);
251        assert_eq!(pt.y, 2);
252        assert_eq!(pt.z, 3);
253    }
254
255    #[test]
256    fn add_point_to_point3() {
257        let pt = Point3::new(0, 0, 0);
258        let p2 = pt + Point3::new(1, 2, 3);
259        assert_eq!(p2.x, 1);
260        assert_eq!(p2.y, 2);
261        assert_eq!(p2.z, 3);
262    }
263
264    #[test]
265    fn add_assign_point_to_point3() {
266        let mut pt = Point3::new(0, 0, 0);
267        pt += Point3::new(1, 2, 3);
268        assert_eq!(pt.x, 1);
269        assert_eq!(pt.y, 2);
270        assert_eq!(pt.z, 3);
271    }
272
273    #[test]
274    fn add_point3_to_int() {
275        let pt = Point3::new(0, 0, 0);
276        let p2 = pt + 2;
277        assert_eq!(p2.x, 2);
278        assert_eq!(p2.y, 2);
279        assert_eq!(p2.z, 2);
280    }
281
282    #[test]
283    fn sub_point3_to_point() {
284        let pt = Point3::new(0, 0, 0);
285        let p2 = pt - Point3::new(1, 2, 3);
286        assert_eq!(p2.x, -1);
287        assert_eq!(p2.y, -2);
288        assert_eq!(p2.z, -3);
289    }
290
291    #[test]
292    fn sub_assign_point3_to_point() {
293        let mut pt = Point3::new(0, 0, 0);
294        pt -= Point3::new(1, 2, 3);
295        assert_eq!(pt.x, -1);
296        assert_eq!(pt.y, -2);
297        assert_eq!(pt.z, -3);
298    }
299
300    #[test]
301    fn sub_point3_to_int() {
302        let pt = Point3::new(0, 0, 0);
303        let p2 = pt - 2;
304        assert_eq!(p2.x, -2);
305        assert_eq!(p2.y, -2);
306        assert_eq!(p2.z, -2);
307    }
308
309    #[test]
310    fn mul_point3_to_point() {
311        let pt = Point3::new(1, 1, 1);
312        let p2 = pt * Point3::new(1, 2, 4);
313        assert_eq!(p2.x, 1);
314        assert_eq!(p2.y, 2);
315        assert_eq!(p2.z, 4);
316    }
317
318    #[test]
319    fn mul_assign_point3_to_point() {
320        let mut pt = Point3::new(1, 1, 1);
321        pt *= Point3::new(1, 2, 4);
322        assert_eq!(pt.x, 1);
323        assert_eq!(pt.y, 2);
324        assert_eq!(pt.z, 4);
325    }
326
327    #[test]
328    fn mul_point3_to_int() {
329        let pt = Point3::new(1, 1, 1);
330        let p2 = pt * 2;
331        assert_eq!(p2.x, 2);
332        assert_eq!(p2.y, 2);
333        assert_eq!(p2.z, 2);
334    }
335
336    #[test]
337    fn mul_point3_to_float() {
338        let pt = Point3::new(1, 1, 1);
339        let p2 = pt * 4.0;
340        assert_eq!(p2.x, 4);
341        assert_eq!(p2.y, 4);
342        assert_eq!(p2.z, 4);
343    }
344
345    #[test]
346    fn div_point3_to_point() {
347        let pt = Point3::new(4, 4, 4);
348        let p2 = pt / Point3::new(2, 4, 1);
349        assert_eq!(p2.x, 2);
350        assert_eq!(p2.y, 1);
351        assert_eq!(p2.z, 4);
352    }
353
354    #[test]
355    fn div_assign_point3_to_point() {
356        let mut pt = Point3::new(4, 4, 4);
357        pt /= Point3::new(2, 4, 1);
358        assert_eq!(pt.x, 2);
359        assert_eq!(pt.y, 1);
360        assert_eq!(pt.z, 4);
361    }
362
363    #[test]
364    fn div_point3_to_int() {
365        let pt = Point3::new(4, 4, 4);
366        let p2 = pt / 2;
367        assert_eq!(p2.x, 2);
368        assert_eq!(p2.y, 2);
369        assert_eq!(p2.z, 2);
370    }
371
372    #[test]
373    fn div_point3_to_float() {
374        let pt = Point3::new(4, 4, 4);
375        let p2 = pt / 2.0;
376        assert_eq!(p2.x, 2);
377        assert_eq!(p2.y, 2);
378        assert_eq!(p2.z, 2);
379    }
380}