1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
|
use crate::geometry::vec::*;
use std::ops::*;
use num_traits::{NumOps, NumAssignOps};
use num_traits::pow::Pow;
use num_traits::real::Real;
macro_rules! impl_point {
($PointN:ident { $($field:ident),+ }, $VecN:ident) => {
#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
pub struct $PointN<T> {
$(pub $field: T),+
}
impl<T> $PointN<T> {
pub fn new($($field: T),+) -> $PointN<T> {
$PointN { $($field),+ }
}
}
impl<T: NumOps + Pow<u8, Output=T> + Copy> $PointN<T> {
pub fn distance_squared(self, other: $PointN<T>) -> T {
(self - other).magnitude_squared()
}
}
impl<T: Real + Pow<u8, Output=T>> $PointN<T> {
pub fn distance(self, other: $PointN<T>) -> T {
(self - other).magnitude()
}
}
impl<T: NumOps> Add<$VecN<T>> for $PointN<T> {
type Output = Self;
fn add(self, other: $VecN<T>) -> Self {
$PointN {
$($field: self.$field + other.$field),+
}
}
}
impl<T: NumAssignOps> AddAssign<$VecN<T>> for $PointN<T> {
fn add_assign(&mut self, other: $VecN<T>) {
$(self.$field += other.$field);+
}
}
impl<T: NumOps> Sub for $PointN<T> {
type Output = $VecN<T>;
fn sub(self, other: Self) -> $VecN<T> {
$VecN {
$($field: self.$field - other.$field),+
}
}
}
}
}
impl_point!(Point2d { x, y }, Vec2d);
impl_point!(Point3d { x, y, z }, Vec3d);
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn distance_in_x_dimension_example() {
let a = Point2d::new(1., 1.);
let b = Point2d::new(3., 1.);
assert_eq!(a.distance(b), 2.);
assert_eq!(a.distance_squared(b), 4.);
}
#[test]
fn distance_in_y_dimension_example() {
let a = Point2d::new(1., 1.);
let b = Point2d::new(1., 3.);
assert_eq!(b.distance(a), 2.);
assert_eq!(b.distance_squared(a), 4.);
}
}
|