{- ORMOLU_DISABLE -}
-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
-- Copyright 2016, Julia Longtin (julial@turinglace.com)
-- Released under the GNU AGPLV3+, see LICENSE

module Graphics.Implicit.ObjectUtil.GetBox2 (getBox2, getBox2R) where

import Prelude(pure, fmap, Eq, (==), (.), (<$>), (||), unzip, minimum, maximum, ($), (/), (-), (+), (*), cos, sin, sqrt, min, max, (<), (<>), pi, atan2, (==), (>), show, (&&), otherwise, error)

import Graphics.Implicit.Definitions
    ( SymbolicObj2(Square, Circle, Polygon, Rotate2, Transform2, Shared2),
      SharedObj(IntersectR, Complement, UnionR, DifferenceR),
      Box2,
      ℝ2,
      ,
      minℝ )

import Data.Fixed (mod')

import Graphics.Implicit.ObjectUtil.GetBoxShared (emptyBox, corners, outsetBox, intersectBoxes, pointsBox, getBoxShared, unionBoxes)

-- To construct vectors of ℝs.
import Linear (V2(V2), V3(V3))
import qualified Linear

-- Get a Box2 around the given object.
getBox2 :: SymbolicObj2 -> Box2
-- Primitives
getBox2 :: SymbolicObj2 -> Box2
getBox2 (Square ℝ2
size) = (ℝ -> ℝ2
forall (f :: * -> *) a. Applicative f => a -> f a
pure 0, ℝ2
size)
getBox2 (Circle r) = (ℝ -> ℝ2
forall (f :: * -> *) a. Applicative f => a -> f a
pure (-r), ℝ -> ℝ2
forall (f :: * -> *) a. Applicative f => a -> f a
pure r)
getBox2 (Polygon [ℝ2]
points) = [ℝ2] -> Box2
forall (f :: * -> *) a.
(Applicative f, Num a, VectorStuff (f a)) =>
[f a] -> (f a, f a)
pointsBox [ℝ2]
points
-- (Rounded) CSG
-- Simple transforms
getBox2 (Rotate2 θ SymbolicObj2
symbObj) =
    let rotate :: ℝ2 -> ℝ2
rotate (V2 x y) = ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 (xℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℝ -> ℝ
forall a. Floating a => a -> a
cos θ ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
- yℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℝ -> ℝ
forall a. Floating a => a -> a
sin θ) (xℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℝ -> ℝ
forall a. Floating a => a -> a
sin θ ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ yℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℝ -> ℝ
forall a. Floating a => a -> a
cos θ)
     in [ℝ2] -> Box2
forall (f :: * -> *) a.
(Applicative f, Num a, VectorStuff (f a)) =>
[f a] -> (f a, f a)
pointsBox ([ℝ2] -> Box2) -> [ℝ2] -> Box2
forall a b. (a -> b) -> a -> b
$ (ℝ2 -> ℝ2) -> [ℝ2] -> [ℝ2]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ℝ2 -> ℝ2
rotate ([ℝ2] -> [ℝ2]) -> [ℝ2] -> [ℝ2]
forall a b. (a -> b) -> a -> b
$ Box2 -> [ℝ2]
forall vec. VectorStuff vec => (vec, vec) -> [vec]
corners (Box2 -> [ℝ2]) -> Box2 -> [ℝ2]
forall a b. (a -> b) -> a -> b
$ SymbolicObj2 -> Box2
getBox2 SymbolicObj2
symbObj
getBox2 (Transform2 M33 ℝ
m SymbolicObj2
symbObj) =
    let box :: Box2
box = SymbolicObj2 -> Box2
getBox2 SymbolicObj2
symbObj
        augment :: V2 a -> V3 a
augment (V2 a
x a
y) = (a -> a -> a -> V3 a
forall a. a -> a -> a -> V3 a
V3 a
x a
y a
1)
        normalize :: V3 a -> V2 a
normalize (V3 a
x a
y a
w) = (a -> a -> V2 a
forall a. a -> a -> V2 a
V2 (a
xa -> a -> a
forall a. Fractional a => a -> a -> a
/a
w) (a
ya -> a -> a
forall a. Fractional a => a -> a -> a
/a
w))
     in [ℝ2] -> Box2
forall (f :: * -> *) a.
(Applicative f, Num a, VectorStuff (f a)) =>
[f a] -> (f a, f a)
pointsBox ([ℝ2] -> Box2) -> [ℝ2] -> Box2
forall a b. (a -> b) -> a -> b
$ V3 ℝ -> ℝ2
forall a. Fractional a => V3 a -> V2 a
normalize (V3 ℝ -> ℝ2) -> (ℝ2 -> V3 ℝ) -> ℝ2 -> ℝ2
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (M33 ℝ
m M33 ℝ -> V3 ℝ -> V3 ℝ
forall (m :: * -> *) (r :: * -> *) a.
(Functor m, Foldable r, Additive r, Num a) =>
m (r a) -> r a -> m a
Linear.!*) (V3 ℝ -> V3 ℝ) -> (ℝ2 -> V3 ℝ) -> ℝ2 -> V3 ℝ
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ℝ2 -> V3 ℝ
forall a. Num a => V2 a -> V3 a
augment (ℝ2 -> ℝ2) -> [ℝ2] -> [ℝ2]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Box2 -> [ℝ2]
forall vec. VectorStuff vec => (vec, vec) -> [vec]
corners Box2
box
getBox2 (Shared2 SharedObj SymbolicObj2 V2 ℝ
obj) = SharedObj SymbolicObj2 V2 ℝ -> Box2
forall obj (f :: * -> *) a.
(Object obj f a, VectorStuff (f a), ComponentWiseMultable (f a),
 Fractional a, Metric f) =>
SharedObj obj f a -> (f a, f a)
getBoxShared SharedObj SymbolicObj2 V2 ℝ
obj

-- | Define a Box2 around the given object, and the space it occupies while rotating about the center point.
--   Note: No implementations for Square, Translate2, or Scale2 as they would be identical to the fallthrough.
getBox2R :: SymbolicObj2 ->  -> Box2
getBox2R :: SymbolicObj2 -> ℝ -> Box2
getBox2R (Circle r) _ = SymbolicObj2 -> Box2
getBox2 (SymbolicObj2 -> Box2) -> SymbolicObj2 -> Box2
forall a b. (a -> b) -> a -> b
$ ℝ -> SymbolicObj2
Circle r
getBox2R (Polygon [ℝ2]
points) deg =
  let
    pointRBoxes :: [Box2]
pointRBoxes = [ ℝ2 -> ℝ -> Box2
pointRBox ℝ2
point deg | ℝ2
point <- [ℝ2]
points ]
    ([ℝ2]
pointValsMin, [ℝ2]
pointValsMax) = [Box2] -> ([ℝ2], [ℝ2])
forall a b. [(a, b)] -> ([a], [b])
unzip [Box2]
pointRBoxes
    unbox :: ℝ2 -> (, )
    unbox :: ℝ2 -> (ℝ, ℝ)
unbox (V2 x y) = (x, y)
    ([ℝ]
pointValsX, [ℝ]
pointValsY) = [(ℝ, ℝ)] -> ([ℝ], [ℝ])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(ℝ, ℝ)] -> ([ℝ], [ℝ])) -> [(ℝ, ℝ)] -> ([ℝ], [ℝ])
forall a b. (a -> b) -> a -> b
$ (ℝ2 -> (ℝ, ℝ)) -> [ℝ2] -> [(ℝ, ℝ)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ℝ2 -> (ℝ, ℝ)
unbox ([ℝ2] -> [(ℝ, ℝ)]) -> [ℝ2] -> [(ℝ, ℝ)]
forall a b. (a -> b) -> a -> b
$ [ℝ2]
pointValsMin [ℝ2] -> [ℝ2] -> [ℝ2]
forall a. Semigroup a => a -> a -> a
<> [ℝ2]
pointValsMax
  in
    (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 ([ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [ℝ]
pointValsX)( [ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [ℝ]
pointValsY), ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 ([ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [ℝ]
pointValsX) ([ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [ℝ]
pointValsY))
getBox2R (Shared2 (Complement SymbolicObj2
symObj)) _ = SymbolicObj2 -> Box2
getBox2 (SymbolicObj2 -> Box2) -> SymbolicObj2 -> Box2
forall a b. (a -> b) -> a -> b
$ SharedObj SymbolicObj2 V2 ℝ -> SymbolicObj2
Shared2 (SymbolicObj2 -> SharedObj SymbolicObj2 V2 ℝ
forall obj (f :: * -> *) a. obj -> SharedObj obj f a
Complement SymbolicObj2
symObj)
getBox2R (Shared2 (UnionR r [SymbolicObj2]
symObjs)) deg =
    ℝ -> [Box2] -> Box2
forall (f :: * -> *) a.
(VectorStuff (f a), Applicative f, Eq (f a), Num a, Num (f a)) =>
ℝ -> [(f a, f a)] -> (f a, f a)
unionBoxes r ([Box2] -> Box2) -> [Box2] -> Box2
forall a b. (a -> b) -> a -> b
$ (SymbolicObj2 -> Box2) -> [SymbolicObj2] -> [Box2]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (SymbolicObj2 -> ℝ -> Box2
`getBox2R` deg) [SymbolicObj2]
symObjs
getBox2R (Shared2 (DifferenceR _ SymbolicObj2
symObj [SymbolicObj2]
_)) deg = SymbolicObj2 -> ℝ -> Box2
getBox2R SymbolicObj2
symObj deg
getBox2R (Shared2 (IntersectR r [SymbolicObj2]
symObjs)) deg =
  let
    boxes :: [Box2]
boxes = [ SymbolicObj2 -> ℝ -> Box2
getBox2R SymbolicObj2
obj deg| SymbolicObj2
obj <- [SymbolicObj2]
symObjs ]
  in
    ℝ -> Box2 -> Box2
forall a. (VectorStuff a, Num a) => ℝ -> (a, a) -> (a, a)
outsetBox r (Box2 -> Box2) -> Box2 -> Box2
forall a b. (a -> b) -> a -> b
$ [Box2] -> Box2
forall a. VectorStuff a => [(a, a)] -> (a, a)
intersectBoxes [Box2]
boxes
-- FIXME: implement Rotate2.
-- Fallthrough: rotate the points of the containing box. no rounding.
getBox2R SymbolicObj2
symObj deg =
  let
    origBox :: Box2
origBox = SymbolicObj2 -> Box2
getBox2 SymbolicObj2
symObj
    points :: [ℝ2]
points  = Box2 -> [ℝ2]
forall vec. VectorStuff vec => (vec, vec) -> [vec]
corners Box2
origBox
  in
    SymbolicObj2 -> ℝ -> Box2
getBox2R ([ℝ2] -> SymbolicObj2
Polygon [ℝ2]
points) deg

data Quadrant  = UpperRight | UpperLeft | LowerRight | LowerLeft
  deriving Quadrant -> Quadrant -> Bool
(Quadrant -> Quadrant -> Bool)
-> (Quadrant -> Quadrant -> Bool) -> Eq Quadrant
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Quadrant -> Quadrant -> Bool
$c/= :: Quadrant -> Quadrant -> Bool
== :: Quadrant -> Quadrant -> Bool
$c== :: Quadrant -> Quadrant -> Bool
Eq
data Axis      = PosX | PosY | NegX | NegY
  deriving Axis -> Axis -> Bool
(Axis -> Axis -> Bool) -> (Axis -> Axis -> Bool) -> Eq Axis
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Axis -> Axis -> Bool
$c/= :: Axis -> Axis -> Bool
== :: Axis -> Axis -> Bool
$c== :: Axis -> Axis -> Bool
Eq
data Position  = OnAxis Axis | InQuadrant Quadrant | CenterPoint
data HasRotation = Rotation Direction | None
  deriving HasRotation -> HasRotation -> Bool
(HasRotation -> HasRotation -> Bool)
-> (HasRotation -> HasRotation -> Bool) -> Eq HasRotation
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: HasRotation -> HasRotation -> Bool
$c/= :: HasRotation -> HasRotation -> Bool
== :: HasRotation -> HasRotation -> Bool
$c== :: HasRotation -> HasRotation -> Bool
Eq
data Direction = Clockwise | CounterClockwise
  deriving Direction -> Direction -> Bool
(Direction -> Direction -> Bool)
-> (Direction -> Direction -> Bool) -> Eq Direction
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Direction -> Direction -> Bool
$c/= :: Direction -> Direction -> Bool
== :: Direction -> Direction -> Bool
$c== :: Direction -> Direction -> Bool
Eq

-- | put a box around a point, and all of the locations it will be at during an x degree arc around (0,0).
pointRBox :: ℝ2 ->  -> Box2
pointRBox :: ℝ2 -> ℝ -> Box2
pointRBox (V2 xStart yStart) travel =
  let
    k :: 
    k :: ℝ
k = ℝ
forall a. Floating a => a
piℝ -> ℝ -> ℝ
forall a. Fractional a => a -> a -> a
/180
    -- determine the distance of our input point from from the axis of rotation.
    distance :: ℝ
distance = ℝ -> ℝ
forall a. Floating a => a -> a
sqrt (ℝ -> ℝ) -> ℝ -> ℝ
forall a b. (a -> b) -> a -> b
$ xStartℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*xStart ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ yStartℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*yStart
    -- radian starting position.
    θstart :: ℝ
θstart = ℝ -> ℝ -> ℝ
forall a. RealFloat a => a -> a -> a
atan2 yStart xStart
    -- logical starting position
    startPosition :: Position
startPosition = ℝ -> ℝ -> Position
positionOf distance (ℝ -> Position) -> ℝ -> Position
forall a b. (a -> b) -> a -> b
$ ℝ -> ℝ
absrad θstart

    -- take the input point. rotate it. see where it stops.

    -- how far we should rotate our point.
    rotationAmount :: ℝ
rotationAmount = travel ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
* k
    -- what direction are we rotating.
    rotationDirection :: HasRotation
rotationDirection = case travel of
      polarity | polarity ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> 0  -> Direction -> HasRotation
Rotation Direction
CounterClockwise
               | polarity ℝ -> ℝ -> Bool
forall a. Eq a => a -> a -> Bool
== 0 -> HasRotation
None
      _                        -> Direction -> HasRotation
Rotation Direction
Clockwise
    -- stopping position of our point.
    θstop :: ℝ
θstop = ℝ -> ℝ
absrad (ℝ -> ℝ) -> ℝ -> ℝ
forall a b. (a -> b) -> a -> b
$ θstart ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+ rotationAmount
    stopPosition :: Position
stopPosition = ℝ -> ℝ -> Position
positionOf distance θstop
    (xStop, yStop) =
      case ℝ -> ℝ -> Position
positionOf distance θstop of
        Position
CenterPoint -> (0,0)
        OnAxis Axis
PosX -> (distance,0)
        OnAxis Axis
PosY -> (0,distance)
        OnAxis Axis
NegX -> (-distance,0)
        OnAxis Axis
NegY -> (0,-distance)
        InQuadrant Quadrant
_ -> ( distanceℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℝ -> ℝ
forall a. Floating a => a -> a
cos θstop, distanceℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*ℝ -> ℝ
forall a. Floating a => a -> a
sin θstop)

    -- observe what the initial position was, and what the end position is.
    -- check which quadrants they're in, and what direction the rotation was.

    (minX, minY, maxX, maxY) = (ℝ -> ℝ -> ℝ
forall a. Ord a => a -> a -> a
min xStart xStop, ℝ -> ℝ -> ℝ
forall a. Ord a => a -> a -> a
min yStart yStop, ℝ -> ℝ -> ℝ
forall a. Ord a => a -> a -> a
max xStart xStop, ℝ -> ℝ -> ℝ
forall a. Ord a => a -> a -> a
max yStart yStop)
    positionOf ::  ->  -> Position
    positionOf :: ℝ -> ℝ -> Position
positionOf d θpos
      | d ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< minℝ                      = Position
CenterPoint
      | θpos ℝ -> ℝ -> Bool
forall a. Eq a => a -> a -> Bool
== 0 Bool -> Bool -> Bool
|| θpos ℝ -> ℝ -> Bool
forall a. Eq a => a -> a -> Bool
== 360ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k    = Axis -> Position
OnAxis Axis
PosX
      | θpos ℝ -> ℝ -> Bool
forall a. Eq a => a -> a -> Bool
== 90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k                  = Axis -> Position
OnAxis Axis
PosY
      | θpos ℝ -> ℝ -> Bool
forall a. Eq a => a -> a -> Bool
== 180ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
|| θpos ℝ -> ℝ -> Bool
forall a. Eq a => a -> a -> Bool
== -0   = Axis -> Position
OnAxis Axis
NegX
      | θpos ℝ -> ℝ -> Bool
forall a. Eq a => a -> a -> Bool
== 270ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k                 = Axis -> Position
OnAxis Axis
NegY
      | θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> 0 Bool -> Bool -> Bool
&& θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k       = Quadrant -> Position
InQuadrant Quadrant
UpperRight
      | θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> 90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&& θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 180ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k   = Quadrant -> Position
InQuadrant Quadrant
UpperLeft
      | θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> 180ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&& θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 270ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k  = Quadrant -> Position
InQuadrant Quadrant
LowerLeft
      | θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> 270ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&& θpos ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 360ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k  = Quadrant -> Position
InQuadrant Quadrant
LowerRight
      | Bool
otherwise                     = [Char] -> Position
forall a. HasCallStack => [Char] -> a
error ([Char] -> Position) -> [Char] -> Position
forall a b. (a -> b) -> a -> b
$ [Char]
"illegal position in positionOf: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> ℝ -> [Char]
forall a. Show a => a -> [Char]
show (θposℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k) [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" pos: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> ℝ -> [Char]
forall a. Show a => a -> [Char]
show θpos [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> [Char]
" d: " [Char] -> [Char] -> [Char]
forall a. Semigroup a => a -> a -> a
<> ℝ -> [Char]
forall a. Show a => a -> [Char]
show d
    -- returns position around a circle in radians, from 0 to 2pi.
    absrad ::  -> 
    absrad :: ℝ -> ℝ
absrad rad
      | rad ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> (360ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k) = rad ℝ -> ℝ -> ℝ
forall a. Real a => a -> a -> a
`mod'` (360ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k)
      | rad ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 0       = ℝ -> ℝ
absrad (360ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k)ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
+rad
      | Bool
otherwise     = rad

    -- now, if you passed through an axis, then the box must be expanded to include distance from axis of rotation in that direction.
    -- otherwise, put a box around the start and stop positions.

    distanceBox :: Box2
    distanceBox :: Box2
distanceBox = (ℝ -> ℝ2
forall (f :: * -> *) a. Applicative f => a -> f a
pure (-distance), ℝ -> ℝ2
forall (f :: * -> *) a. Applicative f => a -> f a
pure distance)

    noAxis :: Quadrant -> Quadrant -> Direction ->  -> Box2
    noAxis :: Quadrant -> Quadrant -> Direction -> ℝ -> Box2
noAxis Quadrant
q1 Quadrant
q2 Direction
dir amount
      | Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
q2 Bool -> Bool -> Bool
&& amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&& amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> -90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k = (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 minX  minY, ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 maxX maxY)
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft  = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
PosY Quadrant
q2 Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
PosX Quadrant
q2 Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft  = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
NegY Quadrant
q2 Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
NegX Quadrant
q2 Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
PosX Quadrant
q2 Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft  = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
PosY Quadrant
q2 Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft  = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
NegX Quadrant
q2 Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&& Quadrant
q1 Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight = Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
NegY Quadrant
q2 Direction
dir amount
    noAxis Quadrant
_ Quadrant
_ Direction
_ _ = Box2
distanceBox
    oneAxis :: Axis -> Quadrant -> Direction ->  -> Box2
    oneAxis :: Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
axis Quadrant
quadrant Direction
dir amount
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&&
        amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&& amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> -90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight))  = (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 minX minY, ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 maxX maxY)
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&&
        amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&& amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> -90ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight))  = (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 minX minY, ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 maxX maxY)
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight))  = Axis -> Direction -> Box2
crossOne Axis
axis Direction
dir
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight))  = Axis -> Direction -> Box2
crossOne Axis
axis Direction
dir
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight))  = Axis -> Direction -> Box2
crossTwo Axis
axis Direction
dir
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight))  = Axis -> Direction -> Box2
crossTwo Axis
axis Direction
dir
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight))  = Axis -> Box2
crossThree Axis
axis
      | Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise Bool -> Bool -> Bool
