use crate::geom::{scalar::Scalar, Point3};
use crate::math::num_traits::{cast, NumCast};
use core::ops::{Add, Div};
pub trait Vertex: Clone + Copy + PartialEq {
type Scalar: Scalar;
}
pub trait Vertex2d: Vertex {
fn point2(self) -> [Self::Scalar; 2];
}
pub trait Vertex3d: Vertex2d {
fn point3(self) -> [Self::Scalar; 3];
}
pub trait Average: Vertex {
fn average<I>(vertices: I) -> Option<Self>
where
I: IntoIterator<Item = Self>;
}
pub type Default = Point3;
#[derive(Clone, Debug)]
pub struct IterFromIndices<'a, I, V: 'a = Default> {
indices: I,
vertices: &'a [V],
}
pub fn iter_from_indices<I, V>(indices: I, vertices: &[V]) -> IterFromIndices<I::IntoIter, V>
where
I: IntoIterator<Item = usize>,
{
let indices = indices.into_iter();
IterFromIndices { indices, vertices }
}
impl<'a, I, V> Iterator for IterFromIndices<'a, I, V>
where
I: Iterator<Item = usize>,
{
type Item = &'a V;
fn next(&mut self) -> Option<Self::Item> {
let IterFromIndices {
ref mut indices,
ref vertices,
} = *self;
indices.next().map(|i| &vertices[i])
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.indices.size_hint()
}
}
impl<'a, I, V> DoubleEndedIterator for IterFromIndices<'a, I, V>
where
I: Iterator<Item = usize> + DoubleEndedIterator,
{
fn next_back(&mut self) -> Option<Self::Item> {
let IterFromIndices {
ref mut indices,
ref vertices,
} = *self;
indices.next_back().map(|i| &vertices[i])
}
}
impl<'a, I, V> ExactSizeIterator for IterFromIndices<'a, I, V>
where
I: Iterator<Item = usize> + ExactSizeIterator,
{
fn len(&self) -> usize {
self.indices.len()
}
}
impl Vertex for glam::Vec2 {
type Scalar = f32;
}
impl Vertex for glam::Vec3 {
type Scalar = f32;
}
impl Vertex for glam::DVec2 {
type Scalar = f64;
}
impl Vertex for glam::DVec3 {
type Scalar = f64;
}
impl Vertex for glam::IVec2 {
type Scalar = i32;
}
impl Vertex for glam::IVec3 {
type Scalar = i32;
}
impl<S> Vertex for [S; 2]
where
S: Scalar,
{
type Scalar = S;
}
impl<S> Vertex for [S; 3]
where
S: Scalar,
{
type Scalar = S;
}
impl<S> Vertex for (S, S)
where
S: Scalar,
{
type Scalar = S;
}
impl<S> Vertex for (S, S, S)
where
S: Scalar,
{
type Scalar = S;
}
impl Vertex2d for glam::Vec2 {
fn point2(self) -> [Self::Scalar; 2] {
self.to_array()
}
}
impl Vertex2d for glam::Vec3 {
fn point2(self) -> [Self::Scalar; 2] {
self.truncate().to_array()
}
}
impl Vertex2d for glam::DVec2 {
fn point2(self) -> [Self::Scalar; 2] {
self.to_array()
}
}
impl Vertex2d for glam::DVec3 {
fn point2(self) -> [Self::Scalar; 2] {
self.truncate().to_array()
}
}
impl Vertex2d for glam::IVec2 {
fn point2(self) -> [Self::Scalar; 2] {
self.to_array()
}
}
impl Vertex2d for glam::IVec3 {
fn point2(self) -> [Self::Scalar; 2] {
self.truncate().to_array()
}
}
impl<S> Vertex2d for [S; 2]
where
S: Scalar,
{
fn point2(self) -> [Self::Scalar; 2] {
self
}
}
impl<S> Vertex2d for [S; 3]
where
S: Scalar,
{
fn point2(self) -> [Self::Scalar; 2] {
let [x, y, _] = self;
[x, y]
}
}
impl<S> Vertex2d for (S, S)
where
S: Scalar,
{
fn point2(self) -> [Self::Scalar; 2] {
let (x, y) = self;
[x, y]
}
}
impl<S> Vertex2d for (S, S, S)
where
S: Scalar,
{
fn point2(self) -> [Self::Scalar; 2] {
let (x, y, _) = self;
[x, y]
}
}
impl Vertex3d for glam::Vec3 {
fn point3(self) -> [Self::Scalar; 3] {
self.to_array()
}
}
impl Vertex3d for glam::DVec3 {
fn point3(self) -> [Self::Scalar; 3] {
self.to_array()
}
}
impl Vertex3d for glam::IVec3 {
fn point3(self) -> [Self::Scalar; 3] {
self.to_array()
}
}
impl<S> Vertex3d for [S; 3]
where
S: Scalar,
{
fn point3(self) -> [Self::Scalar; 3] {
self
}
}
impl<S> Vertex3d for (S, S, S)
where
S: Scalar,
{
fn point3(self) -> [Self::Scalar; 3] {
let (x, y, z) = self;
[x, y, z]
}
}
fn avg_glam_vecs<I>(vertices: I) -> Option<I::Item>
where
I: IntoIterator,
I::Item: Add<I::Item, Output = I::Item>
+ Div<<I::Item as Vertex>::Scalar, Output = I::Item>
+ Vertex,
<I::Item as Vertex>::Scalar: NumCast,
{
let mut vertices = vertices.into_iter();
vertices.next().map(|first| {
let init = (1, first);
let (len, total) = vertices.fold(init, |(i, acc), p| (i + 1, acc + p));
let divisor: <I::Item as Vertex>::Scalar = cast(len).unwrap();
total / divisor
})
}
impl Average for glam::Vec2 {
fn average<I>(vertices: I) -> Option<Self>
where
I: IntoIterator<Item = Self>,
{
avg_glam_vecs(vertices)
}
}
impl Average for glam::Vec3 {
fn average<I>(vertices: I) -> Option<Self>
where
I: IntoIterator<Item = Self>,
{
avg_glam_vecs(vertices)
}
}
impl Average for glam::DVec2 {
fn average<I>(vertices: I) -> Option<Self>
where
I: IntoIterator<Item = Self>,
{
avg_glam_vecs(vertices)
}
}
impl Average for glam::DVec3 {
fn average<I>(vertices: I) -> Option<Self>
where
I: IntoIterator<Item = Self>,
{
avg_glam_vecs(vertices)
}
}
impl<S> Average for [S; 2]
where
S: Scalar + NumCast,
{
fn average<I>(vertices: I) -> Option<Self>
where
I: IntoIterator<Item = Self>,
{
let mut vertices = vertices.into_iter();
vertices.next().map(|first| {
let init = (1, first);
let (len, [x, y]) =
vertices.fold(init, |(i, [ax, ay]), [bx, by]| (i + 1, [ax + bx, ay + by]));
let divisor: S = cast(len).unwrap();
[x / divisor, y / divisor]
})
}
}
impl<S> Average for [S; 3]
where
S: Scalar + NumCast,
{
fn average<I>(vertices: I) -> Option<Self>
where
I: IntoIterator<Item = Self>,
{
let mut vertices = vertices.into_iter();
vertices.next().map(|first| {
let init = (1, first);
let (len, [x, y, z]) = vertices.fold(init, |(i, [ax, ay, az]), [bx, by, bz]| {
(i + 1, [ax + bx, ay + by, az + bz])
});
let divisor: S = cast(len).unwrap();
[x / divisor, y / divisor, z / divisor]
})
}
}