use decorum::R64;
use num::{self, Num, NumCast, One, Zero};
use std::ops::{Add, Mul, Neg, Sub};
pub mod compose;
pub mod convert;
pub mod ops;
pub mod query;
use self::convert::AsPosition;
pub trait Geometry: Sized {
type Vertex: Clone;
type Arc: Clone + Default;
type Edge: Clone + Default;
type Face: Clone + Default;
}
impl Geometry for () {
type Vertex = ();
type Arc = ();
type Edge = ();
type Face = ();
}
pub trait Space: Geometry
where
<Self as Geometry>::Vertex: AsPosition<Target = Self::Point>,
{
type Scalar: Clone + Neg<Output = Self::Scalar> + Num;
type Vector: Add<Output = Self::Vector>
+ Clone
+ Mul<Self::Scalar, Output = Self::Vector>
+ Neg<Output = Self::Vector>;
type Point: Add<Self::Vector, Output = Self::Point> + Clone + Sub<Output = Self::Vector>;
}
pub struct Ray<S>
where
S: Space,
<S as Geometry>::Vertex: AsPosition<Target = S::Point>,
{
pub origin: S::Point,
pub direction: S::Vector,
}
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Duplet<T>(pub T, pub T);
impl<T> Duplet<T> {
pub fn one() -> Self
where
T: One,
{
Duplet(One::one(), One::one())
}
pub fn zero() -> Self
where
T: Zero,
{
Duplet(Zero::zero(), Zero::zero())
}
}
impl<T> Geometry for Duplet<T>
where
T: Clone,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Triplet<T>(pub T, pub T, pub T);
impl<T> Triplet<T> {
pub fn one() -> Self
where
T: One,
{
Triplet(One::one(), One::one(), One::one())
}
pub fn zero() -> Self
where
T: Zero,
{
Triplet(Zero::zero(), Zero::zero(), Zero::zero())
}
}
impl<T> Geometry for Triplet<T>
where
T: Clone,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
pub fn lerp<T>(a: T, b: T, f: R64) -> T
where
T: Num + NumCast,
{
let f = num::clamp(f, Zero::zero(), One::one());
let af = <R64 as NumCast>::from(a).unwrap() * (R64::one() - f);
let bf = <R64 as NumCast>::from(b).unwrap() * f;
<T as NumCast>::from(af + bf).unwrap()
}
pub mod alias {
use std::ops::Mul;
use crate::geometry::compose::*;
use crate::geometry::convert::*;
use crate::geometry::*;
pub type VertexPosition<G> = <<G as Geometry>::Vertex as AsPosition>::Target;
pub type ScaledFaceNormal<G, T> = <<G as FaceNormal>::Normal as Mul<T>>::Output;
pub type ScaledArcNormal<G, T> = <<G as ArcNormal>::Normal as Mul<T>>::Output;
}
#[cfg(feature = "geometry-cgmath")]
mod feature_geometry_cgmath {
use cgmath::{Point2, Point3, Vector2, Vector3};
use num::{NumCast, ToPrimitive};
use crate::geometry::*;
impl<T, U> From<Point2<U>> for Duplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Point2<U>) -> Self {
Duplet(T::from(other.x).unwrap(), T::from(other.y).unwrap())
}
}
impl<T, U> From<Vector2<U>> for Duplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Vector2<U>) -> Self {
Duplet(T::from(other.x).unwrap(), T::from(other.y).unwrap())
}
}
impl<T, U> Into<Point2<T>> for Duplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Point2<T> {
Point2::new(T::from(self.0).unwrap(), T::from(self.1).unwrap())
}
}
impl<T, U> Into<Vector2<T>> for Duplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Vector2<T> {
Vector2::new(T::from(self.0).unwrap(), T::from(self.1).unwrap())
}
}
impl<T, U> From<Point3<U>> for Triplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Point3<U>) -> Self {
Triplet(
T::from(other.x).unwrap(),
T::from(other.y).unwrap(),
T::from(other.z).unwrap(),
)
}
}
impl<T, U> From<Vector3<U>> for Triplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Vector3<U>) -> Self {
Triplet(
T::from(other.x).unwrap(),
T::from(other.y).unwrap(),
T::from(other.z).unwrap(),
)
}
}
impl<T, U> Into<Point3<T>> for Triplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Point3<T> {
Point3::new(
T::from(self.0).unwrap(),
T::from(self.1).unwrap(),
T::from(self.2).unwrap(),
)
}
}
impl<T, U> Into<Vector3<T>> for Triplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Vector3<T> {
Vector3::new(
T::from(self.0).unwrap(),
T::from(self.1).unwrap(),
T::from(self.2).unwrap(),
)
}
}
impl<T> Geometry for Point2<T>
where
T: Clone,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
impl<T> Geometry for Point3<T>
where
T: Clone,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
}
#[cfg(feature = "geometry-mint")]
mod feature_geometry_mint {
use mint::{Point2, Point3, Vector2, Vector3};
use num::{NumCast, ToPrimitive};
use crate::geometry::*;
impl<T, U> From<Point2<U>> for Duplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Point2<U>) -> Self {
Duplet(T::from(other.x).unwrap(), T::from(other.y).unwrap())
}
}
impl<T, U> From<Vector2<U>> for Duplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Vector2<U>) -> Self {
Duplet(T::from(other.x).unwrap(), T::from(other.y).unwrap())
}
}
impl<T, U> Into<Point2<T>> for Duplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Point2<T> {
Point2 {
x: T::from(self.0).unwrap(),
y: T::from(self.1).unwrap(),
}
}
}
impl<T, U> Into<Vector2<T>> for Duplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Vector2<T> {
Vector2 {
x: T::from(self.0).unwrap(),
y: T::from(self.1).unwrap(),
}
}
}
impl<T, U> From<Point3<U>> for Triplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Point3<U>) -> Self {
Triplet(
T::from(other.x).unwrap(),
T::from(other.y).unwrap(),
T::from(other.z).unwrap(),
)
}
}
impl<T, U> From<Vector3<U>> for Triplet<T>
where
T: NumCast,
U: ToPrimitive,
{
fn from(other: Vector3<U>) -> Self {
Triplet(
T::from(other.x).unwrap(),
T::from(other.y).unwrap(),
T::from(other.z).unwrap(),
)
}
}
impl<T, U> Into<Point3<T>> for Triplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Point3<T> {
Point3 {
x: T::from(self.0).unwrap(),
y: T::from(self.1).unwrap(),
z: T::from(self.2).unwrap(),
}
}
}
impl<T, U> Into<Vector3<T>> for Triplet<U>
where
T: NumCast,
U: ToPrimitive,
{
fn into(self) -> Vector3<T> {
Vector3 {
x: T::from(self.0).unwrap(),
y: T::from(self.1).unwrap(),
z: T::from(self.2).unwrap(),
}
}
}
impl<T> Geometry for Point2<T>
where
T: Clone,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
impl<T> Geometry for Point3<T>
where
T: Clone,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
}
#[cfg(feature = "geometry-nalgebra")]
mod feature_geometry_nalgebra {
use nalgebra::{Point2, Point3, Scalar, Vector2, Vector3};
use num::{NumCast, ToPrimitive};
use std::ops::{AddAssign, MulAssign, SubAssign};
use crate::geometry::*;
impl<T, U> From<Point2<U>> for Duplet<T>
where
T: NumCast,
U: Scalar + ToPrimitive,
{
fn from(other: Point2<U>) -> Self {
Duplet(T::from(other.x).unwrap(), T::from(other.y).unwrap())
}
}
impl<T, U> From<Vector2<U>> for Duplet<T>
where
T: NumCast,
U: Scalar + ToPrimitive,
{
fn from(other: Vector2<U>) -> Self {
Duplet(T::from(other.x).unwrap(), T::from(other.y).unwrap())
}
}
impl<T, U> Into<Point2<T>> for Duplet<U>
where
T: NumCast + Scalar,
U: ToPrimitive,
{
fn into(self) -> Point2<T> {
Point2::new(T::from(self.0).unwrap(), T::from(self.1).unwrap())
}
}
impl<T, U> Into<Vector2<T>> for Duplet<U>
where
T: NumCast + Scalar,
U: ToPrimitive,
{
fn into(self) -> Vector2<T> {
Vector2::new(T::from(self.0).unwrap(), T::from(self.1).unwrap())
}
}
impl<T, U> From<Point3<U>> for Triplet<T>
where
T: NumCast,
U: Scalar + ToPrimitive,
{
fn from(other: Point3<U>) -> Self {
Triplet(
T::from(other.x).unwrap(),
T::from(other.y).unwrap(),
T::from(other.z).unwrap(),
)
}
}
impl<T, U> From<Vector3<U>> for Triplet<T>
where
T: NumCast,
U: Scalar + ToPrimitive,
{
fn from(other: Vector3<U>) -> Self {
Triplet(
T::from(other.x).unwrap(),
T::from(other.y).unwrap(),
T::from(other.z).unwrap(),
)
}
}
impl<T, U> Into<Point3<T>> for Triplet<U>
where
T: NumCast + Scalar,
U: ToPrimitive,
{
fn into(self) -> Point3<T> {
Point3::new(
T::from(self.0).unwrap(),
T::from(self.1).unwrap(),
T::from(self.2).unwrap(),
)
}
}
impl<T, U> Into<Vector3<T>> for Triplet<U>
where
T: NumCast + Scalar,
U: ToPrimitive,
{
fn into(self) -> Vector3<T> {
Vector3::new(
T::from(self.0).unwrap(),
T::from(self.1).unwrap(),
T::from(self.2).unwrap(),
)
}
}
impl<T> Geometry for Point2<T>
where
T: Scalar,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
impl<T> Geometry for Point3<T>
where
T: Scalar,
{
type Vertex = Self;
type Arc = ();
type Edge = ();
type Face = ();
}
impl<T> Space for Point2<T>
where
T: AddAssign + MulAssign + Neg<Output = T> + Num + Scalar + SubAssign,
<Self as Geometry>::Vertex: AsPosition<Target = Self>,
{
type Scalar = T;
type Vector = Vector2<T>;
type Point = Self;
}
impl<T> Space for Point3<T>
where
T: AddAssign + MulAssign + Neg<Output = T> + Num + Scalar + SubAssign,
<Self as Geometry>::Vertex: AsPosition<Target = Self>,
{
type Scalar = T;
type Vector = Vector3<T>;
type Point = Self;
}
}