1use std::{f32::consts::PI, iter::Sum};
2
3use geo_types::Coord;
4use mint::Point2;
5use serde::{Deserialize, Serialize};
6
7use crate::{rand_range, Angle, Rect, Rotate, Rotate90, SampleSettings};
8
9use super::v2i::V2i;
10
11#[derive(Debug, Copy, Clone, Default, Serialize, Deserialize)]
12pub struct V2 {
13 pub x: f32,
14 pub y: f32,
15}
16
17impl V2 {
18 pub fn xy(x_and_y: f32) -> Self {
19 Self {
20 x: x_and_y,
21 y: x_and_y,
22 }
23 }
24
25 pub fn new(x: f32, y: f32) -> Self {
26 Self { x, y }
27 }
28 pub fn new_from_geo(geo_coord: &Coord<f32>) -> Self {
29 Self {
30 x: geo_coord.x,
31 y: geo_coord.y,
32 }
33 }
34 pub fn polar(angle: Angle, distance: f32) -> Self {
35 Self {
36 x: angle.to_rad().cos() * distance,
37 y: angle.to_rad().sin() * distance,
38 }
39 }
40 pub fn zero() -> Self {
41 Self { x: 0.0, y: 0.0 }
42 }
43 pub fn up() -> Self {
44 Self { x: 0.0, y: 1.0 }
45 }
46 pub fn right() -> Self {
47 Self { x: 1.0, y: 0.0 }
48 }
49 pub fn down() -> Self {
50 Self { x: 0.0, y: -1.0 }
51 }
52 pub fn left() -> Self {
53 Self { x: 0.0, y: -1.0 }
54 }
55
56 pub fn random_unit_circle() -> Self {
57 Self::polar(Angle::rand(), 1.0)
58 }
59 pub fn random_unit_disk() -> Self {
60 let angle = Angle::rand();
61 let radius = rand_range(0.0, 1.0).sqrt();
62 Self::polar(angle, radius)
63 }
64 pub fn random_in_rect(rect: &Rect) -> Self {
65 Self::new(
66 rand_range(rect.bl().x, rect.tr().x),
67 rand_range(rect.bl().y, rect.tr().y),
68 )
69 }
70
71 pub fn din_a(number: u8) -> Self {
72 match number {
73 0 => Self::a0(),
74 1 => Self::a1(),
75 2 => Self::a2(),
76 3 => Self::a3(),
77 4 => Self::a4(),
78 5 => Self::a5(),
79 6 => Self::a6(),
80 7 => Self::a7(),
81 8 => Self::a8(),
82 9 => Self::a9(),
83 10 => Self::a10(),
84 _ => panic!("DIN A number out of range."),
85 }
86 }
87 pub fn a0() -> Self {
88 Self { x: 84.1, y: 118.9 }
89 }
90 pub fn a1() -> Self {
91 Self { x: 59.4, y: 84.1 }
92 }
93 pub fn a2() -> Self {
94 Self { x: 42.0, y: 59.4 }
95 }
96 pub fn a3() -> Self {
97 Self { x: 29.7, y: 42.0 }
98 }
99 pub fn a4() -> Self {
100 Self { x: 21.0, y: 29.7 }
101 }
102 pub fn a5() -> Self {
103 Self { x: 14.8, y: 21.0 }
104 }
105 pub fn a6() -> Self {
106 Self { x: 10.5, y: 14.8 }
107 }
108 pub fn a7() -> Self {
109 Self { x: 7.4, y: 10.5 }
110 }
111 pub fn a8() -> Self {
112 Self { x: 5.2, y: 7.4 }
113 }
114 pub fn a9() -> Self {
115 Self { x: 3.7, y: 5.2 }
116 }
117 pub fn a10() -> Self {
118 Self { x: 2.6, y: 3.7 }
119 }
120
121 pub fn swap(&self) -> Self {
122 Self {
123 x: self.y,
124 y: self.x,
125 }
126 }
127
128 pub fn only_x(&self) -> Self {
129 Self { x: self.x, y: 0.0 }
130 }
131 pub fn only_y(&self) -> Self {
132 Self { x: 0.0, y: self.y }
133 }
134
135 pub fn as_geo_coord(&self) -> Coord<f32> {
136 Coord {
137 x: self.x,
138 y: self.y,
139 }
140 }
141 pub fn as_tuple(&self) -> (f32, f32) {
142 (self.x, self.y)
143 }
144 pub fn as_array(&self) -> [f32; 2] {
145 [self.x, self.y]
146 }
147 pub fn as_vec(&self) -> Vec<f32> {
148 vec![self.x, self.y]
149 }
150
151 pub fn round(&self) -> Self {
152 Self {
153 x: self.x.round(),
154 y: self.y.round(),
155 }
156 }
157 pub fn round_to_int(&self) -> V2i {
158 V2i::new(self.x.round() as i32, self.y.round() as i32)
159 }
160
161 pub fn ceil(&self) -> Self {
162 Self {
163 x: self.x.ceil(),
164 y: self.y.ceil(),
165 }
166 }
167 pub fn ceil_to_int(&self) -> V2i {
168 V2i::new(self.x.ceil() as i32, self.y.ceil() as i32)
169 }
170
171 pub fn floor(&self) -> Self {
172 Self {
173 x: self.x.floor(),
174 y: self.y.floor(),
175 }
176 }
177 pub fn floor_to_int(&self) -> V2i {
178 V2i::new(self.x.floor() as i32, self.y.floor() as i32)
179 }
180
181 pub fn dot(&self, other: &Self) -> f32 {
182 self.x * other.x + self.y * other.y
183 }
184
185 pub fn min(&self, other: &Self) -> Self {
186 V2::new(self.x.min(other.x), self.y.min(other.y))
187 }
188 pub fn min_axis(&self) -> f32 {
189 self.x.min(self.y)
190 }
191 pub fn max(&self, other: &Self) -> Self {
192 V2::new(self.x.max(other.x), self.y.max(other.y))
193 }
194 pub fn max_axis(&self) -> f32 {
195 self.x.max(self.y)
196 }
197
198 pub fn dist(&self, other: &Self) -> f32 {
199 ((self.x - other.x).powi(2) + (self.y - other.y).powi(2)).sqrt()
200 }
201 pub fn dist_squared(&self, other: &Self) -> f32 {
202 (self.x - other.x).powi(2) + (self.y - other.y).powi(2)
203 }
204 pub fn dist_manhattan(&self, other: &Self) -> f32 {
205 (self.x - other.x).abs() + (self.y - other.y).abs()
206 }
207
208 pub fn len(&self) -> f32 {
209 (self.x * self.x + self.y * self.y).sqrt()
210 }
211 pub fn len_squared(&self) -> f32 {
212 self.x * self.x + self.y * self.y
213 }
214
215 pub fn angle(&self) -> Angle {
216 let mut rad = self.y.atan2(self.x);
217 if rad < 0.0 {
218 rad += 2.0 * PI;
219 }
220 Angle::from_rad(rad)
221 }
222 pub fn angle_to(&self, other: &Self) -> Angle {
223 (other - self).angle()
224 }
225
226 pub fn normalize(&self) -> Self {
227 let len = self.len();
228 if len == 0.0 {
229 *self
230 } else {
231 *self / len
232 }
233 }
234 pub fn normalize_to(&self, len: f32) -> Self {
235 *self * len / self.len()
236 }
237
238 pub fn project_onto(&self, other: &Self) -> Self {
240 let length_squared = other.len_squared();
241 let dot_product = self.dot(other);
242 V2::new(
243 (dot_product / length_squared) * other.x,
244 (dot_product / length_squared) * other.y,
245 )
246 }
247
248 pub fn clamp_len(&self, min_len: f32, max_len: f32) -> Self {
249 let len = self.len();
250 if len < min_len {
251 *self * (min_len / len)
252 } else if len > max_len {
253 *self * (max_len / len)
254 } else {
255 *self
256 }
257 }
258
259 pub fn map(&self, f: fn(f32) -> f32) -> Self {
260 V2::new(f(self.x), f(self.y))
261 }
262
263 pub fn sqrt(&self) -> Self {
264 V2::new(self.x.sqrt(), self.y.sqrt())
265 }
266
267 pub fn lerp(&self, other: &Self, t: f32) -> Self {
268 V2::new(
269 self.x + t * (other.x - self.x),
270 self.y + t * (other.y - self.y),
271 )
272 }
273 pub fn lerp_iter_fixed(&self, end: V2, steps: usize) -> V2Interpolator {
274 V2Interpolator::new(*self, end, steps)
275 }
276 pub fn lerp_iter(&self, end: V2, sample_settings: &SampleSettings) -> V2Interpolator {
277 let distance = self.dist(&end);
278 V2Interpolator::new(
279 *self,
280 end,
281 sample_settings.get_num_points_for_length(distance) as usize,
282 )
283 }
284}
285
286pub struct V2Interpolator {
287 start: V2,
288 end: V2,
289 steps: usize,
290 current_step: usize,
291}
292
293impl V2Interpolator {
294 pub fn new(start: V2, end: V2, steps: usize) -> Self {
295 Self {
296 start,
297 end,
298 steps,
299 current_step: 0,
300 }
301 }
302}
303
304impl Iterator for V2Interpolator {
305 type Item = V2;
306
307 fn next(&mut self) -> Option<Self::Item> {
308 if self.current_step > self.steps {
309 return None;
310 }
311 let t = self.current_step as f32 / self.steps as f32;
312 let interpolated = self.start.lerp(&self.end, t);
313 self.current_step += 1;
314 Some(interpolated)
315 }
316}
317
318impl Rotate for V2 {
319 fn rotate(&self, angle: &Angle) -> Self {
320 let angle = angle.to_rad();
321 let angle_sin = angle.sin();
322 let angle_cos = angle.cos();
323 Self::new(
324 self.x * angle_cos - self.y * angle_sin,
325 self.x * angle_sin + self.y * angle_cos,
326 )
327 }
328 fn rotate_mut(&mut self, angle: &Angle) {
329 *self = self.rotate(angle);
330 }
331
332 fn rotate_around(&self, pivot: &V2, angle: &Angle) -> Self {
333 let angle = angle.to_rad();
334 let angle_sin = angle.sin();
335 let angle_cos = angle.cos();
336
337 let x_offset = self.x - pivot.x;
338 let y_offset = self.y - pivot.y;
339
340 Self::new(
341 (x_offset * angle_cos - y_offset * angle_sin) + pivot.x,
342 (x_offset * angle_sin + y_offset * angle_cos) + pivot.y,
343 )
344 }
345 fn rotate_around_mut(&mut self, pivot: &V2, angle: &Angle) {
346 *self = self.rotate_around(pivot, angle);
347 }
348}
349
350impl Rotate90 for V2 {
351 fn rotate_90(&self) -> Self {
352 Self::new(-self.y, self.x)
353 }
354 fn rotate_90_mut(&mut self) {
355 *self = self.rotate_90();
356 }
357
358 fn rotate_180(&self) -> Self {
359 Self::new(-self.x, -self.y)
360 }
361 fn rotate_180_mut(&mut self) {
362 *self = self.rotate_180();
363 }
364
365 fn rotate_270(&self) -> Self {
366 Self::new(self.y, -self.x)
367 }
368 fn rotate_270_mut(&mut self) {
369 *self = self.rotate_270();
370 }
371
372 fn rotate_90_around(&self, pivot: &V2) -> Self {
373 Self::new(-self.y + pivot.y + pivot.x, self.x - pivot.x + pivot.y)
374 }
375 fn rotate_90_around_mut(&mut self, pivot: &V2) {
376 *self = self.rotate_90_around(pivot);
377 }
378
379 fn rotate_180_around(&self, pivot: &V2) -> Self {
380 Self::new(pivot.x * 2.0 - self.x, pivot.y * 2.0 - self.y)
381 }
382 fn rotate_180_around_mut(&mut self, pivot: &V2) {
383 *self = self.rotate_180_around(pivot);
384 }
385
386 fn rotate_270_around(&self, pivot: &V2) -> Self {
387 Self::new(self.y - pivot.y + pivot.x, -self.x + pivot.x + pivot.y)
388 }
389 fn rotate_270_around_mut(&mut self, pivot: &V2) {
390 *self = self.rotate_270_around(pivot);
391 }
392}
393
394impl Sum for V2 {
395 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
396 iter.fold(V2::zero(), |a, b| a + b)
397 }
398}
399
400impl From<Point2<f32>> for V2 {
401 fn from(point: Point2<f32>) -> Self {
402 Self::new(point.x, point.y)
403 }
404}
405
406impl From<V2> for Point2<f32> {
407 fn from(v2: V2) -> Self {
408 Point2 { x: v2.x, y: v2.y }
409 }
410}
411
412impl From<&V2> for Point2<f32> {
413 fn from(v2: &V2) -> Self {
414 Point2 { x: v2.x, y: v2.y }
415 }
416}
417
418impl From<&Point2<f32>> for V2 {
419 fn from(point: &Point2<f32>) -> Self {
420 Self::new(point.x, point.y)
421 }
422}