use crate::tower::EuclideanSpace;
pub trait Transformation<E: EuclideanSpace>: Sized + Clone {
fn transform_point(&self, pt: &E) -> E;
fn transform_vector(&self, v: &E::Coordinates) -> E::Coordinates;
}
pub trait ProjectiveTransformation<E: EuclideanSpace>: Transformation<E> {
fn inverse_transform(&self) -> Self;
fn inverse_transform_point(&self, pt: &E) -> E {
self.inverse_transform().transform_point(pt)
}
fn inverse_transform_vector(&self, v: &E::Coordinates) -> E::Coordinates {
self.inverse_transform().transform_vector(v)
}
}
pub trait AffineTransformation<E: EuclideanSpace>: ProjectiveTransformation<E> {
type Rotation: Rotation<E>;
type NonUniformScaling: AffineTransformation<E>;
type Translation: Translation<E>;
fn decompose(&self) -> (Self::Translation, Self::Rotation, Self::NonUniformScaling);
fn append_translation(&self, t: &Self::Translation) -> Self;
fn prepend_translation(&self, t: &Self::Translation) -> Self;
fn append_rotation(&self, r: &Self::Rotation) -> Self;
fn prepend_rotation(&self, r: &Self::Rotation) -> Self;
fn append_scaling(&self, s: &Self::NonUniformScaling) -> Self;
fn prepend_scaling(&self, s: &Self::NonUniformScaling) -> Self;
}
pub trait Similarity<E: EuclideanSpace>: AffineTransformation<E> {
type Scaling: Scaling<E>;
fn translation(&self) -> Self::Translation;
fn rotation(&self) -> Self::Rotation;
fn scaling(&self) -> Self::Scaling;
fn translate_point(&self, pt: &E) -> E {
<Self::Translation as Translation<E>>::transform_point(&self.translation(), pt)
}
fn rotate_point(&self, pt: &E) -> E {
<Self::Rotation as Transformation<E>>::transform_point(&self.rotation(), pt)
}
fn scale_point(&self, pt: &E) -> E {
<Self::Scaling as Transformation<E>>::transform_point(&self.scaling(), pt)
}
}
pub trait Rotation<E: EuclideanSpace>: Transformation<E> {}
pub trait Isometry<E: EuclideanSpace>: Similarity<E> {}
pub trait DirectIsometry<E: EuclideanSpace>: Isometry<E> {}
pub trait OrthogonalTransformation<E: EuclideanSpace>: Transformation<E> {}
pub trait Scaling<E: EuclideanSpace>: Transformation<E> {}
pub trait Translation<E: EuclideanSpace>: Transformation<E> {
fn translation_vector(&self) -> E::Coordinates;
fn transform_point(&self, pt: &E) -> E {
E::from_coordinates(<E::Coordinates as crate::tower::Magma<crate::op::Additive>>::combine(
&pt.coordinates(),
&self.translation_vector(),
))
}
fn transform_vector(&self, v: &E::Coordinates) -> E::Coordinates {
<E::Coordinates as Clone>::clone(v)
}
}