packages feed

edge-0.8: Trigonometry.hs

module Trigonometry where

import Data.Maybe

radToDeg :: Floating a => a -> a
radToDeg x = x * 180 / pi

mulSV :: Double -> (Double, Double) -> (Double, Double)
mulSV s (x, y) = (s * x, s * y)

distance :: (Double, Double) -> (Double, Double) -> Double
distance (x1, y1) (x2, y2) = sqrt ((x2 - x1)**2 + (y2 - y1)**2)

normAngle :: Double -> Double -- radians
normAngle x = if x >= 0 then asin (sin x)
                       else 2 * pi + asin (sin x)

vectorDirection :: (Double, Double) -- vector
                -> Double -- angle in radians
vectorDirection (0, 0) = 0.0 / 0.0 -- NaN
vectorDirection (x, y)
  | x >= 0 && y >= 0 = a
  | x < 0 && y >= 0 = pi - a
  | x < 0 && y < 0 = pi + a
  | otherwise = 2 * pi - a
  where a = atan (abs y / abs x)

-- let x = 2 * pi + pi / 2 in asin (sin x)
-- let x = (- (2*pi)) + (- (pi / 2)) in 2*pi + asin (sin x)

{-
  Assumes source (origin of projectile) is at origin of grid (0, 0) and so
  target center is relative to this. Assumes source is stationary and so
  velocity of target is relative to source.
-}
targetingA :: Double -> (Double, Double) -> (Double, Double) -> Double
targetingA pSpeed tCenter tVelocity = targetingA'
                                        pSpeed tCenter tVelocity Nothing 3

  where targetingA' pSpeed oCenter tVelocity nCenter iter =
          let eCenter = fromMaybe oCenter nCenter in
          let d = distance (0, 0) eCenter in
          let t = d / pSpeed in
          let aCenter = addV oCenter (mulSV t tVelocity) in
          if iter > 0
            then targetingA' pSpeed oCenter tVelocity (Just aCenter) (iter - 1)
            else vectorDirection aCenter

addV :: (Double, Double) -> (Double, Double) -> (Double, Double)
addV (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)

subV :: (Double, Double) -> (Double, Double) -> (Double, Double)
subV (x1, y1) (x2, y2) = (x1 - x2, y1 - y2)

doubleRem :: Double -> Double -> Double
doubleRem x y = let a = x / y in
                (a - (fromIntegral (truncate a))) * y