module Apecs.Physics.Geometry where

import Apecs.Physics.Types
import Linear

vertices :: Convex -> [BVec]
vertices :: Convex -> [BVec]
vertices (Convex [BVec]
s Double
_) = [BVec]
s

-- | Map a function over all vertices
mapVertices :: (BVec -> BVec) -> Convex -> Convex
mapVertices :: (BVec -> BVec) -> Convex -> Convex
mapVertices BVec -> BVec
f (Convex [BVec]
s Double
r) = [BVec] -> Double -> Convex
Convex (BVec -> BVec
f (BVec -> BVec) -> [BVec] -> [BVec]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [BVec]
s) Double
r

-- | Translates all vertices. The name shift is to prevent collisions with gloss
shift :: BVec -> Convex -> Convex
shift :: BVec -> Convex -> Convex
shift = (BVec -> BVec) -> Convex -> Convex
mapVertices ((BVec -> BVec) -> Convex -> Convex)
-> (BVec -> BVec -> BVec) -> BVec -> Convex -> Convex
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BVec -> BVec -> BVec
forall a. Num a => a -> a -> a
(+)

getRadius :: Convex -> Double
getRadius :: Convex -> Double
getRadius (Convex [BVec]
_ Double
r) = Double
r

setRadius :: Double -> Convex -> Convex
setRadius :: Double -> Convex -> Convex
setRadius Double
r (Convex [BVec]
s Double
_) = [BVec] -> Double -> Convex
Convex [BVec]
s Double
r

cCircle, zCircle :: Double -> Convex
cCircle :: Double -> Convex
cCircle Double
r = BVec -> Double -> Convex
oCircle BVec
0 Double
r
zCircle :: Double -> Convex
zCircle = Double -> Convex
cCircle

oCircle :: BVec -> Double -> Convex
oCircle :: BVec -> Double -> Convex
oCircle BVec
o Double
r = [BVec] -> Double -> Convex
Convex [BVec
o] Double
r

hLine, vLine :: Double -> Convex
hLine :: Double -> Convex
hLine Double
l = [BVec] -> Double -> Convex
Convex [Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 (-Double
lDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) Double
0, Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 (Double
lDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2) Double
0] Double
0
vLine :: Double -> Convex
vLine Double
l = [BVec] -> Double -> Convex
Convex [Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 Double
0 (Double
lDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2), Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 Double
0 (-Double
lDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
2)] Double
0

-- | Centered rectangle with a given size
cRectangle :: BVec -> Convex
cRectangle :: BVec -> Convex
cRectangle BVec
s = BVec -> BVec -> Convex
oRectangle (-BVec
sBVec -> BVec -> BVec
forall a. Num a => a -> a -> a
*BVec
0.5) BVec
s

-- | Rectangle with a given origin and size
oRectangle :: BVec -> BVec -> Convex
oRectangle :: BVec -> BVec -> Convex
oRectangle (V2 Double
x Double
y) (V2 Double
w Double
h) = [BVec] -> Double -> Convex
Convex [Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 Double
x Double
y, Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 Double
x (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
h), Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
w) (Double
yDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
h), Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 (Double
xDouble -> Double -> Double
forall a. Num a => a -> a -> a
+Double
w) Double
y] Double
0

-- | Rectangle with origin 0 and given size
zRectangle :: BVec -> Convex
zRectangle :: BVec -> Convex
zRectangle BVec
s = BVec -> BVec -> Convex
oRectangle BVec
0 BVec
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 -> [Convex]
toEdges (Convex [] Double
_) = []
toEdges (Convex [BVec
_] Double
_) = []
toEdges (Convex [BVec]
vs Double
r) = (BVec -> BVec -> Convex) -> [BVec] -> [BVec] -> [Convex]
forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\BVec
h BVec
t -> [BVec] -> Double -> Convex
Convex [BVec
h,BVec
t] Double
r) [BVec]
vs ([BVec] -> [BVec]
forall a. [a] -> [a]
tail ([BVec] -> [BVec]) -> ([BVec] -> [BVec]) -> [BVec] -> [BVec]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [BVec] -> [BVec]
forall a. [a] -> [a]
cycle ([BVec] -> [BVec]) -> [BVec] -> [BVec]
forall a b. (a -> b) -> a -> b
$ [BVec]
vs)

-- | A set of lines forming a grid. Returns (r + c + 2) segments.
gridLines :: Vec -> Int -> Int -> [Convex]
gridLines :: BVec -> Int -> Int -> [Convex]
gridLines BVec
size Int
c Int
r =
  [ BVec -> Convex -> Convex
shift (Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 Double
x Double
0) (Double -> Convex
vLine Double
h) | Double
x <- [Double]
xs ] [Convex] -> [Convex] -> [Convex]
forall a. [a] -> [a] -> [a]
++
  [ BVec -> Convex -> Convex
shift (Double -> Double -> BVec
forall a. a -> a -> V2 a
V2 Double
0 Double
y) (Double -> Convex
hLine Double
w) | Double
y <- [Double]
ys ]
  where
    V2 Double
w Double
h = BVec
size
    V2 Double
x Double
y = -BVec
sizeBVec -> BVec -> BVec
forall a. Num a => a -> a -> a
*BVec
0.5
    dx :: Double
dx = Double
wDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
c
    dy :: Double
dy = Double
hDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
r
    xs :: [Double]
xs = [Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
dx | Int
n <- [Int
0..Int
c]]
    ys :: [Double]
ys = [Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
dy | Int
n <- [Int
0..Int
r]]