module DMS where
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif
import Control.Monad.Except
import Datum
import LatLng
data LatitudeDMS = North DMS
| South DMS
data LongitudeDMS = East DMS
| West DMS
data DMS = DMS { degrees :: Double
, minutes :: Double
, seconds :: Double
}
toLatLng :: LatitudeDMS -> LongitudeDMS -> Datum -> Except String LatLng
toLatLng lat lng dtm = do
lt <- withExcept (const "Invalid latitude") (evalLatitude lat)
ln <- withExcept (const "Invalid longitude") (evalLongitude lng)
pure LatLng { latitude = lt, longitude = ln, height = 0, datum = dtm }
where evalLatitude :: LatitudeDMS -> Except String Double
evalLatitude (North p) = dmsToLatLngPoint p 1
evalLatitude (South p) = dmsToLatLngPoint p (1)
evalLongitude :: LongitudeDMS -> Except String Double
evalLongitude (East p) = dmsToLatLngPoint p 1
evalLongitude (West p) = dmsToLatLngPoint p (1)
dmsToLatLngPoint :: DMS -> Double -> Except String Double
dmsToLatLngPoint DMS { degrees = d, minutes = m, seconds = s } cardinal
| d < 0.0 || m < 0.0 || s < 0.0 || d > 90.0 || m >= 60.0 || s >= 60.0 = throwError "Invalid point"
| otherwise = pure (cardinal * (d + m / 60.0 + s / 3600.0))