1use crate::Rect;
4
5#[derive(Debug, Clone, Copy, PartialEq)]
7#[repr(C)]
8pub struct Point {
9 pub x: f64,
10 pub y: f64,
11}
12
13impl Point {
14 #[inline]
15 pub const fn new(x: f64, y: f64) -> Self {
16 Self { x, y }
17 }
18
19 #[inline]
21 pub fn rect(self) -> Rect {
22 let r = unsafe { tg_geom_sys::tg_point_rect(self.into()) };
23 r.into()
24 }
25
26 #[inline]
27 pub fn intersects_rect(self, rect: Rect) -> bool {
28 unsafe { tg_geom_sys::tg_point_intersects_rect(self.into(), rect.into()) }
29 }
30}
31
32impl From<tg_geom_sys::tg_point> for Point {
33 #[inline]
34 fn from(p: tg_geom_sys::tg_point) -> Self {
35 Self { x: p.x, y: p.y }
36 }
37}
38
39impl From<Point> for tg_geom_sys::tg_point {
40 #[inline]
41 fn from(p: Point) -> Self {
42 Self { x: p.x, y: p.y }
43 }
44}
45
46impl From<(f64, f64)> for Point {
47 #[inline]
48 fn from((x, y): (f64, f64)) -> Self {
49 Self { x, y }
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 fn p(x: f64, y: f64) -> Point {
58 Point::new(x, y)
59 }
60
61 fn r(min_x: f64, min_y: f64, max_x: f64, max_y: f64) -> Rect {
62 Rect::from_coords(min_x, min_y, max_x, max_y)
63 }
64
65 #[test]
66 fn test_point_rect() {
67 let pt = p(5.0, 5.0);
68 let rect = pt.rect();
69 assert_eq!(rect, r(5.0, 5.0, 5.0, 5.0));
70 }
71
72 #[test]
73 fn test_point_intersects_rect() {
74 assert!(p(5.0, 5.0).intersects_rect(r(5.0, 5.0, 5.0, 5.0)));
75 assert!(p(5.0, 5.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
76 assert!(p(0.0, 0.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
77 assert!(!p(-1.0, 0.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
78 assert!(!p(11.0, 5.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
79 assert!(!p(5.0, 11.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
80 assert!(!p(5.0, -1.0).intersects_rect(r(0.0, 0.0, 10.0, 10.0)));
81 }
82
83 #[test]
84 fn test_point_new() {
85 let pt = Point::new(1.5, 2.5);
86 assert_eq!(pt.x, 1.5);
87 assert_eq!(pt.y, 2.5);
88 }
89
90 #[test]
91 fn test_point_from_tuple() {
92 let pt: Point = (3.0, 4.0).into();
93 assert_eq!(pt.x, 3.0);
94 assert_eq!(pt.y, 4.0);
95 }
96
97 #[test]
98 fn test_point_eq() {
99 assert_eq!(p(1.0, 2.0), p(1.0, 2.0));
100 assert_ne!(p(1.0, 2.0), p(1.0, 3.0));
101 assert_ne!(p(1.0, 2.0), p(2.0, 2.0));
102 }
103
104 #[test]
105 fn test_point_copy() {
106 let pt1 = p(1.0, 2.0);
107 let pt2 = pt1;
108 assert_eq!(pt1, pt2);
109 }
110
111 #[test]
112 fn test_point_negative_coords() {
113 let pt = p(-5.0, -10.0);
114 assert_eq!(pt.x, -5.0);
115 assert_eq!(pt.y, -10.0);
116 let rect = pt.rect();
117 assert_eq!(rect.min.x, -5.0);
118 assert_eq!(rect.min.y, -10.0);
119 }
120
121 #[test]
122 fn test_point_zero() {
123 let pt = p(0.0, 0.0);
124 assert_eq!(pt.rect(), r(0.0, 0.0, 0.0, 0.0));
125 assert!(pt.intersects_rect(r(-1.0, -1.0, 1.0, 1.0)));
126 }
127
128 #[test]
129 fn test_point_sys_roundtrip() {
130 let pt = p(1.5, 2.5);
131 let sys_pt: tg_geom_sys::tg_point = pt.into();
132 let back: Point = sys_pt.into();
133 assert_eq!(pt, back);
134 }
135
136 #[test]
137 fn test_point_debug() {
138 let pt = p(1.0, 2.0);
139 let debug_str = format!("{pt:?}");
140 assert!(debug_str.contains("Point"));
141 assert!(debug_str.contains("1"));
142 assert!(debug_str.contains("2"));
143 }
144}