&&
        ((Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerRight) Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
LowerLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperLeft)  Bool -> Bool -> Bool
||
         (Axis
axis Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Quadrant
quadrant Quadrant -> Quadrant -> Bool
forall a. Eq a => a -> a -> Bool
== Quadrant
UpperRight))  = Axis -> Box2
crossThree Axis
axis
      | Bool
otherwise = Box2
distanceBox
    twoAxis :: Axis -> Axis -> Direction -> Box2
    twoAxis :: Axis -> Axis -> Direction -> Box2
twoAxis Axis
start Axis
stop Direction
dir
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY)  = Axis -> Direction -> Box2
crossOne Axis
start Direction
dir
    twoAxis Axis
start Axis
stop Direction
dir
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX)  = if Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise
                                           then (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 minX minY, ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 maxX maxY)
                                           else Axis -> Direction -> Box2
crossTwo Axis
start Direction
dir
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY) Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Axis
stop Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX)  = if Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise
                                           then (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 minX minY, ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 maxX maxY)
                                           else Axis -> Direction -> Box2
crossTwo Axis
start Direction
dir
    twoAxis Axis
_ Axis
_ Direction
_ = Box2
distanceBox
    crossOne :: Axis -> Direction -> Box2
    crossOne :: Axis -> Direction -> Box2
