use crate::vector::{Vector2, Vector3};
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Point2 {
pub x: f64,
pub y: f64,
}
impl Point2 {
pub const ORIGIN: Point2 = Point2 { x: 0.0, y: 0.0 };
pub const fn new(x: f64, y: f64) -> Point2 {
Point2 { x, y }
}
pub fn distance(self, other: Point2) -> f64 {
let dx = other.x - self.x;
let dy = other.y - self.y;
(dx * dx + dy * dy).sqrt()
}
}
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Point3 {
pub x: f64,
pub y: f64,
pub z: f64,
}
impl Point3 {
pub const ORIGIN: Point3 = Point3 {
x: 0.0,
y: 0.0,
z: 0.0,
};
pub const fn new(x: f64, y: f64, z: f64) -> Point3 {
Point3 { x, y, z }
}
pub fn distance(self, other: Point3) -> f64 {
let dx = other.x - self.x;
let dy = other.y - self.y;
let dz = other.z - self.z;
(dx * dx + dy * dy + dz * dz).sqrt()
}
}
impl std::ops::Add<Vector3> for Point3 {
type Output = Point3;
fn add(self, vector: Vector3) -> Point3 {
Point3 {
x: self.x + vector.x,
y: self.y + vector.y,
z: self.z + vector.z,
}
}
}
impl std::ops::Sub<Vector3> for Point3 {
type Output = Point3;
fn sub(self, vector: Vector3) -> Point3 {
Point3 {
x: self.x - vector.x,
y: self.y - vector.y,
z: self.z - vector.z,
}
}
}
impl std::ops::Sub for Point3 {
type Output = Vector3;
fn sub(self, other: Point3) -> Vector3 {
Vector3 {
x: self.x - other.x,
y: self.y - other.y,
z: self.z - other.z,
}
}
}
impl std::ops::Add<Vector2> for Point2 {
type Output = Point2;
fn add(self, vector: Vector2) -> Point2 {
Point2 {
x: self.x + vector.x,
y: self.y + vector.y,
}
}
}
impl std::ops::Sub<Vector2> for Point2 {
type Output = Point2;
fn sub(self, vector: Vector2) -> Point2 {
Point2 {
x: self.x - vector.x,
y: self.y - vector.y,
}
}
}
impl std::ops::Sub for Point2 {
type Output = Vector2;
fn sub(self, other: Point2) -> Vector2 {
Vector2 {
x: self.x - other.x,
y: self.y - other.y,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_point3_origin() {
assert_eq!(Point3::ORIGIN, Point3::new(0.0, 0.0, 0.0));
}
#[test]
fn test_point3_new() {
let p = Point3::new(1.0, 2.0, 3.0);
assert_eq!(p.x, 1.0);
assert_eq!(p.y, 2.0);
assert_eq!(p.z, 3.0);
}
#[test]
fn test_point3_distance() {
let p1 = Point3::new(1.0, 2.0, 3.0);
let p2 = Point3::new(4.0, 6.0, 3.0);
assert_eq!(p1.distance(p2), 5.0);
}
#[test]
fn test_point3_add_vector() {
let p = Point3::new(1.0, 2.0, 3.0);
let v = Vector3::new(4.0, 5.0, 6.0);
assert_eq!(p + v, Point3::new(5.0, 7.0, 9.0));
}
#[test]
fn test_point3_sub_vector() {
let p = Point3::new(5.0, 7.0, 9.0);
let v = Vector3::new(4.0, 5.0, 6.0);
assert_eq!(p - v, Point3::new(1.0, 2.0, 3.0));
}
#[test]
fn test_point3_sub_point() {
let p1 = Point3::new(4.0, 6.0, 8.0);
let p2 = Point3::new(1.0, 2.0, 3.0);
assert_eq!(p1 - p2, Vector3::new(3.0, 4.0, 5.0));
}
#[test]
fn test_point3_op_identity() {
let p = Point3::new(1.0, 2.0, 3.0);
let q = Point3::new(4.0, 5.0, 6.0);
let diff = q - p;
assert_eq!(p + diff, q);
}
#[test]
fn test_point2_origin() {
assert_eq!(Point2::ORIGIN, Point2::new(0.0, 0.0));
}
#[test]
fn test_point2_new() {
let p = Point2::new(1.0, 2.0);
assert_eq!(p.x, 1.0);
assert_eq!(p.y, 2.0);
}
#[test]
fn test_point2_distance() {
let p1 = Point2::new(0.0, 0.0);
let p2 = Point2::new(3.0, 4.0);
assert_eq!(p1.distance(p2), 5.0);
}
#[test]
fn test_point2_add_vector() {
let p = Point2::new(1.0, 2.0);
let v = Vector2::new(3.0, 4.0);
assert_eq!(p + v, Point2::new(4.0, 6.0));
}
#[test]
fn test_point2_sub_vector() {
let p = Point2::new(4.0, 6.0);
let v = Vector2::new(1.0, 2.0);
assert_eq!(p - v, Point2::new(3.0, 4.0));
}
#[test]
fn test_point2_sub_point() {
let p1 = Point2::new(4.0, 6.0);
let p2 = Point2::new(1.0, 2.0);
assert_eq!(p1 - p2, Vector2::new(3.0, 4.0));
}
#[test]
fn test_point2_op_identity() {
let p = Point2::new(1.0, 2.0);
let q = Point2::new(4.0, 6.0);
let diff = q - p;
assert_eq!(p + diff, q);
}
}