use app_units::Au;
use euclid::default::Size2D;
use std::iter::Sum;
use std::ops::Add;
pub trait ComputeSquaredDistance {
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()>;
}
#[derive(Add, Clone, Copy, Debug, From)]
pub struct SquaredDistance {
value: f64,
}
impl SquaredDistance {
#[inline]
pub fn from_sqrt(sqrt: f64) -> Self {
Self { value: sqrt * sqrt }
}
}
impl ComputeSquaredDistance for u16 {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
Ok(SquaredDistance::from_sqrt(
((*self as f64) - (*other as f64)).abs(),
))
}
}
impl ComputeSquaredDistance for i16 {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
Ok(SquaredDistance::from_sqrt((*self - *other).abs() as f64))
}
}
impl ComputeSquaredDistance for i32 {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
Ok(SquaredDistance::from_sqrt((*self - *other).abs() as f64))
}
}
impl ComputeSquaredDistance for f32 {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
Ok(SquaredDistance::from_sqrt((*self - *other).abs() as f64))
}
}
impl ComputeSquaredDistance for f64 {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
Ok(SquaredDistance::from_sqrt((*self - *other).abs()))
}
}
impl ComputeSquaredDistance for Au {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
self.0.compute_squared_distance(&other.0)
}
}
impl<T> ComputeSquaredDistance for Box<T>
where
T: ComputeSquaredDistance,
{
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
(**self).compute_squared_distance(&**other)
}
}
impl<T> ComputeSquaredDistance for Option<T>
where
T: ComputeSquaredDistance,
{
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
match (self.as_ref(), other.as_ref()) {
(Some(this), Some(other)) => this.compute_squared_distance(other),
(None, None) => Ok(SquaredDistance::from_sqrt(0.)),
_ => Err(()),
}
}
}
impl<T> ComputeSquaredDistance for Size2D<T>
where
T: ComputeSquaredDistance,
{
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
Ok(self.width.compute_squared_distance(&other.width)? +
self.height.compute_squared_distance(&other.height)?)
}
}
impl SquaredDistance {
#[inline]
pub fn sqrt(self) -> f64 {
self.value.sqrt()
}
}
impl Sum for SquaredDistance {
fn sum<I>(iter: I) -> Self
where
I: Iterator<Item = Self>,
{
iter.fold(SquaredDistance::from_sqrt(0.), Add::add)
}
}