crossOne Axis
start Direction
dir
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [(0,-distance)]
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [(-distance, 0)]
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [(0, distance)]
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [( distance, 0)]
      | Bool
otherwise = Box2
distanceBox
    crossTwo :: Axis -> Direction -> Box2
    crossTwo :: Axis -> Direction -> Box2
crossTwo Axis
start Direction
dir
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [(-distance, 0), ( 0,-distance)]
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [( distance, 0), ( 0,-distance)]
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [( distance, 0), ( 0, distance)]
      | (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
NegY Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
Clockwise)        Bool -> Bool -> Bool
||
        (Axis
start Axis -> Axis -> Bool
forall a. Eq a => a -> a -> Bool
== Axis
PosX Bool -> Bool -> Bool
&& Direction
dir Direction -> Direction -> Bool
forall a. Eq a => a -> a -> Bool
== Direction
CounterClockwise)  = [(ℝ, ℝ)] -> Box2
mixWith [(-distance, 0), ( 0, distance)]
      | Bool
otherwise = Box2
distanceBox
    crossThree :: Axis -> Box2
    crossThree :: Axis -> Box2
crossThree Axis
PosX = [(ℝ, ℝ)] -> Box2
mixWith [( 0, distance), (-distance, 0), ( 0,-distance)]
    crossThree Axis
