{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts, TypeFamilies #-} ---------------------------------------------------------------------- -- | -- Module : Data.AffineSpace -- Copyright : (c) Conal Elliott and Andy J Gill 2008 -- License : BSD3 -- -- Maintainer : conal@conal.net, andygill@ku.edu -- Stability : experimental -- -- Affine spaces. ---------------------------------------------------------------------- module Data.AffineSpace ( AffineSpace(..), (.-^), distanceSq, distance, alerp ) where import Control.Applicative (liftA2) import Data.VectorSpace infix 4 .+^, .-^, .-. -- TODO: Convert AffineSpace from fundep to associated type, and eliminate -- FunctionalDependencies above. class AdditiveGroup (Diff p) => AffineSpace p where -- | Associated vector space type Diff p -- | Subtract points (.-.) :: p -> p -> Diff p -- | Point plus vector (.+^) :: p -> Diff p -> p -- | Point minus vector (.-^) :: AffineSpace p => p -> Diff p -> p p .-^ v = p .+^ negateV v -- | Square of the distance between two points. Sometimes useful for -- efficiency. See also 'distance'. distanceSq :: (AffineSpace p, v ~ Diff p, InnerSpace v) => p -> p -> Scalar v distanceSq = (fmap.fmap) magnitudeSq (.-.) -- | Distance between two points. See also 'distanceSq'. distance :: (AffineSpace p, v ~ Diff p, InnerSpace v , s ~ Scalar v, Floating (Scalar v)) => p -> p -> s distance = (fmap.fmap) sqrt distanceSq -- | Affine linear interpolation. Varies from @p@ to @p'@ as @s@ varies -- from 0 to 1. See also 'lerp' (on vector spaces). alerp :: (AffineSpace p, VectorSpace (Diff p)) => p -> p -> Scalar (Diff p) -> p alerp p p' s = p .+^ (s *^ (p' .-. p)) instance AffineSpace Double where type Diff Double = Double (.-.) = (-) (.+^) = (+) instance AffineSpace Float where type Diff Float = Float (.-.) = (-) (.+^) = (+) instance (AffineSpace p, AffineSpace q) => AffineSpace (p,q) where type Diff (p,q) = (Diff p, Diff q) (p,q) .-. (p',q') = (p .-. p', q .-. q') (p,q) .+^ (u,v) = (p .+^ u, q .+^ v) instance (AffineSpace p, AffineSpace q, AffineSpace r) => AffineSpace (p,q,r) where type Diff (p,q,r) = (Diff p, Diff q, Diff r) (p,q,r) .-. (p',q',r') = (p .-. p', q .-. q', r .-. r') (p,q,r) .+^ (u,v,w) = (p .+^ u, q .+^ v, r .+^ w) instance (AffineSpace p) => AffineSpace (a -> p) where type Diff (a -> p) = a -> Diff p (.-.) = liftA2 (.-.) (.+^) = liftA2 (.+^)