{-# LANGUAGE MultiParamTypeClasses #-}
module Geometry.Flat.TwoD.Space
  ( Point(..)
  , Geodesic(..)
  ) where

import Geometry.Class
import Geometry.Utils (fixAngle)

data Point = Point{ pX, pY :: !Double } deriving Show
data Geodesic = Geodesic{ gO :: !Point, gX, gY :: !Double } deriving Show
  
instance Geometry Point Geodesic where

  distance (Point u v) (Point x y) =
    let dx = x - u
        dy = y - v
    in  sqrt (dx * dx + dy * dy)

  angle (Point p q) (Point u v) (Point x y) =
    let du = u - p
        dv = v - q
        dx = x - p
        dy = y - q
        uv = atan2 dv du
        xy = atan2 dy dx
    in  fixAngle (xy - uv)

  geodesic p@(Point u v) (Point x y) =
    let dx = x - u
        dy = y - v
        d = sqrt (dx * dx + dy * dy)
    in  Geodesic p (dx / d) (dy / d)

  rotate a (Point u v) (Point x y) =
    let co = cos a
        si = sin a
        p = x - u
        q = y - v
    in  Point (u + co * p - si * q) (v + si * p + co * q)

  translate d (Geodesic _ dx dy) (Point x y) = Point (x + d * dx) (y + d * dy)

  midpoint (Point u v) (Point x y) = Point (0.5 * (u + x)) (0.5 * (v + y))

instance Embedding Point Point where
  embed = id
  model = Just