Skip to main content

tumo_path/geom/
point.rs

1#[allow(unused_imports)]
2use crate::float::Float;
3
4#[repr(C)]
5#[derive(Clone, Copy)]
6pub struct Point {
7	pub x: f32,
8	pub y: f32,
9}
10impl Point {
11	pub const ZERO: Point = Point::zero();
12	pub const ONE: Point = Point::new(1., 1.);
13	pub const AXIS_X: Point = Point::new(1., 0.);
14	pub const AXIS_Y: Point = Point::new(0., 1.);
15	#[inline]
16	pub const fn new(x: f32, y: f32) -> Self {
17		Self { x, y }
18	}
19	#[inline]
20	pub const fn zero() -> Self {
21		Self { x: 0., y: 0. }
22	}
23	#[inline]
24	pub const fn to_array(self) -> [f32; 2] {
25		[self.x, self.y]
26	}
27	#[inline]
28	pub const fn to_tuple(self) -> (f32, f32) {
29		(self.x, self.y)
30	}
31	#[inline]
32	pub fn abs(self) -> Self {
33		Self {
34			x: self.x.abs(),
35			y: self.y.abs(),
36		}
37	}
38	#[inline]
39	pub fn floor(self) -> Self {
40		Self::new(self.x.floor(), self.y.floor())
41	}
42	#[inline]
43	pub fn round(self) -> Self {
44		Self::new(self.x.round(), self.y.round())
45	}
46	#[inline]
47	pub fn ceil(self) -> Self {
48		Self::new(self.x.ceil(), self.y.ceil())
49	}
50	#[inline]
51	pub fn normalize(self) -> Option<Self> {
52		let length = self.length();
53		if length <= f32::EPSILON {
54			return None;
55		}
56		let inverse = 1. / length;
57		Some(Self::new(self.x * inverse, self.y * inverse))
58	}
59	#[inline]
60	pub fn normalized(self) -> Self {
61		self.normalize().unwrap_or_default()
62	}
63	#[inline]
64	pub fn lerp(self, other: Self, t: f32) -> Self {
65		Point {
66			x: self.x * (1.0 - t) + other.x * t,
67			y: self.y * (1.0 - t) + other.y * t,
68		}
69	}
70	#[inline]
71	pub fn length_squared(self) -> f32 {
72		self.x * self.x + self.y * self.y
73	}
74	#[inline]
75	pub fn length(self) -> f32 {
76		self.length_squared().sqrt()
77	}
78	#[inline]
79	pub fn area(self) -> f32 {
80		self.x * self.y
81	}
82	#[inline]
83	pub fn dot(self, to: Self) -> f32 {
84		self.x * to.x + self.y * to.y
85	}
86	#[inline]
87	pub fn cross(self, to: Self) -> f32 {
88		self.x * to.y - self.y * to.x
89	}
90	#[inline]
91	pub fn distance_squared(self, to: Point) -> f32 {
92		(self - to).length_squared()
93	}
94	#[inline]
95	pub fn distance(self, to: Point) -> f32 {
96		self.distance_squared(to).sqrt()
97	}
98	#[inline]
99	pub fn normal(self) -> Point {
100		Point::new(self.y, -self.x)
101	}
102	#[inline]
103	pub fn normal_to(self, to: Point) -> Point {
104		(to - self).normal()
105	}
106	#[inline]
107	pub fn nearly(self, to: Point, epsilon: f32) -> bool {
108		(self.x - to.x).abs() < epsilon && (self.y - to.y).abs() < epsilon
109	}
110	// Calculate the angle (in radians) of the vector from origin to this point
111	#[inline]
112	pub fn angle(self) -> f32 {
113		self.y.atan2(self.x)
114	}
115}
116impl Default for Point {
117	#[inline]
118	fn default() -> Self {
119		Self::zero()
120	}
121}
122impl core::fmt::Debug for Point {
123	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
124		f.debug_tuple("Point").field(&self.x).field(&self.y).finish()
125	}
126}
127impl PartialEq<Point> for Point {
128	fn eq(&self, other: &Point) -> bool {
129		(self.x - other.x).abs() < f32::EPSILON && (self.y - other.y).abs() < f32::EPSILON
130	}
131}
132impl PartialOrd<Point> for Point {
133	fn partial_cmp(&self, other: &Point) -> Option<core::cmp::Ordering> {
134		if self.eq(other) {
135			Some(core::cmp::Ordering::Equal)
136		} else {
137			self.x.partial_cmp(&other.x).and_then(|x| {
138				if x != core::cmp::Ordering::Equal {
139					return Some(x);
140				}
141				self.y.partial_cmp(&other.y)
142			})
143		}
144	}
145}
146impl core::hash::Hash for Point {
147	fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
148		state.write_i32((self.x * 1000.) as _);
149		state.write_i32((self.y * 1000.) as _);
150	}
151}
152
153impl core::ops::Mul<f32> for Point {
154	type Output = Point;
155	#[inline]
156	fn mul(self, scale: f32) -> Self::Output {
157		Point::new(self.x * scale, self.y * scale)
158	}
159}
160impl core::ops::Mul<Point> for Point {
161	type Output = Point;
162	fn mul(self, rhs: Point) -> Self::Output {
163		Point::new(self.x * rhs.x, self.y * rhs.y)
164	}
165}
166impl core::ops::Div<f32> for Point {
167	type Output = Point;
168	#[inline]
169	fn div(self, rhs: f32) -> Self::Output {
170		Point::new(self.x / rhs, self.y / rhs)
171	}
172}
173impl core::ops::Div for Point {
174	type Output = Self;
175	#[inline]
176	fn div(self, rhs: Self) -> Self {
177		Self::new(self.x / rhs.x, self.y / rhs.y)
178	}
179}
180impl core::ops::Add for Point {
181	type Output = Point;
182	#[inline]
183	fn add(self, other: Point) -> Self::Output {
184		Point::new(self.x + other.x, self.y + other.y)
185	}
186}
187impl core::ops::Sub for Point {
188	type Output = Point;
189	#[inline]
190	fn sub(self, other: Self) -> Self::Output {
191		Point::new(self.x - other.x, self.y - other.y)
192	}
193}
194impl core::ops::Neg for Point {
195	type Output = Point;
196	#[inline]
197	fn neg(self) -> Self::Output {
198		Point::new(-self.x, -self.y)
199	}
200}
201
202impl From<(f32, f32)> for Point {
203	#[inline]
204	fn from(value: (f32, f32)) -> Self {
205		Self::new(value.0, value.1)
206	}
207}
208impl From<[f32; 2]> for Point {
209	fn from(v: [f32; 2]) -> Self {
210		Self::new(v[0], v[1])
211	}
212}
213impl From<(i32, i32)> for Point {
214	fn from(v: (i32, i32)) -> Self {
215		Self::new(v.0 as f32, v.1 as f32)
216	}
217}
218impl From<[i32; 2]> for Point {
219	fn from(v: [i32; 2]) -> Self {
220		Self::new(v[0] as f32, v[1] as f32)
221	}
222}
223impl From<(f32, i32)> for Point {
224	fn from(v: (f32, i32)) -> Self {
225		Self::new(v.0, v.1 as f32)
226	}
227}
228impl From<(i32, f32)> for Point {
229	fn from(v: (i32, f32)) -> Self {
230		Self::new(v.0 as f32, v.1)
231	}
232}
233impl From<f32> for Point {
234	fn from(x: f32) -> Self {
235		Self::new(x, x)
236	}
237}
238impl From<i32> for Point {
239	fn from(x: i32) -> Self {
240		let x = x as f32;
241		Self::new(x, x)
242	}
243}
244impl From<Point> for [f32; 2] {
245	fn from(v: Point) -> Self {
246		[v.x, v.y]
247	}
248}
249impl From<Point> for (f32, f32) {
250	fn from(v: Point) -> Self {
251		(v.x, v.y)
252	}
253}