--- a/src/sets.rs Sat Dec 21 23:32:20 2024 -0500 +++ b/src/sets.rs Sun Dec 22 14:54:46 2024 -0500 @@ -3,19 +3,19 @@ */ use std::ops::{RangeFull,RangeFrom,Range,RangeInclusive,RangeTo,RangeToInclusive}; -use std::marker::PhantomData; use crate::types::*; use crate::loc::Loc; -use crate::euclidean::Dot; +use crate::euclidean::Euclidean; +use crate::instance::{Space, Instance}; use serde::Serialize; pub mod cube; pub use cube::Cube; /// Trait for arbitrary sets. The parameter `U` is the element type. -pub trait Set<U> where U : ?Sized { +pub trait Set<U> where U : Space { /// Check for element containment - fn contains(&self, item : &U) -> bool; + fn contains<I : Instance<U>>(&self, item : I) -> bool; } /// Additional ordering (besides [`PartialOrd`]) of a subfamily of sets: @@ -31,22 +31,27 @@ impl<U, const N : usize> Set<Loc<U, N>> for Cube<U,N> where U : Num + PartialOrd + Sized { - fn contains(&self, item : &Loc<U, N>) -> bool { - self.0.iter().zip(item.iter()).all(|(s, x)| s.contains(x)) + fn contains<I : Instance<Loc<U, N>>>(&self, item : I) -> bool { + self.0.iter().zip(item.ref_instance().iter()).all(|(s, x)| s.contains(x)) } } -impl<U> Set<U> for RangeFull { - fn contains(&self, _item : &U) -> bool { true } +impl<U : Space> Set<U> for RangeFull { + fn contains<I : Instance<U>>(&self, _item : I) -> bool { true } } macro_rules! impl_ranges { ($($range:ident),*) => { $( - impl<U,Idx> Set<U> - for $range<Idx> - where Idx : PartialOrd<U>, U : PartialOrd<Idx> + ?Sized, Idx : PartialOrd { + impl<U,Idx> Set<U> for $range<Idx> + where + Idx : PartialOrd<U>, + U : PartialOrd<Idx> + Space, + Idx : PartialOrd + { #[inline] - fn contains(&self, item : &U) -> bool { $range::contains(&self, item) } + fn contains<I : Instance<U>>(&self, item : I) -> bool { + item.eval(|x| $range::contains(&self, x)) + } } )* } } @@ -61,40 +66,39 @@ /// `U` is the element type, `F` the floating point number type, and `A` the type of the /// orthogonal (dual) vectors. They need implement [`Dot<U, F>`]. #[derive(Clone,Copy,Debug,Serialize,Eq,PartialEq)] -pub struct Halfspace<A, F, U> where A : Dot<U, F>, F : Float { +pub struct Halfspace<A, F> where A : Euclidean<F>, F : Float { pub orthogonal : A, pub offset : F, - _phantom : PhantomData<U>, } -impl<A,F,U> Halfspace<A,F,U> where A : Dot<U,F>, F : Float { +impl<A,F> Halfspace<A,F> where A : Euclidean<F>, F : Float { #[inline] pub fn new(orthogonal : A, offset : F) -> Self { - Halfspace{ orthogonal : orthogonal, offset : offset, _phantom : PhantomData } + Halfspace{ orthogonal : orthogonal, offset : offset } } } /// Trait for generating a halfspace spanned by another set `Self` of elements of type `U`. -pub trait SpannedHalfspace<F, U> where F : Float { +pub trait SpannedHalfspace<F> where F : Float { /// Type of the orthogonal vector describing the halfspace. - type A : Dot<U, F>; + type A : Euclidean<F>; /// Returns the halfspace spanned by this set. - fn spanned_halfspace(&self) -> Halfspace<Self::A, F, U>; + fn spanned_halfspace(&self) -> Halfspace<Self::A, F>; } // TODO: Gram-Schmidt for higher N. -impl<F : Float> SpannedHalfspace<F,Loc<F, 1>> for [Loc<F, 1>; 2] { +impl<F : Float> SpannedHalfspace<F> for [Loc<F, 1>; 2] { type A = Loc<F, 1>; - fn spanned_halfspace(&self) -> Halfspace<Self::A, F, Loc<F, 1>> { + fn spanned_halfspace(&self) -> Halfspace<Self::A, F> { let (x0, x1) = (self[0], self[1]); Halfspace::new(x1-x0, x0[0]) } } // TODO: Gram-Schmidt for higher N. -impl<F : Float> SpannedHalfspace<F,Loc<F, 2>> for [Loc<F, 2>; 2] { +impl<F : Float> SpannedHalfspace<F> for [Loc<F, 2>; 2] { type A = Loc<F, 2>; - fn spanned_halfspace(&self) -> Halfspace<Self::A, F, Loc<F, 2>> { + fn spanned_halfspace(&self) -> Halfspace<Self::A, F> { let (x0, x1) = (&self[0], &self[1]); let d = x1 - x0; let orthog = loc![d[1], -d[0]]; // We don't normalise for efficiency @@ -103,19 +107,29 @@ } } -impl<A,U,F> Set<U> for Halfspace<A,F,U> where A : Dot<U,F>, F : Float { +impl<A,F> Set<A> for Halfspace<A,F> +where + A : Euclidean<F>, + F : Float, +{ #[inline] - fn contains(&self, item : &U) -> bool { + fn contains<I : Instance<A>>(&self, item : I) -> bool { self.orthogonal.dot(item) >= self.offset } } /// Polygons defined by `N` `Halfspace`s. #[derive(Clone,Copy,Debug,Eq,PartialEq)] -pub struct NPolygon<A, F, U, const N : usize>(pub [Halfspace<A,F,U>; N]) where A : Dot<U,F>, F : Float; +pub struct NPolygon<A, F, const N : usize>(pub [Halfspace<A,F>; N]) +where A : Euclidean<F>, F : Float; -impl<A,U,F,const N : usize> Set<U> for NPolygon<A,F,U,N> where A : Dot<U,F>, F : Float { - fn contains(&self, item : &U) -> bool { - self.0.iter().all(|halfspace| halfspace.contains(item)) +impl<A,F,const N : usize> Set<A> for NPolygon<A,F,N> +where + A : Euclidean<F>, + F : Float, +{ + fn contains<I : Instance<A>>(&self, item : I) -> bool { + let r = item.ref_instance(); + self.0.iter().all(|halfspace| halfspace.contains(r)) } }