use num_traits::Float;
use crate::bezier::Cubic;
use crate::goodness::Goodness;
pub struct CrudeIndependentAbsolute<T: Float> {
absolute_distance: T,
relative_distance: T,
subdivision: usize,
index: usize,
}
impl<T: Float> CrudeIndependentAbsolute<T> {
#[inline]
pub fn new(absolute_distance: T, relative_distance: T, subdivision: usize) -> Self {
Self {
absolute_distance,
relative_distance,
subdivision,
index: 0,
}
}
}
impl<T: Float> Goodness<Cubic<T>> for CrudeIndependentAbsolute<T> {
fn admit(&mut self, candidate: &Cubic<T>, original: &Cubic<T>) -> Option<bool> {
let size = (original.0[0] - original.0[3]).abs();
let distance = self.absolute_distance.min(self.relative_distance * size);
if admit(candidate.0, original.0, distance) {
return Some(true);
}
if self.index < self.subdivision {
self.index += 1;
return Some(false);
}
None
}
}
impl<T: Float> Goodness<(Cubic<T>, Cubic<T>)> for CrudeIndependentAbsolute<T> {
fn admit(
&mut self,
candidate: &(Cubic<T>, Cubic<T>),
original: &(Cubic<T>, Cubic<T>),
) -> Option<bool> {
let size = {
let width = (original.0[0] - original.0[3]).abs();
let height = (original.1[0] - original.1[3]).abs();
width.max(height)
};
let distance = self.absolute_distance.min(self.relative_distance * size);
if admit(candidate.0 .0, original.0 .0, distance)
&& admit(candidate.1 .0, original.1 .0, distance)
{
return Some(true);
}
if self.index < self.subdivision {
self.index += 1;
return Some(false);
}
None
}
}
#[rustfmt::skip]
fn admit<T: Float>(one: [T; 4], other: [T; 4], distance: T) -> bool {
(one[0] - other[0]).abs() <= distance &&
(one[1] - other[1]).abs() <= distance &&
(one[2] - other[2]).abs() <= distance &&
(one[3] - other[3]).abs() <= distance
}