use std::ops::*; use std::f64; #[derive(Debug, Clone, Copy, PartialEq)] pub struct Vec2d { pub x: f64, pub y: f64 } impl Vec2d { pub fn new(x: f64, y: f64) -> Vec2d { Vec2d {x, y} } pub fn distance(&self, other: Vec2d) -> f64 { self.distance_squared(other).sqrt() } pub fn distance_squared(&self, other: Vec2d) -> f64 { ((other.x-self.x).powi(2) + (other.y-self.y).powi(2)) } pub fn magnitude(&self) -> f64 { self.magnitude_squared().sqrt() } pub fn magnitude_squared(&self) -> f64 { self.x.powi(2) + self.y.powi(2) } pub fn angle(&self) -> f64 { self.y.atan2(self.x) } pub fn unit(&self) -> Vec2d { let mag = self.magnitude(); Vec2d { x: self.x / mag, y: self.y / mag } } pub fn dot(&self, other: Vec2d) -> f64 { (self.x * other.x) + (self.y * other.y) } } pub struct LineSegment { pub start: Vec2d, pub end: Vec2d } impl LineSegment { pub fn distance(&self, other: Vec2d) -> f64 { let length_squared = self.start.distance_squared(self.end); if length_squared == 0.0 { return self.start.distance(other); } let t = f64::max(0., f64::min(1., (other - self.start).dot(self.end - self.start) / length_squared)); let projection = self.start + (self.end - self.start) * t; other.distance(projection) } } impl Add for Vec2d { type Output = Vec2d; fn add(self, other: Self) -> Self { Vec2d { x: self.x + other.x, y: self.y + other.y } } } impl Sub for Vec2d { type Output = Vec2d; fn sub(self, other: Self) -> Self { Vec2d { x: self.x - other.x, y: self.y - other.y } } } impl Neg for Vec2d { type Output = Vec2d; fn neg(self) -> Self { Vec2d { x: -self.x, y: -self.y } } } impl Mul for Vec2d { type Output = Vec2d; fn mul(self, rhs: f64) -> Self { Vec2d { x: self.x * rhs, y: self.y * rhs } } }