use truck_meshalgo::prelude::*; #[derive(Clone, Debug)] pub enum Alternative { FirstType(T), SecondType(U), } #[doc(hidden)] #[macro_export] macro_rules! impl_from { ($firsttype: ty, $secondtype: ty) => { impl From<$firsttype> for $crate::alternative::Alternative<$firsttype, $secondtype> { #[inline(always)] fn from(t: $firsttype) -> Self { $crate::alternative::Alternative::FirstType(t) } } }; } impl From for Alternative { #[inline(always)] fn from(u: U) -> Self { Alternative::SecondType(u) } } // test for impl_from impl_from!((), usize); macro_rules! derive_method { ($method: tt, $return_type: ty, $($var: ident : $paramtype: ty),*) => { fn $method (&self, $($var: $paramtype),*) -> $return_type { match &self { Alternative::FirstType(got) => got.$method($($var),*), Alternative::SecondType(got) => got.$method($($var),*), } } }; ($method: tt <$x: ident : $y: path>, $return_type: ty, $($var: ident : $paramtype: ty),*) => { fn $method<$x : $y>(&self, $($var: $paramtype),*) -> $return_type { match &self { Alternative::FirstType(got) => got.$method($($var),*), Alternative::SecondType(got) => got.$method($($var),*), } } }; } impl ParametricCurve for Alternative where C0: ParametricCurve, C1: ParametricCurve, { type Point = C0::Point; type Vector = C0::Vector; derive_method!(subs, C0::Point, t: f64); derive_method!(der, C0::Vector, t: f64); derive_method!(der2, C0::Vector, t: f64); derive_method!( parameter_range, (std::ops::Bound, std::ops::Bound), ); } impl BoundedCurve for Alternative where C0: BoundedCurve, C1: BoundedCurve, { } impl ParametricSurface for Alternative where S0: ParametricSurface, S1: ParametricSurface, { type Point = S0::Point; type Vector = S0::Vector; derive_method!(subs, S0::Point, u: f64, v: f64); derive_method!(uder, S0::Vector, u: f64, v: f64); derive_method!(vder, S0::Vector, u: f64, v: f64); derive_method!(uuder, S0::Vector, u: f64, v: f64); derive_method!(uvder, S0::Vector, u: f64, v: f64); derive_method!(vvder, S0::Vector, u: f64, v: f64); } impl ParametricSurface3D for Alternative where S0: ParametricSurface3D, S1: ParametricSurface3D, { derive_method!(normal, Vector3, u: f64, v: f64); } impl Cut for Alternative where C0: Cut, C1: Cut, { fn cut(&mut self, t: f64) -> Self { match self { Self::FirstType(curve) => Self::FirstType(curve.cut(t)), Self::SecondType(curve) => Self::SecondType(curve.cut(t)), } } } impl ParameterDivision1D for Alternative where C0: ParameterDivision1D, C1: ParameterDivision1D, { type Point = C0::Point; derive_method!( parameter_division, (Vec, Vec), range: (f64, f64), tol: f64 ); } impl ParameterDivision2D for Alternative where S0: ParameterDivision2D, S1: ParameterDivision2D, { derive_method!( parameter_division, (Vec, Vec), range: ((f64, f64), (f64, f64)), tol: f64 ); } impl SearchParameter for Alternative where T: SearchParameter, U: SearchParameter, { type Point = T::Point; derive_method!( search_parameter>, Option, point: T::Point, hint: H, trials: usize ); } impl SearchNearestParameter for Alternative where T: SearchNearestParameter, U: SearchNearestParameter, { type Point = T::Point; derive_method!( search_nearest_parameter>, Option, point: T::Point, hint: H, trials: usize ); } impl Invertible for Alternative where T: Invertible, U: Invertible, { #[inline(always)] fn invert(&mut self) { match self { Self::FirstType(entity) => entity.invert(), Self::SecondType(entity) => entity.invert(), } } #[inline(always)] fn inverse(&self) -> Self { match self { Self::FirstType(entity) => Self::FirstType(entity.inverse()), Self::SecondType(entity) => Self::SecondType(entity.inverse()), } } }