use crate::gerber::coordinates::Coord;
pub(super) fn required(value: Option<f64>, name: &str) -> Result<f64, String> {
match value {
Some(v) if v.is_finite() => Ok(v),
Some(v) => Err(format!("{name} is not finite ({v})")),
None => Err(format!("missing {name}")),
}
}
pub(super) fn finite_or(value: Option<f64>, default: f64, name: &str) -> Result<f64, String> {
value.map_or(Ok(default), |v| required(Some(v), name))
}
pub(super) fn quarter_turns(rot: f64) -> Option<u8> {
let q = rot / 90.0;
let r = q.round();
((q - r).abs() < 1e-9).then(|| r.rem_euclid(4.0) as u8)
}
pub(super) fn rotate([x, y]: [f64; 2], deg: f64) -> [f64; 2] {
let (s, c) = deg.to_radians().sin_cos();
[x * c - y * s, x * s + y * c]
}
pub(super) fn add(a: [f64; 2], b: [f64; 2]) -> [f64; 2] {
[a[0] + b[0], a[1] + b[1]]
}
pub(super) fn long_axis(w: f64, h: f64, rot: f64, at: [f64; 2]) -> ([f64; 2], [f64; 2]) {
let half = (w.max(h) - w.min(h)) / 2.0;
let axis = if w >= h { [half, 0.0] } else { [0.0, half] };
let [dx, dy] = rotate(axis, rot);
([at[0] - dx, at[1] - dy], [at[0] + dx, at[1] + dy])
}
pub(super) fn coord([x, y]: [f64; 2]) -> [Coord; 2] {
[Coord::from_mm(x), Coord::from_mm(y)]
}