1use std::fmt;
10use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
11
12pub use num_traits::Zero;
13use num_traits::{Float, NumCast};
14
15use crate::point::Point;
16use crate::traits::{MapPointwise, TryCastCoord};
17pub use crate::traits::{Mirror, RotateOrtho};
18pub use crate::types::Angle;
19pub use crate::types::Orientation;
20pub use crate::CoordinateType;
21
22#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
24#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
25pub struct Vector<T> {
26 pub x: T,
28 pub y: T,
30}
31
32#[macro_export]
45macro_rules! vector {
46 ($x:expr, $y:expr) => {
47 Vector::new($x, $y)
48 };
49}
50
51impl<T: Copy> From<Vector<T>> for (T, T) {
52 #[inline]
53 fn from(v: Vector<T>) -> Self {
54 (v.x, v.y)
55 }
56}
57
58impl<T: Copy> From<&Vector<T>> for (T, T) {
59 #[inline]
60 fn from(v: &Vector<T>) -> Self {
61 (v.x, v.y)
62 }
63}
64
65impl<T: Copy> From<(T, T)> for Vector<T> {
66 #[inline]
67 fn from(coords: (T, T)) -> Self {
68 Vector::new(coords.0, coords.1)
69 }
70}
71
72impl<'a, T: Copy> From<&'a (T, T)> for Vector<T> {
73 #[inline]
74 fn from(coords: &'a (T, T)) -> Self {
75 Vector::new(coords.0, coords.1)
76 }
77}
78
79impl<'a, T: Copy> From<&'a Vector<T>> for Vector<T> {
80 #[inline]
81 fn from(v: &'a Vector<T>) -> Self {
82 Vector::new(v.x, v.y)
83 }
84}
85
86impl<T: Copy> From<[T; 2]> for Vector<T> {
87 #[inline]
88 fn from(coords: [T; 2]) -> Self {
89 Vector::new(coords[0], coords[1])
90 }
91}
92
93impl<T> fmt::Debug for Vector<T>
94where
95 T: fmt::Debug,
96{
97 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
98 write!(f, "({:?}, {:?})", &self.x, &self.y)
99 }
100}
101
102impl<T> fmt::Display for Vector<T>
103where
104 T: fmt::Display + Copy,
105{
106 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
107 write!(f, "({}, {})", self.x, self.y)
108 }
109}
110
111impl<T: Zero> Zero for Vector<T> {
112 #[inline]
124 fn zero() -> Self {
125 Vector {
126 x: T::zero(),
127 y: T::zero(),
128 }
129 }
130
131 #[inline]
140 fn is_zero(&self) -> bool {
141 self.x.is_zero() && self.y.is_zero()
142 }
143}
144
145impl<T> Vector<T> {
146 pub fn new(x: T, y: T) -> Self {
155 Vector { x, y }
156 }
157}
158
159impl<T: Copy + Zero + PartialOrd + Sub<Output = T>> Vector<T> {
160 #[inline]
169 pub fn norm1(&self) -> T {
170 let xabs = if self.x < T::zero() {
171 T::zero() - self.x
172 } else {
173 self.x
174 };
175 let yabs = if self.y < T::zero() {
176 T::zero() - self.y
177 } else {
178 self.y
179 };
180 xabs + yabs
181 }
182}
183
184impl<T: Copy + Zero + PartialOrd + Mul<Output = T> + Sub<Output = T>> Vector<T> {
185 pub fn orientation_of(&self, other: Self) -> Orientation {
203 let p = self.cross_prod(other);
204
205 if p < T::zero() {
206 Orientation::ClockWise
207 } else if p > T::zero() {
208 Orientation::CounterClockWise
209 } else {
210 Orientation::Straight
211 }
212 }
213}
214
215impl<T: Copy + Mul<Output = T> + Add<Output = T>> Vector<T> {
216 #[inline]
225 pub fn norm2_squared(&self) -> T {
226 self.x * self.x + self.y * self.y
227 }
228
229 pub fn dot(&self, other: Self) -> T {
242 self.x * other.x + self.y * other.y
243 }
244}
245
246impl<T: Copy + Mul<Output = T> + Sub<Output = T>> Vector<T> {
247 #[inline]
261 pub fn cross_prod(&self, other: Self) -> T {
262 self.x * other.y - other.x * self.y
263 }
264}
265
266impl<T> Vector<T>
267where
268 T: Copy + NumCast,
269{
270 #[inline]
272 pub fn cast_to_float<F>(&self) -> Vector<F>
273 where
274 F: Float + NumCast,
275 {
276 Vector {
278 x: F::from(self.x).unwrap(),
279 y: F::from(self.y).unwrap(),
280 }
281 }
282}
283
284impl<T: Copy + NumCast, Dst: Copy + NumCast> TryCastCoord<T, Dst> for Vector<T> {
285 type Output = Vector<Dst>;
286
287 #[inline]
312 fn try_cast(&self) -> Option<Self::Output> {
313 match (Dst::from(self.x), Dst::from(self.y)) {
314 (Some(x), Some(y)) => Some(Vector::new(x, y)),
315 _ => None,
316 }
317 }
318}
319
320impl<T> Vector<T>
321where
322 T: Copy + Float + Mul<Output = T> + Add<Output = T>,
323{
324 #[inline]
337 pub fn norm2(&self) -> T {
338 (self.norm2_squared()).sqrt()
339 }
340
341 #[inline]
346 pub fn normalized(&self) -> Self {
347 *self / self.norm2()
348 }
349
350 #[inline]
356 pub fn normal(&self) -> Self {
357 self.normalized().rotate_ortho(Angle::R90)
358 }
359}
360
361impl<T: Copy + NumCast> Vector<T> {
362 #[inline]
377 pub fn length<F: Float>(&self) -> F {
378 let x = F::from(self.x).unwrap();
379 let y = F::from(self.y).unwrap();
380
381 x.hypot(y)
382 }
383}
384
385impl<T> Add for Vector<T>
387where
388 T: Add<Output = T>,
389{
390 type Output = Self;
391
392 #[inline]
393 fn add(self, rhs: Self) -> Self {
394 Vector {
395 x: self.x + rhs.x,
396 y: self.y + rhs.y,
397 }
398 }
399}
400
401impl<T> AddAssign for Vector<T>
402where
403 T: AddAssign,
404{
405 #[inline]
406 fn add_assign(&mut self, rhs: Self) {
407 self.x += rhs.x;
408 self.y += rhs.y;
409 }
410}
411
412impl<T> Sub for Vector<T>
414where
415 T: Sub<Output = T>,
416{
417 type Output = Self;
418
419 #[inline]
420 fn sub(self, rhs: Self) -> Self {
421 Vector {
422 x: self.x - rhs.x,
423 y: self.y - rhs.y,
424 }
425 }
426}
427
428impl<T> SubAssign for Vector<T>
429where
430 T: SubAssign,
431{
432 #[inline]
433 fn sub_assign(&mut self, rhs: Self) {
434 self.x -= rhs.x;
435 self.y -= rhs.y;
436 }
437}
438
439impl<T> Neg for Vector<T>
440where
441 T: Neg<Output = T>,
442{
443 type Output = Self;
444
445 #[inline]
446 fn neg(self) -> Self {
447 Vector {
448 x: -self.x,
449 y: -self.y,
450 }
451 }
452}
453
454impl<T, M> Mul<M> for Vector<T>
456where
457 T: Mul<M, Output = T>,
458 M: Copy,
459{
460 type Output = Self;
461
462 fn mul(self, rhs: M) -> Self {
463 Vector {
464 x: self.x * rhs,
465 y: self.y * rhs,
466 }
467 }
468}
469
470impl<T, M> MulAssign<M> for Vector<T>
472where
473 T: Copy + MulAssign<M>,
474 M: Copy,
475{
476 #[inline]
477 fn mul_assign(&mut self, rhs: M) {
478 self.x *= rhs;
479 self.y *= rhs;
480 }
481}
482
483impl<T, D> Div<D> for Vector<T>
485where
486 T: Copy + Div<D, Output = T>,
487 D: Copy,
488{
489 type Output = Self;
490
491 #[inline]
492 fn div(self, rhs: D) -> Self {
493 Vector {
494 x: self.x / rhs,
495 y: self.y / rhs,
496 }
497 }
498}
499
500impl<T, D> DivAssign<D> for Vector<T>
502where
503 T: Copy + DivAssign<D>,
504 D: Copy,
505{
506 #[inline]
507 fn div_assign(&mut self, rhs: D) {
508 self.x /= rhs;
509 self.y /= rhs;
510 }
511}
512
513impl<T> MapPointwise<T> for Vector<T>
514where
515 T: Copy,
516{
517 #[inline]
518 fn transform<F>(&self, transformation: F) -> Self
519 where
520 F: Fn(Point<T>) -> Point<T>,
521 {
522 *transformation(Point::from(self))
523 }
524}
525
526impl<T> std::iter::Sum for Vector<T>
529where
530 T: Zero + Add<Output = T>,
531{
532 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
533 iter.fold(Self::zero(), |acc, v| acc + v)
534 }
535}
536
537#[cfg(test)]
538mod tests {
539 use super::*;
540 use num_rational::Rational64;
541 use num_traits::Zero;
542
543 #[test]
544 fn test_rational_vector() {
545 let _ = Vector::new(Rational64::zero(), Rational64::zero());
546 }
547}