splines-0.5.0.1: src/Math/Spline/Class.hs
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, UndecidableInstances #-}
{-# LANGUAGE OverlappingInstances, IncoherentInstances #-}
module Math.Spline.Class where
import Control.Applicative
import Math.Spline.Knots
import qualified Math.Spline.BSpline.Internal as BSpline
import qualified Data.Vector as V
import qualified Data.Vector.Generic as G
import Data.VectorSpace
-- |A spline is a piecewise polynomial vector-valued function. The necessary
-- and sufficient instance definition is 'toBSpline'.
class (VectorSpace v, Fractional (Scalar v), Ord (Scalar v)) => Spline s v where
-- |Returns the domain of a spline. In the case of B-splines, this is
-- the domain on which a spline with this degree and knot vector has a
-- full basis set. In other cases, it should be no larger than
-- @splineDomain . toBSpline@, but may be smaller. Within this domain,
-- 'evalSpline' should agree with @'evalSpline' . 'toBSpline'@ (not
-- necessarily exactly, but up to reasonable expectations of numerical
-- accuracy).
splineDomain :: s v -> Maybe (Scalar v, Scalar v)
splineDomain = knotDomain <$> knotVector <*> splineDegree
evalSpline :: s v -> Scalar v -> v
evalSpline = evalSpline . toBSpline
splineDegree :: s v -> Int
splineDegree = splineDegree . toBSpline
knotVector :: s v -> Knots (Scalar v)
knotVector = knotVector . toBSpline
toBSpline :: s v -> BSpline.BSpline V.Vector v
-- TODO: this class should probably go away. all it really does is overload something that doesn't really have any implementation-independent semantics (or does it?).
class Spline s v => ControlPoints s v where
controlPoints :: s v -> V.Vector v
instance (VectorSpace v, Fractional (Scalar v), Ord (Scalar v)) => Spline (BSpline.BSpline V.Vector) v where
evalSpline = BSpline.evalBSpline
splineDegree = BSpline.degree
knotVector = BSpline.knotVector
toBSpline = id
instance ( VectorSpace a, Fractional (Scalar a), Ord (Scalar a), G.Vector v a
, G.Vector v (Scalar a)) => Spline (BSpline.BSpline v) a where
evalSpline = BSpline.evalBSpline
splineDegree = BSpline.degree
knotVector = BSpline.knotVector
toBSpline (BSpline.Spline deg ks ctp) = BSpline.Spline deg ks (G.convert $ ctp)
instance Spline (BSpline.BSpline V.Vector) a => ControlPoints (BSpline.BSpline V.Vector) a where
controlPoints = BSpline.controlPoints
instance (Spline (BSpline.BSpline v) a, G.Vector v a) => ControlPoints (BSpline.BSpline v) a where
controlPoints = V.convert . BSpline.controlPoints