use std::collections::VecDeque;
use std::marker::PhantomData;
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
pub struct Quad<T> {
pub x: T,
pub y: T,
pub z: T,
pub w: T,
}
impl<T> Quad<T> {
pub fn new(v0: T, v1: T, v2: T, v3: T) -> Self {
Quad {
x: v0,
y: v1,
z: v2,
w: v3,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
pub struct Triangle<T> {
pub x: T,
pub y: T,
pub z: T,
}
impl<T> Triangle<T> {
pub fn new(v0: T, v1: T, v2: T) -> Self {
Triangle {
x: v0,
y: v1,
z: v2,
}
}
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum Polygon<T> {
PolyTri(Triangle<T>),
PolyQuad(Quad<T>),
}
pub trait EmitVertices<T> {
fn emit_vertices<F>(self, F)
where
F: FnMut(T);
}
impl<T> EmitVertices<T> for Line<T> {
fn emit_vertices<F>(self, mut emit: F)
where
F: FnMut(T),
{
let Line { x, y } = self;
emit(x);
emit(y);
}
}
impl<T> EmitVertices<T> for Triangle<T> {
fn emit_vertices<F>(self, mut emit: F)
where
F: FnMut(T),
{
let Triangle { x, y, z } = self;
emit(x);
emit(y);
emit(z);
}
}
impl<T> EmitVertices<T> for Quad<T> {
fn emit_vertices<F>(self, mut emit: F)
where
F: FnMut(T),
{
let Quad { x, y, z, w } = self;
emit(x);
emit(y);
emit(z);
emit(w);
}
}
impl<T> EmitVertices<T> for Polygon<T> {
fn emit_vertices<F>(self, emit: F)
where
F: FnMut(T),
{
use self::Polygon::{PolyQuad, PolyTri};
match self {
PolyTri(p) => p.emit_vertices(emit),
PolyQuad(p) => p.emit_vertices(emit),
}
}
}
pub trait Vertices<SRC, V> {
fn vertices(self) -> VerticesIterator<SRC, V>;
}
impl<V, P: EmitVertices<V>, T: Iterator<Item = P>> Vertices<T, V> for T {
fn vertices(self) -> VerticesIterator<T, V> {
VerticesIterator {
source: self,
buffer: VecDeque::new(),
}
}
}
pub struct VerticesIterator<SRC, V> {
source: SRC,
buffer: VecDeque<V>,
}
impl<V, U: EmitVertices<V>, SRC: Iterator<Item = U>> Iterator for VerticesIterator<SRC, V> {
type Item = V;
fn next(&mut self) -> Option<V> {
loop {
match self.buffer.pop_front() {
Some(v) => return Some(v),
None => (),
}
match self.source.next() {
Some(p) => p.emit_vertices(|v| self.buffer.push_back(v)),
None => return None,
}
}
}
}
pub trait MapVertex<T, U> {
type Output;
fn map_vertex<F>(self, F) -> Self::Output
where
F: FnMut(T) -> U;
}
impl<T: Clone, U> MapVertex<T, U> for Line<T> {
type Output = Line<U>;
fn map_vertex<F>(self, mut map: F) -> Line<U>
where
F: FnMut(T) -> U,
{
let Line { x, y } = self;
Line {
x: map(x),
y: map(y),
}
}
}
impl<T: Clone, U> MapVertex<T, U> for Triangle<T> {
type Output = Triangle<U>;
fn map_vertex<F>(self, mut map: F) -> Triangle<U>
where
F: FnMut(T) -> U,
{
let Triangle { x, y, z } = self;
Triangle {
x: map(x),
y: map(y),
z: map(z),
}
}
}
impl<T: Clone, U> MapVertex<T, U> for Quad<T> {
type Output = Quad<U>;
fn map_vertex<F>(self, mut map: F) -> Quad<U>
where
F: FnMut(T) -> U,
{
let Quad { x, y, z, w } = self;
Quad {
x: map(x),
y: map(y),
z: map(z),
w: map(w),
}
}
}
impl<T: Clone, U> MapVertex<T, U> for Polygon<T> {
type Output = Polygon<U>;
fn map_vertex<F>(self, map: F) -> Polygon<U>
where
F: FnMut(T) -> U,
{
use self::Polygon::{PolyQuad, PolyTri};
match self {
PolyTri(p) => PolyTri(p.map_vertex(map)),
PolyQuad(p) => PolyQuad(p.map_vertex(map)),
}
}
}
pub trait MapToVertices<T, U>: Sized {
type Output;
fn vertex<F>(self, map: F) -> MapToVerticesIter<Self, T, U, F>
where
F: FnMut(T) -> U;
}
impl<VIn, VOut, P, POut: MapVertex<VIn, VOut, Output = P>, T: Iterator<Item = POut>>
MapToVertices<VIn, VOut> for T
{
type Output = P;
fn vertex<F>(self, map: F) -> MapToVerticesIter<T, VIn, VOut, F>
where
F: FnMut(VIn) -> VOut,
{
MapToVerticesIter {
src: self,
f: map,
phantom: PhantomData,
}
}
}
pub struct MapToVerticesIter<SRC, T, U, F: FnMut(T) -> U> {
src: SRC,
f: F,
phantom: PhantomData<(T, U)>,
}
impl<
'a,
P,
POut: MapVertex<T, U, Output = P>,
SRC: Iterator<Item = POut>,
T,
U,
F: FnMut(T) -> U,
> Iterator for MapToVerticesIter<SRC, T, U, F>
{
type Item = P;
fn size_hint(&self) -> (usize, Option<usize>) {
self.src.size_hint()
}
fn next(&mut self) -> Option<P> {
self.src.next().map(|x| x.map_vertex(|x| (self.f)(x)))
}
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash)]
pub struct Line<T> {
pub x: T,
pub y: T,
}
impl<T> Line<T> {
pub fn new(x: T, y: T) -> Self {
Line { x: x, y: y }
}
}
pub trait EmitLines {
type Vertex;
fn emit_lines<E>(self, emit: E)
where
E: FnMut(Line<Self::Vertex>);
}
impl<T: Clone> EmitLines for Triangle<T> {
type Vertex = T;
fn emit_lines<E>(self, mut emit: E)
where
E: FnMut(Line<T>),
{
emit(Line::new(self.x.clone(), self.y.clone()));
emit(Line::new(self.y, self.z.clone()));
emit(Line::new(self.z, self.x));
}
}
impl<T: Clone> EmitLines for Quad<T> {
type Vertex = T;
fn emit_lines<E>(self, mut emit: E)
where
E: FnMut(Line<T>),
{
emit(Line::new(self.x.clone(), self.y.clone()));
emit(Line::new(self.y, self.z.clone()));
emit(Line::new(self.z, self.w.clone()));
emit(Line::new(self.w, self.x));
}
}
impl<T: Clone> EmitLines for Polygon<T> {
type Vertex = T;
fn emit_lines<E>(self, emit: E)
where
E: FnMut(Line<T>),
{
match self {
Polygon::PolyTri(x) => x.emit_lines(emit),
Polygon::PolyQuad(x) => x.emit_lines(emit),
}
}
}
pub trait Lines: Sized {
type Vertex;
fn lines(self) -> LinesIterator<Self, Self::Vertex>;
}
impl<T, P, V> Lines for T
where
T: Iterator<Item = P>,
P: EmitLines<Vertex = V>,
{
type Vertex = V;
fn lines(self) -> LinesIterator<T, V> {
LinesIterator {
source: self,
buffer: VecDeque::new(),
}
}
}
pub struct LinesIterator<I, V> {
source: I,
buffer: VecDeque<Line<V>>,
}
impl<I, P, V> Iterator for LinesIterator<I, V>
where
I: Iterator<Item = P>,
P: EmitLines<Vertex = V>,
{
type Item = Line<V>;
fn size_hint(&self) -> (usize, Option<usize>) {
let (n, _) = self.source.size_hint();
(n, None)
}
fn next(&mut self) -> Option<Line<V>> {
loop {
match self.buffer.pop_front() {
Some(v) => return Some(v),
None => (),
}
match self.source.next() {
Some(p) => p.emit_lines(|v| self.buffer.push_back(v)),
None => return None,
}
}
}
}