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

import Geometry.Class
import qualified Geometry.Flat.TwoD.Space as E

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

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

  angle _ _ _ = error "Geometry.Flat.ThreeD.Space.angle"

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

  rotate _ _ _ = error "Geometry.Flat.ThreeD.Space.rotate"

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

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

instance Embedding Point Point where
  embed = id
  model = Just

instance Embedding Point E.Point where
  embed (E.Point x y) = Point x y 0
  model (Point x y z)
    | z == 0 = Just (E.Point x y)
    | otherwise = Nothing