Create workspace from previous implementation files

This commit is contained in:
2023-05-21 13:52:18 +02:00
parent b84f46ed57
commit a5976252e8
23 changed files with 1374 additions and 15 deletions

243
kairo-common/src/point.rs Normal file
View 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");
}