content: {-#LANGUAGE TypeFamilies,FlexibleInstances, FlexibleContexts#-}
  module Utils.GeometryClass where
  
  import Utils.Rectangle
  import Utils.Point
  
  class Point2D a where
     type ELP a :: *
     pt :: a -> (ELP a, ELP a)
     toPt :: (ELP a,ELP a) -> a
  
  instance Point2D (Int,Int) where
     type ELP (Int,Int) = Int
     pt = id
     toPt = id
  
  instance Point2D (Float,Float) where
     type ELP (Float,Float) = Float
     pt = id
     toPt = id
  
  instance Point2D (Double,Double) where
     type ELP (Double,Double) = Double
     pt = id
     toPt = id
  
  -- | Extract integer coordinates of a point
  ipt :: (Point2D a,RealFrac (ELP a)) => a -> (Int,Int)
  ipt = (\(x,y) -> (round x, round y)) . pt
  
  convertPt :: (Point2D a, Point2D b, ELP a ~ ELP b) => a -> b
  convertPt = toPt . pt
  
  class BoundingBox a where
     type ELBB a :: *
     bounds :: a -> Rectangle (ELBB a)
  
  class FromBounds a where
     type ELFB a :: *
     fromBounds :: Rectangle (ELFB a) -> a
  
  instance BoundingBox (Rectangle a) where
     type ELBB (Rectangle a) = a
     bounds = id
  
  instance FromBounds (Rectangle a) where
     type ELFB (Rectangle a) = a
     fromBounds = id
  
  convertBounds :: (BoundingBox a, FromBounds b, ELBB a ~ ELFB b) => a -> b
  convertBounds = fromBounds . bounds
  
  -- type IntBounded a = (BoundingBox a,Integral (ELBB a))
  
  class Line2D a where
     type ELL a :: *
     offsetAngle :: a -> (ELL a, Double)
  
  class LineSegment a where
     type ELS a :: *
     startEnd :: a -> ((ELS a, ELS a),(ELS a, ELS a))
  
  -- | Typeclass for elements with a size, such as images and matrices.
  class Sized a where
      type Size a :: *
      getSize :: a -> Size a
  
  biggerThan :: (Sized a, Sized b, Size a~(Int,Int), Size b ~Size a) => a -> b -> Bool
  biggerThan a b = w1>=w2 && h1>=h2
      where
       (w1,h1) = getSize a
       (w2,h2) = getSize b
  
  