use alloc::{borrow::Cow, vec::Vec};
pub(crate) type MatrixRxX<const D: usize> = na::OMatrix<f64, na::Const<D>, na::Dyn>;
pub(crate) fn to_mat<C, const D: usize>(curve: C) -> MatrixRxX<D>
where
C: Curve<D>,
{
MatrixRxX::from_iterator(curve.len(), curve.as_curve().iter().flatten().copied())
}
pub trait Curve<const D: usize>: Sized {
fn to_curve(self) -> Vec<[f64; D]>;
fn as_curve(&self) -> &[[f64; D]];
fn len(&self) -> usize {
self.as_curve().len()
}
fn is_empty(&self) -> bool {
self.as_curve().is_empty()
}
fn closed_lin(self) -> Vec<[f64; D]> {
let mut c = self.to_curve();
c.push(c[0]);
c
}
fn popped_last(self) -> Vec<[f64; D]> {
let mut curve = self.to_curve();
curve.pop();
curve
}
fn is_closed(&self) -> bool {
let curve = self.as_curve();
curve.first() == curve.last()
}
}
impl<const D: usize> Curve<D> for Vec<[f64; D]> {
fn to_curve(self) -> Vec<[f64; D]> {
self
}
fn as_curve(&self) -> &[[f64; D]] {
self
}
}
macro_rules! impl_slice {
() => {
fn to_curve(self) -> Vec<[f64; D]> {
self.to_vec()
}
fn as_curve(&self) -> &[[f64; D]] {
self
}
};
}
impl<const D: usize, const N: usize> Curve<D> for [[f64; D]; N] {
impl_slice!();
}
impl<const D: usize> Curve<D> for &[[f64; D]] {
impl_slice!();
}
impl<const D: usize> Curve<D> for Cow<'_, [[f64; D]]> {
impl_slice!();
}
impl<const D: usize, T: Curve<D> + Clone> Curve<D> for &T {
fn to_curve(self) -> Vec<[f64; D]> {
self.clone().to_curve()
}
fn as_curve(&self) -> &[[f64; D]] {
(*self).as_curve()
}
}
impl<const D: usize> Curve<D> for core::slice::Iter<'_, [f64; D]> {
fn to_curve(self) -> Vec<[f64; D]> {
self.copied().collect()
}
fn as_curve(&self) -> &[[f64; D]] {
self.as_slice()
}
}
impl<const D: usize, const N: usize> Curve<D> for core::array::IntoIter<[f64; D], N> {
fn to_curve(self) -> Vec<[f64; D]> {
self.collect()
}
fn as_curve(&self) -> &[[f64; D]] {
self.as_slice()
}
}
impl<const D: usize> Curve<D> for alloc::vec::IntoIter<[f64; D]> {
fn to_curve(self) -> Vec<[f64; D]> {
self.collect()
}
fn as_curve(&self) -> &[[f64; D]] {
self.as_slice()
}
}