use crate::graphical::point_2d::Point2D;
use crate::graphical::linear_equation::LinearEquation;
#[derive(Debug, PartialEq)]
pub struct Arc {
pub radius: f64,
pub theta: f64,
}
#[allow(dead_code)]
impl Arc {
pub fn new(radius: f64, theta: f64) -> Arc {
Arc { radius, theta }
}
pub fn calculate_arc_length(&self) -> f64 {
self.radius * self.theta
}
pub fn arc_length(&self) -> f64 {
self.radius * self.theta
}
pub fn from_arc_length_and_radius(arc_length: f64, radius: f64) -> Arc {
let mut theta_guess = arc_length / radius;
let epsilon = 1e-10; let mut theta_prev;
loop {
theta_prev = theta_guess;
let f_theta = radius * theta_prev - arc_length;
let f_prime_theta = radius; theta_guess = theta_prev - f_theta / f_prime_theta;
if (theta_guess - theta_prev).abs() < epsilon {
break;
}
}
Arc {
radius,
theta: theta_guess,
}
}
pub fn from_chord_length_and_radius(chord_length: f64, radius: f64) -> Arc {
let theta = 2.0 * f64::asin(chord_length / (2.0 * radius));
Arc {
radius,
theta,
}
}
pub fn from_endpoints(x1: f64, y1: f64, x2: f64, y2: f64) -> Arc {
let radius = ((x2 - x1).powi(2) + (y2 - y1).powi(2)).sqrt();
let center_x = (x1 + x2) / 2.0;
let center_y = (y1 + y2) / 2.0;
let v1_x = x1 - center_x;
let v1_y = y1 - center_y;
let v2_x = x2 - center_x;
let v2_y = y2 - center_y;
let dot_product = v1_x * v2_x + v1_y * v2_y;
let magnitude_product = (v1_x.powi(2) + v1_y.powi(2)).sqrt() * (v2_x.powi(2) + v2_y.powi(2)).sqrt();
let cos_theta = dot_product / magnitude_product;
let theta = cos_theta.acos();
Arc { radius, theta }
}
pub fn from_area_and_radius(area: f64, radius: f64) -> Arc {
let arc_length = (area * 2.0 / radius).sqrt();
let theta = arc_length / radius;
Arc { radius, theta }
}
pub fn generate_points(&self, num_points: usize) -> Vec<Point2D> {
let mut points = Vec::with_capacity(num_points);
for i in 0..num_points {
let theta_increment = self.theta / (num_points as f64 - 1.0);
let current_theta = i as f64 * theta_increment;
let x = self.radius * current_theta.cos();
let y = self.radius * current_theta.sin();
points.push(Point2D { x, y });
}
points
}
pub fn point_on_arc(&self, angle: f64) -> (f64, f64) {
let x = self.radius * angle.cos();
let y = self.radius * angle.sin();
(x, y)
}
pub fn tangent_at_point(&self, angle: f64) -> LinearEquation {
let (x1, y1) = self.point_on_arc(angle);
let epsilon = 1e-8;
let (x2, y2) = self.point_on_arc(angle + epsilon);
let a = y2 - y1;
let b = x1 - x2;
let c = x2 * y1 - x1 * y2;
LinearEquation { a, b, c }
}
pub fn normal_at_point(&self, angle: f64) -> LinearEquation {
let tangent_slope = -(self.radius * self.theta.sin()) / (self.radius * self.theta.cos());
let normal_slope = -1.0 / tangent_slope;
let (x0, y0) = self.point_on_arc(angle);
let normal_constant = y0 - normal_slope * x0;
LinearEquation {
a: normal_slope,
b: -1.0,
c: normal_constant,
}
}
}