#![cfg(feature = "geometry-mint")]
use arrayvec::ArrayVec;
use decorum::R64;
use mint::{Point2, Point3, Vector2, Vector3};
use num::{Num, NumCast, One, Zero};
use std::ops::Neg;
use typenum::{U2, U3};
use crate::ops::{Cross, Dot, Interpolate, Map, Project, Reduce, ZipMap};
use crate::space::{Basis, FiniteDimensional};
use crate::{Composite, Converged, FromItems, IntoItems};
impl<T> Basis for Vector2<T>
where
T: One + Zero,
{
type Bases = ArrayVec<[Self; 2]>;
fn canonical_basis() -> Self::Bases {
ArrayVec::from([
Self::canonical_basis_component(0).unwrap(),
Self::canonical_basis_component(1).unwrap(),
])
}
fn canonical_basis_component(index: usize) -> Option<Self> {
match index {
0 => Some(Vector2 {
x: T::one(),
y: T::zero(),
}),
1 => Some(Vector2 {
x: T::zero(),
y: T::one(),
}),
_ => None,
}
}
}
impl<T> Basis for Vector3<T>
where
T: One + Zero,
{
type Bases = ArrayVec<[Self; 3]>;
fn canonical_basis() -> Self::Bases {
ArrayVec::from([
Self::canonical_basis_component(0).unwrap(),
Self::canonical_basis_component(1).unwrap(),
Self::canonical_basis_component(2).unwrap(),
])
}
fn canonical_basis_component(index: usize) -> Option<Self> {
match index {
0 => Some(Vector3 {
x: T::one(),
y: T::zero(),
z: T::zero(),
}),
1 => Some(Vector3 {
x: T::zero(),
y: T::one(),
z: T::zero(),
}),
2 => Some(Vector3 {
x: T::zero(),
y: T::zero(),
z: T::one(),
}),
_ => None,
}
}
}
impl<T> Cross for Vector3<T>
where
T: Copy + Neg<Output = T> + Num,
{
type Output = Self;
fn cross(self, other: Self) -> Self::Output {
Vector3 {
x: (self.y * other.z) - (self.z * other.y),
y: (self.z * other.x) - (self.x * other.z),
z: (self.x * other.y) - (self.y * other.x),
}
}
}
impl<T> Composite for Vector2<T> {
type Item = T;
}
impl<T> Composite for Vector3<T> {
type Item = T;
}
impl<T> Converged for Vector2<T>
where
T: Copy,
{
fn converged(value: T) -> Self {
Vector2 { x: value, y: value }
}
}
impl<T> Converged for Vector3<T>
where
T: Copy,
{
fn converged(value: T) -> Self {
Vector3 {
x: value,
y: value,
z: value,
}
}
}
impl<T> Dot for Vector2<T>
where
T: Num,
{
type Output = T;
fn dot(self, other: Self) -> Self::Output {
(self.x * other.x) + (self.y * other.y)
}
}
impl<T> Dot for Vector3<T>
where
T: Num,
{
type Output = T;
fn dot(self, other: Self) -> Self::Output {
(self.x * other.x) + (self.y * other.y) + (self.z * other.z)
}
}
impl<T> FiniteDimensional for Vector2<T> {
type N = U2;
}
impl<T> FiniteDimensional for Vector3<T> {
type N = U3;
}
impl<T> FromItems for Vector2<T> {
fn from_items<I>(items: I) -> Option<Self>
where
I: IntoIterator<Item = Self::Item>,
{
let mut items = items.into_iter().take(2);
match (items.next(), items.next()) {
(Some(x), Some(y)) => Some(Vector2 { x, y }),
_ => None,
}
}
}
impl<T> FromItems for Vector3<T> {
fn from_items<I>(items: I) -> Option<Self>
where
I: IntoIterator<Item = Self::Item>,
{
let mut items = items.into_iter().take(3);
match (items.next(), items.next(), items.next()) {
(Some(x), Some(y), Some(z)) => Some(Vector3 { x, y, z }),
_ => None,
}
}
}
impl<T> Interpolate for Vector2<T>
where
T: Num + NumCast,
{
type Output = Self;
fn lerp(self, other: Self, f: R64) -> Self::Output {
Vector2 {
x: crate::lerp(self.x, other.x, f),
y: crate::lerp(self.y, other.y, f),
}
}
}
impl<T> Interpolate for Vector3<T>
where
T: Num + NumCast,
{
type Output = Self;
fn lerp(self, other: Self, f: R64) -> Self::Output {
Vector3 {
x: crate::lerp(self.x, other.x, f),
y: crate::lerp(self.y, other.y, f),
z: crate::lerp(self.z, other.z, f),
}
}
}
impl<T> IntoItems for Vector2<T> {
type Output = ArrayVec<[T; 2]>;
fn into_items(self) -> Self::Output {
ArrayVec::from([self.x, self.y])
}
}
impl<T> IntoItems for Vector3<T> {
type Output = ArrayVec<[T; 3]>;
fn into_items(self) -> Self::Output {
ArrayVec::from([self.x, self.y, self.z])
}
}
impl<T, U> Map<U> for Vector2<T> {
type Output = Vector2<U>;
fn map<F>(self, mut f: F) -> Self::Output
where
F: FnMut(Self::Item) -> U,
{
Vector2 {
x: f(self.x),
y: f(self.y),
}
}
}
impl<T, U> Map<U> for Vector3<T> {
type Output = Vector3<U>;
fn map<F>(self, mut f: F) -> Self::Output
where
F: FnMut(Self::Item) -> U,
{
Vector3 {
x: f(self.x),
y: f(self.y),
z: f(self.z),
}
}
}
impl<T> Project<Vector2<T>> for Vector2<T>
where
T: Copy + Num,
{
type Output = Vector2<T>;
fn project(self, other: Vector2<T>) -> Self::Output {
let n = other.dot(self);
let d = self.dot(self);
self.map(|a| a * (n / d))
}
}
impl<T> Project<Vector3<T>> for Vector3<T>
where
T: Copy + Num,
{
type Output = Vector3<T>;
fn project(self, other: Vector3<T>) -> Self::Output {
let n = other.dot(self);
let d = self.dot(self);
self.map(|a| a * (n / d))
}
}
impl<T, U> Reduce<U> for Vector2<T>
where
T: Copy,
{
fn reduce<F>(self, mut seed: U, mut f: F) -> U
where
F: FnMut(U, Self::Item) -> U,
{
for a in &[self.x, self.y] {
seed = f(seed, *a);
}
seed
}
}
impl<T, U> Reduce<U> for Vector3<T>
where
T: Copy,
{
fn reduce<F>(self, mut seed: U, mut f: F) -> U
where
F: FnMut(U, Self::Item) -> U,
{
for a in &[self.x, self.y, self.z] {
seed = f(seed, *a);
}
seed
}
}
impl<T, U> ZipMap<U> for Vector2<T> {
type Output = Vector2<U>;
fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
where
F: FnMut(Self::Item, Self::Item) -> U,
{
Vector2 {
x: f(self.x, other.x),
y: f(self.y, other.y),
}
}
}
impl<T, U> ZipMap<U> for Vector3<T> {
type Output = Vector3<U>;
fn zip_map<F>(self, other: Self, mut f: F) -> Self::Output
where
F: FnMut(Self::Item, Self::Item) -> U,
{
Vector3 {
x: f(self.x, other.x),
y: f(self.y, other.y),
z: f(self.z, other.z),
}
}
}
impl<T> Composite for Point2<T>
where
T: Num,
{
type Item = T;
}
impl<T> Composite for Point3<T>
where
T: Num,
{
type Item = T;
}
impl<T> Interpolate for Point2<T>
where
T: Num + NumCast,
{
type Output = Self;
fn lerp(self, other: Self, f: R64) -> Self::Output {
Point2 {
x: crate::lerp(self.x, other.x, f),
y: crate::lerp(self.y, other.y, f),
}
}
}
impl<T> Interpolate for Point3<T>
where
T: Num + NumCast,
{
type Output = Self;
fn lerp(self, other: Self, f: R64) -> Self::Output {
Point3 {
x: crate::lerp(self.x, other.x, f),
y: crate::lerp(self.y, other.y, f),
z: crate::lerp(self.z, other.z, f),
}
}
}