Skip to content

Instantly share code, notes, and snippets.

@reuk
Last active December 21, 2015 15:29
Show Gist options
  • Save reuk/6326924 to your computer and use it in GitHub Desktop.
Save reuk/6326924 to your computer and use it in GitHub Desktop.
I'm quite pleased with this one.
import Control.Applicative
data Vec2 a = Vec2 (a, a) deriving (Eq, Show)
instance Functor Vec2 where
fmap f (Vec2 (x, y)) = Vec2 (f x, f y)
instance Applicative Vec2 where
pure x = Vec2 (x, x)
(Vec2 (f, g)) <*> (Vec2 (x, y)) = Vec2 (f x, g y)
instance Num a => Num (Vec2 a) where
(+) = (<*>) . (<$>) (+)
(-) = (<*>) . (<$>) (-)
(*) = (<*>) . (<$>) (*)
abs = fmap abs
signum = fmap signum
fromInteger = pure . fromInteger
magnitude (Vec2 (x, y)) = sqrt ((x * x) + (y * y))
distance a b = magnitude (a - b)
normalize (Vec2 (x, y)) = Vec2 (x / n, y / n)
where n = magnitude (Vec2 (x, y))
dot (Vec2 (x1, y1)) (Vec2 (x2, y2)) = (x1 * x2) + (y1 * y2)
reflection x y = y - (2 * x * c) where c = pure (dot x y)
normal (Vec2 (x, y)) = normalize (Vec2 (4 * x, y))
data Ray a = Ray (Vec2 a) (Vec2 a) deriving (Eq, Show)
intersection (Ray (Vec2 (x1, y1)) (Vec2 (x2, y2))) = if d p1 > d p2 then p1 else p2
where m = y2 / x2
c = y1 - (m * x1)
f = pointOnEllipse m c
p1 = f (+)
p2 = f (-)
d = distance (Vec2 (x1, y1))
pointOnEllipse m c f = Vec2 (x, y)
where i = (sq m) + 4
j = 2 * m * c
k = (sq c) - 100
x = (f (-j) (sqrt ((sq j) - (4 * i * k)))) / (2 * i)
y = (m * x) + c
sq a = a * a
reflect (Ray point direction) = Ray pos (reflection nor (normalize direction))
where pos = intersection (Ray point direction)
nor = normal pos
solve (Ray (Vec2 (x, y)) d) | -0.01 <= x && x <= 0.01 && y > 0 = 0
| otherwise = 1 + solve (reflect (Ray (Vec2 (x, y)) d))
r = Ray(Vec2(0,10.1))(Vec2(1.4,-19.7))
go = solve (reflect r)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment