use std::ops::{Add, Div, Mul, Neg, Sub};
use crate::math::{Point2D, Rect, Transform};
pub trait Geometry: Sized {
fn transform(self, t: impl Into<Transform>) -> Self;
fn untransform(self, t: impl Into<Transform>) -> Self {
self.transform(t.into().inverse())
}
}
impl Geometry for Rect<f32> {
fn transform(self, t: impl Into<Transform>) -> Self {
let t = t.into();
let min = t * self.min();
let max = t * self.max();
Self::points(min, max)
}
}
impl Geometry for Point2D<f32> {
fn transform(self, t: impl Into<Transform>) -> Self {
t.into() * self
}
}
pub trait Zero: PartialEq + Sized {
const ZERO: Self;
fn is_zero(&self) -> bool;
}
impl Zero for f32 {
const ZERO: f32 = 0.;
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
impl Zero for f64 {
const ZERO: f64 = 0.;
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
impl Zero for usize {
const ZERO: usize = 0;
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
impl Zero for i32 {
const ZERO: i32 = 0;
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
impl Zero for u32 {
const ZERO: u32 = 0;
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
impl Zero for u64 {
const ZERO: u64 = 0;
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
impl Zero for i64 {
const ZERO: i64 = 0;
fn is_zero(&self) -> bool {
self == &Self::ZERO
}
}
pub trait One: Sized {
const ONE: Self;
fn is_one(&self) -> bool;
}
impl One for f32 {
const ONE: f32 = 1.;
fn is_one(&self) -> bool {
self == &Self::ONE
}
}
impl One for f64 {
const ONE: f64 = 1.;
fn is_one(&self) -> bool {
self == &Self::ONE
}
}
impl One for usize {
const ONE: usize = 1;
fn is_one(&self) -> bool {
self == &Self::ONE
}
}
pub trait Two {
const TWO: Self;
}
impl Two for f32 {
const TWO: f32 = 2.;
}
impl Two for f64 {
const TWO: f64 = 2.;
}
impl Two for i32 {
const TWO: i32 = 2;
}
pub trait Float:
Copy
+ PartialOrd
+ Zero
+ One
+ Two
+ Neg<Output = Self>
+ Add<Output = Self>
+ Sub<Output = Self>
+ Div<Output = Self>
+ Mul<Output = Self>
{
fn sqrt(self) -> Self;
}
impl Float for f32 {
fn sqrt(self) -> Self {
f32::sqrt(self)
}
}
impl Float for f64 {
fn sqrt(self) -> Self {
f64::sqrt(self)
}
}
pub trait FloatExt<T> {
fn expand(&self) -> T;
}
impl FloatExt<f64> for f64 {
#[inline]
fn expand(&self) -> f64 {
self.abs().ceil().copysign(*self)
}
}
impl FloatExt<f32> for f32 {
#[inline]
fn expand(&self) -> f32 {
self.abs().ceil().copysign(*self)
}
}