imj-base-0.1.0.2: src/Imj/Graphics/Class/DiscreteDistance.hs
{-# OPTIONS_HADDOCK hide #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Imj.Graphics.Class.DiscreteDistance
( DiscreteDistance(..)
, Successive(..)
) where
import Imj.Prelude
import Data.List( length )
-- | Wrapper on a list, to represents successive waypoints.
newtype Successive a = Successive [a] deriving(Show)
{- | Instances should satisfy:
\( \forall (\, from, to)\, \in v, \)
* 'distance' @from to@ >= 0
* 'distance' @from to@ can be different from 'distance' @to from@,
to provide different forward and backward interpolations (or morphings).
-}
class DiscreteDistance v where
-- | Distance between two 'DiscreteDistance's.
distance :: v -- ^ first value
-> v -- ^ last value
-> Int -- ^ the number of steps (including first and last) to go from first to last
-- | Distance between n successive 'DiscreteDistance's.
distanceSuccessive :: Successive v
-> Int
distanceSuccessive (Successive []) =
error "empty successive"
distanceSuccessive (Successive l@(_:_)) =
succ $ sum $ zipWith (\a b -> pred $ distance a b) l $ tail l
-- | Naïve interpolation.
instance DiscreteDistance Int where
distance i i' =
1 + abs (i-i')
-- | Interpolation between 2 lists, occuring in parallel between same-index elements.
-- Prerequisite : lists have the same lengths.
--
-- For an interpolation that occurs sequentially between same-index elements,
-- use SequentiallyInterpolatedList.
instance (DiscreteDistance a)
=> DiscreteDistance ([] a) where
distance [] _ = 1
distance _ [] = 1
distance l l' =
maximum $ zipWith distance l $ assert (length l == length l') l'