----------------------------------------------------------------------------- -- | -- Copyright : (C) 2015 Dimitri Sabadie -- License : BSD3 -- -- Maintainer : Dimitri Sabadie -- Stability : experimental -- Portability : portable -- -- A @Spline s a@ represents a curve in which 'a' is very likely to be -- 'Additive' (see "linear") and 's' is the sampling type. -- -- The library exports two useful functions: 'spline' and 'smooth'. The former -- enables you to create splines while the latter enables you to sample from -- them using their control points. ---------------------------------------------------------------------------- module Data.Spline ( -- * Spline Spline , spline -- * Smoothing values along splines , smooth ) where import Data.List ( sortBy ) import Data.Ord ( comparing ) import Data.Spline.CP import Data.Spline.Polynomial ( Polynomial(..), bsearchLower ) import Data.Vector ( Vector, (!?), fromList ) -- |A @Spline@ is a collection of control points with associated polynomials. -- Given two control points which indices are /i/ and /i+1/, interpolation on -- the resulting curve is performed using the polynomial of indice /i/. Thus, -- the latest control point is ignored and can be set to whatever the user wants -- to, even 'undefined' – you should use hold, though. Yeah, don’t go filthy. data Spline s a = Spline (Vector (CP s a)) (Vector (Polynomial s a)) -- |Create a spline using a list of control points and associated polynomials. -- Since 'spline' sorts the list before creating the 'Spline', you don’t have to -- ensure the list is sorted – even though you should, setting control points -- with no order might be… chaotic. spline :: (Ord a,Ord s) => [(CP s a,Polynomial s a)] -> Spline s a spline = uncurry spline_ . unzip . dupLast . sortBy (comparing fst) where dupLast s = s ++ [last s] spline_ cps polys = Spline (fromList cps) (fromList polys) -- |Smoothly interpolate a point on a spline. smooth :: (Ord s) => Spline s a -> s -> Maybe a smooth (Spline cps polys) s = do i <- bsearchLower (\(CP s' _) -> compare s s') cps p <- polys !? i unPolynomial p s cps