1use std::fmt;
4use serde::{Serialize, Deserialize};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub struct Point {
10 pub x: i32,
11 pub y: i32,
12}
13
14impl Point {
15 pub fn new(x: i32, y: i32) -> Self {
17 Self { x, y }
18 }
19
20 pub fn origin() -> Self {
22 Self::new(0, 0)
23 }
24
25 pub fn distance_to(&self, other: &Point) -> f64 {
27 let dx = (self.x - other.x) as f64;
28 let dy = (self.y - other.y) as f64;
29 (dx * dx + dy * dy).sqrt()
30 }
31
32 pub fn dot(&self, other: &Point) -> i32 {
34 self.x * other.x + self.y * other.y
35 }
36}
37
38impl Default for Point {
39 fn default() -> Self {
40 Self::origin()
41 }
42}
43
44impl fmt::Display for Point {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 write!(f, "({}, {})", self.x, self.y)
47 }
48}
49
50impl From<(i32, i32)> for Point {
51 fn from((x, y): (i32, i32)) -> Self {
52 Self::new(x, y)
53 }
54}
55
56impl From<Point> for (i32, i32) {
57 fn from(point: Point) -> Self {
58 (point.x, point.y)
59 }
60}
61
62#[derive(Debug, Clone, Copy, PartialEq)]
64#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
65pub struct Point2f {
66 pub x: f32,
67 pub y: f32,
68}
69
70impl Point2f {
71 pub fn new(x: f32, y: f32) -> Self {
73 Self { x, y }
74 }
75
76 pub fn origin() -> Self {
78 Self::new(0.0, 0.0)
79 }
80
81 pub fn distance_to(&self, other: &Point2f) -> f32 {
83 let dx = self.x - other.x;
84 let dy = self.y - other.y;
85 (dx * dx + dy * dy).sqrt()
86 }
87
88 pub fn dot(&self, other: &Point2f) -> f32 {
90 self.x * other.x + self.y * other.y
91 }
92
93 pub fn normalize(&self) -> Point2f {
95 let len = (self.x * self.x + self.y * self.y).sqrt();
96 if len > 0.0 {
97 Point2f::new(self.x / len, self.y / len)
98 } else {
99 *self
100 }
101 }
102}
103
104impl Default for Point2f {
105 fn default() -> Self {
106 Self::origin()
107 }
108}
109
110impl fmt::Display for Point2f {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 write!(f, "({:.2}, {:.2})", self.x, self.y)
113 }
114}
115
116impl From<(f32, f32)> for Point2f {
117 fn from((x, y): (f32, f32)) -> Self {
118 Self::new(x, y)
119 }
120}
121
122impl From<Point2f> for (f32, f32) {
123 fn from(point: Point2f) -> Self {
124 (point.x, point.y)
125 }
126}
127
128impl From<Point> for Point2f {
129 fn from(point: Point) -> Self {
130 Self::new(point.x as f32, point.y as f32)
131 }
132}
133
134#[derive(Debug, Clone, Copy, PartialEq)]
136#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
137pub struct Point2d {
138 pub x: f64,
139 pub y: f64,
140}
141
142impl Point2d {
143 pub fn new(x: f64, y: f64) -> Self {
145 Self { x, y }
146 }
147
148 pub fn origin() -> Self {
150 Self::new(0.0, 0.0)
151 }
152
153 pub fn distance_to(&self, other: &Point2d) -> f64 {
155 let dx = self.x - other.x;
156 let dy = self.y - other.y;
157 (dx * dx + dy * dy).sqrt()
158 }
159
160 pub fn dot(&self, other: &Point2d) -> f64 {
162 self.x * other.x + self.y * other.y
163 }
164
165 pub fn normalize(&self) -> Point2d {
167 let len = (self.x * self.x + self.y * self.y).sqrt();
168 if len > 0.0 {
169 Point2d::new(self.x / len, self.y / len)
170 } else {
171 *self
172 }
173 }
174}
175
176impl Default for Point2d {
177 fn default() -> Self {
178 Self::origin()
179 }
180}
181
182impl fmt::Display for Point2d {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 write!(f, "({:.6}, {:.6})", self.x, self.y)
185 }
186}
187
188impl From<(f64, f64)> for Point2d {
189 fn from((x, y): (f64, f64)) -> Self {
190 Self::new(x, y)
191 }
192}
193
194impl From<Point2d> for (f64, f64) {
195 fn from(point: Point2d) -> Self {
196 (point.x, point.y)
197 }
198}
199
200impl From<Point2f> for Point2d {
201 fn from(point: Point2f) -> Self {
202 Self::new(point.x as f64, point.y as f64)
203 }
204}
205
206#[derive(Debug, Clone, Copy, PartialEq)]
208#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
209pub struct Point3f {
210 pub x: f32,
211 pub y: f32,
212 pub z: f32,
213}
214
215impl Point3f {
216 pub fn new(x: f32, y: f32, z: f32) -> Self {
218 Self { x, y, z }
219 }
220
221 pub fn origin() -> Self {
223 Self::new(0.0, 0.0, 0.0)
224 }
225
226 pub fn distance_to(&self, other: &Point3f) -> f32 {
228 let dx = self.x - other.x;
229 let dy = self.y - other.y;
230 let dz = self.z - other.z;
231 (dx * dx + dy * dy + dz * dz).sqrt()
232 }
233
234 pub fn dot(&self, other: &Point3f) -> f32 {
236 self.x * other.x + self.y * other.y + self.z * other.z
237 }
238
239 pub fn cross(&self, other: &Point3f) -> Point3f {
241 Point3f::new(
242 self.y * other.z - self.z * other.y,
243 self.z * other.x - self.x * other.z,
244 self.x * other.y - self.y * other.x,
245 )
246 }
247
248 pub fn normalize(&self) -> Point3f {
250 let len = (self.x * self.x + self.y * self.y + self.z * self.z).sqrt();
251 if len > 0.0 {
252 Point3f::new(self.x / len, self.y / len, self.z / len)
253 } else {
254 *self
255 }
256 }
257}
258
259impl Default for Point3f {
260 fn default() -> Self {
261 Self::origin()
262 }
263}
264
265impl fmt::Display for Point3f {
266 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
267 write!(f, "({:.2}, {:.2}, {:.2})", self.x, self.y, self.z)
268 }
269}
270
271impl From<(f32, f32, f32)> for Point3f {
272 fn from((x, y, z): (f32, f32, f32)) -> Self {
273 Self::new(x, y, z)
274 }
275}
276
277impl From<Point3f> for (f32, f32, f32) {
278 fn from(point: Point3f) -> Self {
279 (point.x, point.y, point.z)
280 }
281}
282
283#[derive(Debug, Clone, Copy, PartialEq)]
285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
286pub struct Point3d {
287 pub x: f64,
288 pub y: f64,
289 pub z: f64,
290}
291
292impl Point3d {
293 pub fn new(x: f64, y: f64, z: f64) -> Self {
295 Self { x, y, z }
296 }
297
298 pub fn origin() -> Self {
300 Self::new(0.0, 0.0, 0.0)
301 }
302
303 pub fn distance_to(&self, other: &Point3d) -> f64 {
305 let dx = self.x - other.x;
306 let dy = self.y - other.y;
307 let dz = self.z - other.z;
308 (dx * dx + dy * dy + dz * dz).sqrt()
309 }
310
311 pub fn dot(&self, other: &Point3d) -> f64 {
313 self.x * other.x + self.y * other.y + self.z * other.z
314 }
315
316 pub fn cross(&self, other: &Point3d) -> Point3d {
318 Point3d::new(
319 self.y * other.z - self.z * other.y,
320 self.z * other.x - self.x * other.z,
321 self.x * other.y - self.y * other.x,
322 )
323 }
324
325 pub fn normalize(&self) -> Point3d {
327 let len = (self.x * self.x + self.y * self.y + self.z * self.z).sqrt();
328 if len > 0.0 {
329 Point3d::new(self.x / len, self.y / len, self.z / len)
330 } else {
331 *self
332 }
333 }
334}
335
336impl Default for Point3d {
337 fn default() -> Self {
338 Self::origin()
339 }
340}
341
342impl fmt::Display for Point3d {
343 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
344 write!(f, "({:.6}, {:.6}, {:.6})", self.x, self.y, self.z)
345 }
346}
347
348impl From<(f64, f64, f64)> for Point3d {
349 fn from((x, y, z): (f64, f64, f64)) -> Self {
350 Self::new(x, y, z)
351 }
352}
353
354impl From<Point3d> for (f64, f64, f64) {
355 fn from(point: Point3d) -> Self {
356 (point.x, point.y, point.z)
357 }
358}
359
360impl From<Point3f> for Point3d {
361 fn from(point: Point3f) -> Self {
362 Self::new(point.x as f64, point.y as f64, point.z as f64)
363 }
364}
365
366#[cfg(test)]
367mod tests {
368 use super::*;
369
370 #[test]
371 fn test_point_creation() {
372 let p = Point::new(10, 20);
373 assert_eq!(p.x, 10);
374 assert_eq!(p.y, 20);
375 }
376
377 #[test]
378 fn test_point_distance() {
379 let p1 = Point::new(0, 0);
380 let p2 = Point::new(3, 4);
381 assert_eq!(p1.distance_to(&p2), 5.0);
382 }
383
384 #[test]
385 fn test_point3d_cross_product() {
386 let p1 = Point3d::new(1.0, 0.0, 0.0);
387 let p2 = Point3d::new(0.0, 1.0, 0.0);
388 let cross = p1.cross(&p2);
389 assert_eq!(cross, Point3d::new(0.0, 0.0, 1.0));
390 }
391}