module Math.Spline.ISpline
( ISpline, iSpline, toISpline
, evalSpline
) where
import Math.Spline.BSpline
import Math.Spline.Class
import Math.Spline.Knots
import qualified Data.Vector as V
import Data.VectorSpace
data ISpline v = ISpline
{ iSplineDegree :: !Int
, iSplineKnotVector :: Knots (Scalar v)
, iSplineControlPoints :: !(V.Vector v)
}
deriving instance (Eq (Scalar v), Eq v) => Eq (ISpline v)
deriving instance (Ord (Scalar v), Ord v) => Ord (ISpline v)
instance (Show (Scalar v), Show v) => Show (ISpline v) where
showsPrec p (ISpline _ kts cps) = showParen (p>10)
( showString "iSpline "
. showsPrec 11 kts
. showChar ' '
. showsPrec 11 cps
)
iSpline :: Knots (Scalar a) -> V.Vector a -> ISpline a
iSpline kts cps
| n > m = error "iSpline: too few knots"
| otherwise = ISpline (m n) kts cps
where
n = V.length cps
m = numKnots kts 1
instance (VectorSpace v, Fractional (Scalar v), Ord (Scalar v)) => Spline ISpline v where
splineDegree = (1 +) . iSplineDegree
knotVector spline = mkKnots (head ts : ts ++ [last ts])
where ts = knots (iSplineKnotVector spline)
toBSpline spline = bSpline (knotVector spline) (V.scanl (^+^) zeroV cs)
where cs = iSplineControlPoints spline
instance Spline ISpline v => ControlPoints ISpline v where
controlPoints (ISpline _ _ cs) = cs
toISpline :: (Spline s v, Eq v) => s v -> ISpline v
toISpline = fromBSpline . toBSpline
fromBSpline spline
| V.head ds == zeroV
&& numKnots ks >= 2 = iSpline (mkKnots (init (tail ts))) (V.tail ds')
| otherwise = iSpline (mkKnots (init ts )) ds'
where
ks = knotVector spline
ts = knots ks
ds = controlPoints spline
ds' = V.zipWith (^-^) ds (V.cons zeroV ds)