use altium_format_derive::AltiumRecord;
use super::primitive::PcbPrimitiveCommon;
use crate::types::{Coord, CoordPoint, CoordRect, Layer};
#[derive(Debug, Clone, Default, AltiumRecord)]
#[altium(format = "binary")]
pub struct PcbArc {
#[altium(flatten)]
pub common: PcbPrimitiveCommon,
#[altium(coord_point)]
pub location: CoordPoint,
#[altium(coord)]
pub radius: Coord,
pub start_angle: f64,
pub end_angle: f64,
#[altium(coord)]
pub width: Coord,
}
impl PcbArc {
pub fn new(
center: CoordPoint,
radius: Coord,
start_angle: f64,
end_angle: f64,
width: Coord,
layer: Layer,
) -> Self {
use super::primitive::PcbFlags;
Self {
common: PcbPrimitiveCommon {
layer,
flags: PcbFlags::default(),
unique_id: None,
},
location: center,
radius,
start_angle,
end_angle,
width,
}
}
pub fn circle(center: CoordPoint, radius: Coord, width: Coord, layer: Layer) -> Self {
Self::new(center, radius, 0.0, 360.0, width, layer)
}
pub fn from_mms(
center_x: f64,
center_y: f64,
radius: f64,
start_angle: f64,
end_angle: f64,
width: f64,
layer: Layer,
) -> Self {
Self::new(
CoordPoint::from_mms(center_x, center_y),
Coord::from_mms(radius),
start_angle,
end_angle,
Coord::from_mms(width),
layer,
)
}
pub fn from_mils(
center_x: f64,
center_y: f64,
radius: f64,
start_angle: f64,
end_angle: f64,
width: f64,
layer: Layer,
) -> Self {
Self::new(
CoordPoint::from_mils(center_x, center_y),
Coord::from_mils(radius),
start_angle,
end_angle,
Coord::from_mils(width),
layer,
)
}
pub fn calculate_bounds(&self) -> CoordRect {
let r = self.radius.to_raw();
CoordRect::from_raw(
self.location.x.to_raw() - r,
self.location.y.to_raw() - r,
r * 2,
r * 2,
)
}
pub fn sweep_angle(&self) -> f64 {
let mut sweep = self.end_angle - self.start_angle;
if sweep < 0.0 {
sweep += 360.0;
}
sweep
}
pub fn is_circle(&self) -> bool {
(self.sweep_angle() - 360.0).abs() < 0.001
}
}