{-# LANGUAGE NamedFieldPuns #-}
module Geometry
( Point(..)
, Line(..)
, Angle(..)
, intersectLineLine
, distanceFromOrigin
, distanceLineFromOrigin
, perpendicularThroughPoint
, angleFromOrigin
, normalizeAngle
, lengthOfRayUntilIntersect
) where
import Data.Fixed (mod')
data Point =
Point Double
Double
data Line = Line
{ Line -> Double
slope :: Double
, Line -> Double
intercept :: Double
}
newtype Angle =
Radians Double
intersectLineLine :: Line -> Line -> Point
intersectLineLine :: Line -> Line -> Point
intersectLineLine Line
a Line
b =
let x :: Double
x = (Line -> Double
intercept Line
a Double -> Double -> Double
forall a. Num a => a -> a -> a
- Line -> Double
intercept Line
b) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Line -> Double
slope Line
b Double -> Double -> Double
forall a. Num a => a -> a -> a
- Line -> Double
slope Line
a)
y :: Double
y = Line -> Double
slope Line
a Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Line -> Double
intercept Line
a
in Double -> Double -> Point
Point Double
x Double
y
distanceFromOrigin :: Point -> Double
distanceFromOrigin :: Point -> Double
distanceFromOrigin (Point Double
x Double
y) = Double -> Double
forall a. Floating a => a -> a
sqrt (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
y)
distanceLineFromOrigin :: Line -> Double
distanceLineFromOrigin :: Line -> Double
distanceLineFromOrigin Line {Double
slope :: Line -> Double
slope :: Double
slope, Double
intercept :: Line -> Double
intercept :: Double
intercept} =
Double -> Double
forall a. Num a => a -> a
abs Double
intercept Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double -> Double
forall a. Floating a => a -> a
sqrt (Double
slope Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
slope Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
1)
perpendicularThroughPoint :: Line -> Point -> Line
perpendicularThroughPoint :: Line -> Point -> Line
perpendicularThroughPoint Line {Double
slope :: Line -> Double
slope :: Double
slope} (Point Double
x Double
y) =
let slope' :: Double
slope' = -Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
slope
intercept' :: Double
intercept' = Double
y Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
slope' Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x
in Line {slope :: Double
slope = Double
slope', intercept :: Double
intercept = Double
intercept'}
angleFromOrigin :: Point -> Angle
angleFromOrigin :: Point -> Angle
angleFromOrigin (Point Double
x Double
y) = Double -> Angle
Radians (Double -> Angle) -> Double -> Angle
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
forall a. RealFloat a => a -> a -> a
atan2 Double
y Double
x
normalizeAngle :: Angle -> Angle
normalizeAngle :: Angle -> Angle
normalizeAngle (Radians Double
theta) = Double -> Angle
Radians (Double -> Angle) -> Double -> Angle
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
forall a. Real a => a -> a -> a
mod' Double
theta (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi)
lengthOfRayUntilIntersect :: Angle -> Line -> Double
lengthOfRayUntilIntersect :: Angle -> Line -> Double
lengthOfRayUntilIntersect (Radians Double
theta) Line {Double
slope :: Line -> Double
slope :: Double
slope, Double
intercept :: Line -> Double
intercept :: Double
intercept} =
Double
intercept Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double -> Double
forall a. Floating a => a -> a
sin Double
theta Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
slope Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
theta)