PosY = [(ℝ, ℝ)] -> Box2
mixWith [(-distance, 0), ( 0,-distance), ( distance, 0)]
    crossThree Axis
NegX = [(ℝ, ℝ)] -> Box2
mixWith [( 0,-distance), ( distance, 0), ( 0, distance)]
    crossThree Axis
NegY = [(ℝ, ℝ)] -> Box2
mixWith [( distance, 0), ( 0, distance), (-distance, 0)]
    -- TODO(sandy): clean me up to not use pairs
    mixWith :: [(,)] -> Box2
    mixWith :: [(ℝ, ℝ)] -> Box2
mixWith [(ℝ, ℝ)]
points = (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 ([ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [ℝ]
xPoints) ([ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum [ℝ]
yPoints), ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 ([ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [ℝ]
xPoints) ([ℝ] -> ℝ
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [ℝ]
yPoints))
                     where
                       ([ℝ]
xPoints, [ℝ]
yPoints) = [(ℝ, ℝ)] -> ([ℝ], [ℝ])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(ℝ, ℝ)] -> ([ℝ], [ℝ])) -> [(ℝ, ℝ)] -> ([ℝ], [ℝ])
forall a b. (a -> b) -> a -> b
$ [(ℝ, ℝ)]
points [(ℝ, ℝ)] -> [(ℝ, ℝ)] -> [(ℝ, ℝ)]
forall a. Semigroup a => a -> a -> a
<> [(xStart, yStart), (xStop, yStop)]
    invertRotation :: Direction -> Direction
    invertRotation :: Direction -> Direction
invertRotation Direction
Clockwise = Direction
CounterClockwise
    invertRotation Direction
CounterClockwise = Direction
Clockwise
  in
    case HasRotation
rotationDirection of
      HasRotation
None -> (ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 xStart yStart, ℝ -> ℝ -> ℝ2
forall a. a -> a -> V2 a
V2 xStart  yStart)
      Rotation Direction
dir -> case rotationAmount of
                 amount | amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
< 360ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k Bool -> Bool -> Bool
&& amount ℝ -> ℝ -> Bool
forall a. Ord a => a -> a -> Bool
> -360ℝ -> ℝ -> ℝ
forall a. Num a => a -> a -> a
*k ->
                          case Position
startPosition of
                            Position
CenterPoint -> Box2
forall (f :: * -> *) a. (Applicative f, Num a) => (f a, f a)
emptyBox
                            OnAxis Axis
axis -> case Position
stopPosition of
                                             OnAxis Axis
stopaxis         -> Axis -> Axis -> Direction -> Box2
twoAxis Axis
axis Axis
stopaxis Direction
dir
                                             InQuadrant Quadrant
stopquadrant -> Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
axis Quadrant
stopquadrant Direction
dir amount
                                             Position
CenterPoint -> Box2
forall (f :: * -> *) a. (Applicative f, Num a) => (f a, f a)
emptyBox
                            InQuadrant Quadrant
quadrant -> case Position
stopPosition of
                                             OnAxis Axis
stopaxis         -> Axis -> Quadrant -> Direction -> ℝ -> Box2
oneAxis Axis
stopaxis Quadrant
quadrant (Direction -> Direction
invertRotation Direction
dir) (-amount)
                                             InQuadrant Quadrant
stopquadrant -> Quadrant -> Quadrant -> Direction -> ℝ -> Box2
noAxis Quadrant
quadrant Quadrant
stopquadrant Direction
dir travel
                                             Position
CenterPoint -> Box2
forall (f :: * -> *) a. (Applicative f, Num a) => (f a, f a)
emptyBox
                 _                         ->
                            (ℝ -> ℝ2
forall (f :: * -> *) a. Applicative f => a -> f a
pure (-distance), ℝ -> ℝ2
forall (f :: * -> *) a. Applicative f => a -> f a
pure distance)