-- GENERATED by C->Haskell Compiler, version 0.28.3 Switcheroo, 25 November 2017 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "src/Chiphunk/Low/BB.chs" #-}
-- | Description: Utilities for working with bounding box.
-- Module provides utilities for working with bounding box.
module Chiphunk.Low.BB
  ( BB (..)
  , bbNew
  , bbNewForExtents
  , bbNewForCircle
  , bbIntersects
  , bbContainsBB
  , bbContainsVect
  , bbMerge
  , bbExpand
  , bbCenter
  , bbArea
  , bbMergedArea
  , bbSegmentQuery
  , bbIntersectsSegment
  , bbClampVect
  , bbWrapVect
  ) where
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Marshal.Utils as C2HSImp
import qualified System.IO.Unsafe as C2HSImp



import Data.Fixed
import Foreign

import Chiphunk.Low.Math

import Chiphunk.Low.Types
{-# LINE 27 "src/Chiphunk/Low/BB.chs" #-}





-- | Convenience constructor for 'BB' structs.
bbNew :: Double -> Double -> Double -> Double -> BB
bbNew = BB

-- | Convenience constructor for making a 'BB' fitting with a center point and half width and height.
bbNewForExtents
  :: Vect   -- ^ Center point
  -> Double -- ^ Half width
  -> Double -- ^ Half height
  -> BB
bbNewForExtents (Vect x y) hw hh = BB (x - hw) (y - hh) (x + hw) (y + hh)

-- | Convenience constructor for making a 'BB' fitting a circle at position @p@ with radius @r@.
bbNewForCircle
  :: Vect   -- ^ p
  -> Double -- ^ r
  -> BB
bbNewForCircle v r = bbNewForExtents v r r

-- | Returns true if the bounding boxes intersect.
bbIntersects :: BB -> BB -> Bool
BB l1 b1 r1 t1 `bbIntersects` BB l2 b2 r2 t2 = r1 >= l1 && r2 >= l2 && t1 >= b1 && t2 >= b2

-- | Returns true if @bb@ completely contains @other@.
bbContainsBB
  :: BB   -- ^ bb
  -> BB   -- ^ other
  -> Bool
BB l1 b1 r1 t1 `bbContainsBB` BB l2 b2 r2 t2 = l1 <= l2 && r1 >= r2 && t1 >= t2 && b1 <= b2

-- | Returns true if @bb@ contains @v@.
bbContainsVect
  :: BB   -- ^ bb
  -> Vect -- ^ v
  -> Bool
BB l b r t `bbContainsVect` Vect x y = l <= x && r >= x && b <= y && t >= y

-- | Return the minimal bounding box that contains both @a@ and @b@.
bbMerge
  :: BB -- ^ a
  -> BB -- ^ b
  -> BB
BB l1 b1 r1 t1 `bbMerge` BB l2 b2 r2 t2 = BB (min l1 l2) (min b1 b2) (max r1 r2) (max t1 t2)

-- | Return the minimal bounding box that contains both @bb@ and @v@.
bbExpand
  :: BB   -- ^ bb
  -> Vect -- ^ v
  -> BB
BB l b r t `bbExpand` Vect x y = BB (min l x) (min b y) (max r x) (max t y)

-- | Return the center of @bb@.
bbCenter
  :: BB   -- ^ bb
  -> Vect
bbCenter (BB l b r t) = Vect ((l + r) / 2) ((b + t) / 2)

-- | Return the area of @bb@.
bbArea
  :: BB     -- ^ bb
  -> Double
bbArea (BB l b r t) = (r - l) * (t - b)

-- | Merges @a@ and @b@ then returns the area of the merged bounding box.
bbMergedArea
  :: BB     -- ^ a
  -> BB     -- ^ b
  -> Double
BB l1 b1 r1 t1 `bbMergedArea` BB l2 b2 r2 t2 = (max r1 r2 - min l1 l2) * (max t1 t2 - min b1 b2)

-- | Returns the fraction along the segment query the 'BB' is hit. Returns INFINITY if it doesn’t hit.
bbSegmentQuery :: (BB) -- ^ Box
 -> (Vect) -- ^ One segment end
 -> (Vect) -- ^ Other segment end
 -> (Double)
bbSegmentQuery a1 a2 a3 =
  C2HSImp.unsafePerformIO $
  with a1 $ \a1' ->
  with a2 $ \a2' ->
  with a3 $ \a3' ->
  bbSegmentQuery'_ a1' a2' a3' >>= \res ->
  let {res' = realToFrac res} in
  return (res')

{-# LINE 107 "src/Chiphunk/Low/BB.chs" #-}


-- | Returns true if the segment defined by endpoints @a@ and @b@ intersect @bb@.
bbIntersectsSegment :: (BB) -- ^ bb
 -> (Vect) -- ^ a
 -> (Vect) -- ^ b
 -> (Bool)
bbIntersectsSegment a1 a2 a3 =
  C2HSImp.unsafePerformIO $
  with a1 $ \a1' ->
  with a2 $ \a2' ->
  with a3 $ \a3' ->
  bbIntersectsSegment'_ a1' a2' a3' >>= \res ->
  let {res' = C2HSImp.toBool res} in
  return (res')

{-# LINE 114 "src/Chiphunk/Low/BB.chs" #-}


-- | Returns a copy of @v@ clamped to the bounding box @bb@.
bbClampVect
  :: BB   -- ^ bb
  -> Vect -- ^ v
  -> Vect
BB l b r t `bbClampVect` Vect x y = Vect (fClamp x l r) (fClamp y b t)

-- | Returns a copy of @v@ wrapped to the bounding box @bb@.
bbWrapVect
  :: BB   -- ^ bb
  -> Vect -- ^ v
  -> Vect
BB l b r t `bbWrapVect` Vect x y = Vect (l + ((x - l) `mod'` abs (r - l))) (b + ((y - b) `mod'` abs (t - b)))

foreign import ccall unsafe "Chiphunk/Low/BB.chs.h __c2hs_wrapped__w_cpBBSegmentQuery"
  bbSegmentQuery'_ :: ((BBPtr) -> ((VectPtr) -> ((VectPtr) -> (IO C2HSImp.CDouble))))

foreign import ccall unsafe "Chiphunk/Low/BB.chs.h __c2hs_wrapped__w_cpBBIntersectsSegment"
  bbIntersectsSegment'_ :: ((BBPtr) -> ((VectPtr) -> ((VectPtr) -> (IO C2HSImp.CUChar))))