packages feed

shapes-demo-0.1.0.0: src/Physics/Draw/Canonical.hs

{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}

module Physics.Draw.Canonical where

import Data.Either.Combinators
import Linear.Affine (Point(..))
import Linear.V2
import Linear.Matrix
import Physics.Draw.Linear
import Utils.Utils

type V2' = V2 Double
type P2' = P2 Double
type ContactPoints = Either P2' (P2', P2')
data Contact =
  Contact { _contactPoints :: ContactPoints
          , _contactNormal :: V2'
          } deriving (Show)

data Overlap =
  Overlap { _overlapEdge :: (P2', P2')
          , _overlapVector :: V2'
          , _overlapPenetrator :: P2'
          } deriving (Show)

type Polygon = [P2']

newtype Aabb = Aabb (V2 (Double, Double))

class Transformable t where
  transform :: M33 Double -> t -> t

instance Transformable V2' where
  transform = afmul

instance Transformable P2' where
  transform = afmul

instance (Transformable a) => Transformable (a, a) where
  transform = pairMap . transform

instance (Transformable a, Transformable b) => Transformable (Either a b) where
  transform t = mapBoth (transform t) (transform t)

instance Transformable Contact where
  transform t (Contact x y) =
    Contact (transform t x) (transform t y)

instance Transformable Overlap where
  transform t (Overlap x y z) =
    Overlap (transform t x) (transform t y) (transform t z)

instance (Transformable a) => Transformable [a] where
  transform = fmap . transform

instance Transformable Aabb where
  transform t (Aabb box) = Aabb $ (,) <$> minBox <*> maxBox
    where (P minBox) = transform t . P $ fmap fst box
          (P maxBox) = transform t . P $ fmap snd box

class IsCanonical a where
  dummyIsCanonical :: a
  dummyIsCanonical = undefined

instance IsCanonical V2'
instance IsCanonical P2'
instance IsCanonical ContactPoints
instance IsCanonical Contact
instance IsCanonical Overlap
instance IsCanonical Polygon
instance IsCanonical Aabb

class (IsCanonical (Canonical a)) => ToCanonical a where
  type Canonical a
  toCanonical :: a -> Canonical a

transCanon :: (ToCanonical a, Transformable (Canonical a))
           => M33 Double
           -> a
           -> Canonical a
transCanon t = transform t . toCanonical