module Math.Spline.BezierCurve
( BezierCurve, bezierCurve, splitBezierCurve
, evalSpline
) where
import Math.Spline.BSpline
import Math.Spline.Class
import Math.Spline.Knots
import Control.Applicative
import qualified Data.Vector as V
import Data.VectorSpace
data BezierCurve t = BezierCurve !Int !(V.Vector t) deriving (Eq, Ord)
bezierCurve :: V.Vector t -> BezierCurve t
bezierCurve cs
| V.null cs = error "bezierCurve: no control points given"
| otherwise = BezierCurve (V.length cs 1) cs
instance Show v => Show (BezierCurve v) where
showsPrec p (BezierCurve _ cs) = showParen (p>10)
( showString "bezierCurve "
. showsPrec 11 cs
)
instance (VectorSpace v, Fractional (Scalar v), Ord (Scalar v)) => Spline BezierCurve v where
splineDomain (BezierCurve _ _) = Just (0,1)
evalSpline (BezierCurve _ cs) = V.head . last . deCasteljau cs
splineDegree (BezierCurve p _) = p
knotVector (BezierCurve p _) = fromList [(0, p+1), (1, p+1)]
toBSpline = bSpline <$> knotVector <*> controlPoints
instance Spline BezierCurve v => ControlPoints BezierCurve v where
controlPoints (BezierCurve _ cs) = cs
deCasteljau :: VectorSpace v => V.Vector v -> Scalar v -> [V.Vector v]
deCasteljau cs t
| V.null cs = []
| otherwise = cs : deCasteljau (V.zipWith interp cs (V.tail cs)) t
where
interp x0 x1 = lerp x0 x1 t
splitBezierCurve :: VectorSpace v => BezierCurve v -> Scalar v -> (BezierCurve v, BezierCurve v)
splitBezierCurve (BezierCurve n cs) t =
( BezierCurve n (V.fromList (map V.head css))
, BezierCurve n (V.reverse (V.fromList (map V.last css)))
) where css = deCasteljau cs t