use crate::points::{Point2, Points2, PolarPoint};
use serde_derive::{Deserialize, Serialize};
#[derive(Debug, Copy, Clone, PartialEq, Deserialize, Serialize)]
pub enum Angle {
Degrees(f64),
Radians(f64),
}
impl Angle {
pub fn to_degrees(self) -> f64 {
match self {
Angle::Radians(val) => val.to_degrees(),
Angle::Degrees(val) => val,
}
}
pub fn to_radians(self) -> f64 {
match self {
Angle::Degrees(val) => val.to_radians(),
Angle::Radians(val) => val,
}
}
}
pub fn cart2pol(point: &Point2) -> PolarPoint {
let rho = point.magnitude();
let phi = point.y.atan2(point.x);
PolarPoint::new(rho, phi)
}
pub fn pol2cart(point: &PolarPoint) -> Point2 {
let x = point.rho * point.phi.cos();
let y = point.rho * point.phi.sin();
Point2 { x, y }
}
pub fn vector_pol2cart(vector: &PolarPoint, phi: &f64) -> Point2 {
let cos_phi = phi.cos();
let sin_phi = phi.sin();
let vector_x = vector.rho * cos_phi - vector.phi * sin_phi;
let vector_y = vector.rho * sin_phi + vector.phi * cos_phi;
Point2 {
x: vector_x,
y: vector_y,
}
}
pub fn rotate_around_pivot(&point: &Point2, phi: &f64, pivot: &Point2) -> Point2 {
let cos_val = phi.cos();
let sin_val = phi.sin();
let x = point.x - pivot.x;
let y = point.y - pivot.y;
let x_rot = (x * cos_val - y * sin_val) + pivot.x;
let y_rot = (x * sin_val + y * cos_val) + pivot.y;
Point2 { x: x_rot, y: y_rot }
}
pub fn rotate_around_origin(&point: &Point2, phi: &f64) -> Point2 {
let cos_val = phi.cos();
let sin_val = phi.sin();
let x = point.x;
let y = point.y;
let x_rot = x * cos_val - y * sin_val;
let y_rot = x * sin_val + y * cos_val;
Point2 { x: x_rot, y: y_rot }
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{utils::comparison::nearly_equal, PI, PI_2, PI_4};
#[test]
fn test_degrees_to_radians() {
let angle = Angle::Degrees(90.0);
assert!(nearly_equal(angle.to_radians(), PI_2));
}
#[test]
fn test_degrees_to_degrees() {
let angle = Angle::Degrees(32.0);
assert!(nearly_equal(angle.to_degrees(), 32.0));
}
#[test]
fn test_radians_to_degrees() {
let angle = Angle::Radians(PI);
assert!(nearly_equal(angle.to_degrees(), 180.0));
}
#[test]
fn test_radians_to_radians() {
let angle = Angle::Radians(PI_4);
assert!(nearly_equal(angle.to_radians(), PI_4));
}
}