content: module Apecs.Physics.Geometry where
  
  import Apecs.Physics.Types
  import Linear
  
  vertices :: Convex -> [BVec]
  vertices (Convex s _) = s
  
  -- | Map a function over all vertices
  mapVertices :: (BVec -> BVec) -> Convex -> Convex
  mapVertices f (Convex s r) = Convex (f <$> s) r
  
  -- | Translates all vertices. The name shift is to prevent collisions with gloss
  shift :: BVec -> Convex -> Convex
  shift = mapVertices . (+)
  
  getRadius :: Convex -> Double
  getRadius (Convex _ r) = r
  
  setRadius :: Double -> Convex -> Convex
  setRadius r (Convex s _) = Convex s r
  
  cCircle, zCircle :: Double -> Convex
  cCircle r = oCircle 0 r
  zCircle = cCircle
  
  oCircle :: BVec -> Double -> Convex
  oCircle o r = Convex [o] r
  
  hLine, vLine :: Double -> Convex
  hLine l = Convex [V2 (-l/2) 0, V2 (l/2) 0] 0
  vLine l = Convex [V2 0 (l/2), V2 0 (-l/2)] 0
  
  -- | Centered rectangle with a given size
  cRectangle :: BVec -> Convex
  cRectangle s = oRectangle (-s*0.5) s
  
  -- | Rectangle with a given origin and size
  oRectangle :: BVec -> BVec -> Convex
  oRectangle (V2 x y) (V2 w h) = Convex [V2 x y, V2 x (y+h), V2 (x+w) (y+h), V2 (x+w) y] 0
  
  -- | Rectangle with origin 0 and given size
  zRectangle :: BVec -> Convex
  zRectangle s = oRectangle 0 s
  
  -- | Split a shape into its edges. Will return no edges for points, but returns 2 for a line (in opposite directions)
  toEdges :: Convex -> [Convex]
  toEdges (Convex [] _) = []
  toEdges (Convex [_] _) = []
  toEdges (Convex vs r) = zipWith (\h t -> Convex [h,t] r) vs (tail . cycle $ vs)
  
  -- | A set of lines forming a grid. Returns (r + c + 2) segments.
  gridLines :: Vec -> Int -> Int -> [Convex]
  gridLines size c r =
    [ shift (V2 x 0) (vLine h) | x <- xs ] ++
    [ shift (V2 0 y) (hLine w) | y <- ys ]
    where
      V2 w h = size
      V2 x y = -size*0.5
      dx = w/fromIntegral c
      dy = h/fromIntegral r
      xs = [x + fromIntegral n * dx | n <- [0..c]]
      ys = [y + fromIntegral n * dy | n <- [0..r]]
  
  