module Math.Spline.MSpline
( MSpline, mSpline, toMSpline
, evalSpline
) where
import Math.Spline.BSpline
import Math.Spline.Class
import Math.Spline.Knots
import qualified Data.Vector as V
import Data.VectorSpace
data MSpline v = MSpline
{ mSplineDegree :: !Int
, mSplineKnotVector :: Knots (Scalar v)
, mSplineControlPoints :: !(V.Vector v)
}
deriving instance (Eq (Scalar v), Eq v) => Eq (MSpline v)
deriving instance (Ord (Scalar v), Ord v) => Ord (MSpline v)
instance (Show (Scalar v), Show v) => Show (MSpline v) where
showsPrec p (MSpline _ kts cps) = showParen (p>10)
( showString "mSpline "
. showsPrec 11 kts
. showChar ' '
. showsPrec 11 cps
)
mSpline :: Knots (Scalar a) -> V.Vector a -> MSpline a
mSpline kts cps
| n > m = error "mSpline: too few knots"
| otherwise = MSpline (m n) kts cps
where
n = V.length cps
m = numKnots kts 1
spans :: Int -> V.Vector a -> V.Vector (a,a)
spans n xs = V.zip xs (V.drop n xs)
instance (VectorSpace v, Fractional (Scalar v), Ord (Scalar v)) => Spline MSpline v where
splineDegree = mSplineDegree
knotVector = mSplineKnotVector
toBSpline (MSpline p ks cs) = bSpline ks cs'
where
n = p + 1; n' = fromIntegral n
cs' = V.zipWith f cs (spans n (V.fromList (knots ks)))
f c (t0, t1) = ((n' / (t1 t0)) *^ c)
instance Spline MSpline v => ControlPoints MSpline v where
controlPoints = mSplineControlPoints
toMSpline :: Spline s v => s v -> MSpline v
toMSpline = fromBSpline . toBSpline
fromBSpline :: (VectorSpace a, Fractional (Scalar a), Ord (Scalar a))
=> BSpline (V.Vector) a -> MSpline a
fromBSpline spline = mSpline ks cs
where
n = splineDegree spline + 1; n' = fromIntegral n
ks = knotVector spline
cs = V.zipWith f (controlPoints spline) (spans n (V.fromList (knots ks)))
f c (t0, t1) = ((t1 t0) / n') *^ c