Create workspace from previous implementation files
This commit is contained in:
243
kairo-common/src/point.rs
Normal file
243
kairo-common/src/point.rs
Normal file
@@ -0,0 +1,243 @@
|
||||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
ops,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default, PartialEq)]
|
||||
pub struct Point {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
pub fn new(x: f64, y: f64) -> Point {
|
||||
Point { x, y }
|
||||
}
|
||||
pub fn zero() -> Point {
|
||||
Point { x: 0.0, y: 0.0 }
|
||||
}
|
||||
pub fn is_valid(&self) -> bool {
|
||||
!self.x.is_nan() && !self.y.is_nan()
|
||||
}
|
||||
pub fn module(&self) -> f64 {
|
||||
f64::sqrt(self.x * self.x + self.y * self.y)
|
||||
}
|
||||
pub fn phase(&self) -> f64 {
|
||||
f64::atan2(self.y, self.x)
|
||||
}
|
||||
pub fn distance(a: &Point, b: &Point) -> f64 {
|
||||
(a - b).module()
|
||||
}
|
||||
pub fn distance_to(&self, other: &Point) -> f64 {
|
||||
(self - other).module()
|
||||
}
|
||||
pub fn as_versor(&self) -> Option<Point> {
|
||||
if self.x == 0.0 && self.y == 0.0 {
|
||||
None
|
||||
} else {
|
||||
Some(self / self.module())
|
||||
}
|
||||
}
|
||||
pub fn rotate_by(&mut self, α: f64) {
|
||||
let m = self.module();
|
||||
let (sin, cos) = f64::sin_cos(self.phase() + α);
|
||||
self.x = m * cos;
|
||||
self.y = m * sin;
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Point {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
write!(f, "({:.2},{:.2})", &self.x, &self.y)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<Point> for Point {
|
||||
type Output = Point;
|
||||
fn add(self, rhs: Point) -> Point {
|
||||
Point {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::Add<&Point> for &Point {
|
||||
type Output = Point;
|
||||
fn add(self, rhs: &Point) -> Point {
|
||||
Point {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::AddAssign<&Point> for Point {
|
||||
fn add_assign(&mut self, rhs: &Point) {
|
||||
*self = Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
};
|
||||
}
|
||||
}
|
||||
impl ops::AddAssign<Point> for Point {
|
||||
fn add_assign(&mut self, rhs: Point) {
|
||||
*self = Self {
|
||||
x: self.x + rhs.x,
|
||||
y: self.y + rhs.y,
|
||||
};
|
||||
}
|
||||
}
|
||||
impl ops::SubAssign<&Point> for Point {
|
||||
fn sub_assign(&mut self, rhs: &Point) {
|
||||
*self = Self {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
};
|
||||
}
|
||||
}
|
||||
impl ops::SubAssign<Point> for Point {
|
||||
fn sub_assign(&mut self, rhs: Point) {
|
||||
*self = Self {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
};
|
||||
}
|
||||
}
|
||||
impl ops::Sub<Point> for Point {
|
||||
type Output = Point;
|
||||
fn sub(self, rhs: Point) -> Point {
|
||||
Point {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::Sub<&Point> for &Point {
|
||||
type Output = Point;
|
||||
fn sub(self, rhs: &Point) -> Point {
|
||||
Point {
|
||||
x: self.x - rhs.x,
|
||||
y: self.y - rhs.y,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Mul<f64> for Point {
|
||||
type Output = Point;
|
||||
fn mul(self, rhs: f64) -> Point {
|
||||
Point {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::MulAssign<f64> for Point {
|
||||
fn mul_assign(&mut self, rhs: f64) {
|
||||
*self = Point {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::Mul<f64> for &Point {
|
||||
type Output = Point;
|
||||
fn mul(self, rhs: f64) -> Point {
|
||||
Point {
|
||||
x: self.x * rhs,
|
||||
y: self.y * rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::Div<f64> for Point {
|
||||
type Output = Point;
|
||||
fn div(self, rhs: f64) -> Point {
|
||||
Point {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::DivAssign<f64> for Point {
|
||||
fn div_assign(&mut self, rhs: f64) {
|
||||
*self = Point {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl ops::Div<f64> for &Point {
|
||||
type Output = Point;
|
||||
fn div(self, rhs: f64) -> Point {
|
||||
Point {
|
||||
x: self.x / rhs,
|
||||
y: self.y / rhs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
use std::f64::consts::{FRAC_1_SQRT_2, FRAC_PI_2, FRAC_PI_4, SQRT_2};
|
||||
// New
|
||||
let p = Point::new(0.0, 0.0);
|
||||
print!("Testing Point::new()");
|
||||
assert_eq!(p, Point { x: 0.0, y: 0.0 });
|
||||
assert_ne!(p, Point { x: -1.0, y: 1.0 });
|
||||
println!(" ... ok");
|
||||
|
||||
// is_valid
|
||||
let n = Point::new(std::f64::NAN, std::f64::NAN);
|
||||
let nn = Point::new(std::f64::NAN, 0.0);
|
||||
print!("Testing Point::is_valid()");
|
||||
assert_eq!(p.is_valid(), true);
|
||||
assert_eq!(n.is_valid(), false);
|
||||
assert_eq!(nn.is_valid(), false);
|
||||
println!(" ... ok");
|
||||
|
||||
// module
|
||||
let p = Point::new(1.0, 1.0);
|
||||
let r = Point::new(2.0, 0.0);
|
||||
print!("Testing Point::module()");
|
||||
assert!(f64::abs(p.module() - SQRT_2) < 1e-10);
|
||||
assert!(f64::abs(r.module() - 2.0) < 1e-10);
|
||||
println!(" ... ok");
|
||||
|
||||
// phase
|
||||
let p = Point::new(1.0, 1.0);
|
||||
let r = Point::new(2.0, 0.0);
|
||||
let q = Point::new(2.0, -2.0);
|
||||
print!("Testing Point::phase()");
|
||||
assert!(f64::abs(p.phase() - FRAC_PI_4) < 1e-6);
|
||||
assert!(f64::abs(r.phase() - 0.0) < 1e-6);
|
||||
assert!(f64::abs(q.phase() + FRAC_PI_4) < 1e-6);
|
||||
println!(" ... ok");
|
||||
|
||||
//distance
|
||||
let z = Point::zero();
|
||||
let p = Point::new(1.0, 0.0);
|
||||
let q = Point::new(1.0, 1.0);
|
||||
print!("Testing Point::distance() and distance_to()");
|
||||
assert_eq!(z.distance_to(&p), 1.0);
|
||||
assert_eq!(Point::distance(&z, &p), 1.0);
|
||||
assert!(f64::abs(Point::distance(&z, &q) - SQRT_2) < 1e-10);
|
||||
println!(" ... ok");
|
||||
|
||||
//versor
|
||||
print!("Testing Point::as_versor()");
|
||||
assert_eq!(z.as_versor(), None);
|
||||
assert_eq!(p, p.as_versor().unwrap());
|
||||
let q_ver = q.as_versor().unwrap();
|
||||
assert!(f64::abs(q_ver.x - FRAC_1_SQRT_2) < 1e-10);
|
||||
assert!(f64::abs(q_ver.y - FRAC_1_SQRT_2) < 1e-10);
|
||||
println!(" ... ok");
|
||||
|
||||
//rotate_by
|
||||
let mut p = Point::new(1.0, 0.0);
|
||||
print!("Testing Point::rotate_by()");
|
||||
p.rotate_by(FRAC_PI_2);
|
||||
assert!(f64::abs(p.x - 0.0) < 1e-10);
|
||||
assert!(f64::abs(p.y - 1.0) < 1e-10);
|
||||
p.rotate_by(-FRAC_PI_4);
|
||||
assert!(f64::abs(p.x - FRAC_1_SQRT_2) < 1e-10);
|
||||
assert!(f64::abs(p.y - FRAC_1_SQRT_2) < 1e-10);
|
||||
println!(" ... ok");
|
||||
}
|
||||
Reference in New Issue
Block a user