module Data.Geo.Coordinate.Coordinate(
Coordinate
, (.#.)
, (<°>)
, (<㎭>)
, fracCoordinate
, radianCoordinate
, HasCoordinate(..)
, coordinateLatLon
, coordinateLonLat
, coordinateDMSLatLon
, coordinateLatDMSLon
, coordinateDMSLatDMSLon
) where
import Control.Category(Category(id, (.)))
import Control.Lens(Iso', Lens', Prism', iso, lens, prism', mapping, swapped, withIso, (^?), (#))
import Control.Monad(Monad(return))
import Data.Eq(Eq)
import Data.Geo.Coordinate.Latitude(HasLatitude(latitude), Latitude, dmsLatitude, radianLatitude, fracLatitude)
import Data.Geo.Coordinate.Longitude(HasLongitude(longitude), Longitude, dmsLongitude, radianLongitude, fracLongitude)
import Data.Geo.Coordinate.DegreesLatitude(HasDegreesLatitude(degreesLatitude), DegreesLatitude)
import Data.Geo.Coordinate.DegreesLongitude(HasDegreesLongitude(degreesLongitude), DegreesLongitude)
import Data.Geo.Coordinate.Minutes(Minutes)
import Data.Geo.Coordinate.Seconds(Seconds)
import Data.Maybe(Maybe)
import Data.Ord(Ord)
import Data.Tuple(curry, uncurry)
import Prelude(Show, Double)
data Coordinate =
Coordinate
Latitude
Longitude
deriving (Eq, Ord, Show)
(.#.) ::
Latitude
-> Longitude
-> Coordinate
(.#.) =
Coordinate
(<°>) ::
Double
-> Double
-> Maybe Coordinate
(<°>) =
curry (^? fracCoordinate)
(<㎭>) ::
Double
-> Double
-> Maybe Coordinate
(<㎭>) =
curry (^? radianCoordinate)
coordinatePrism ::
Prism' Double Latitude
-> Prism' Double Longitude
-> Prism' (Double, Double) Coordinate
coordinatePrism f g =
prism'
(\x -> let (b, d) = coordinateLatLon # x
in (f # b, g # d))
(\(lat, lon) ->
do lat' <- lat ^? f
lon' <- lon ^? g
return (Coordinate lat' lon'))
fracCoordinate ::
Prism' (Double, Double) Coordinate
fracCoordinate =
coordinatePrism fracLatitude fracLongitude
radianCoordinate ::
Prism' (Double, Double) Coordinate
radianCoordinate =
coordinatePrism radianLatitude radianLongitude
coordinateLatLon ::
Iso' (Latitude, Longitude) Coordinate
coordinateLatLon =
iso (uncurry Coordinate) (\(Coordinate lat lon) -> (lat, lon))
coordinateLonLat ::
Iso' (Longitude, Latitude) Coordinate
coordinateLonLat =
swapped . coordinateLatLon
coordinateDMSLatLon ::
Iso' ((DegreesLatitude, Minutes, Seconds), Longitude) Coordinate
coordinateDMSLatLon =
swapped . mapping dmsLatitude . coordinateLonLat
coordinateLatDMSLon ::
Iso' (Latitude, (DegreesLongitude, Minutes, Seconds)) Coordinate
coordinateLatDMSLon =
mapping dmsLongitude . coordinateLatLon
coordinateDMSLatDMSLon ::
Iso' ((DegreesLatitude, Minutes, Seconds), (DegreesLongitude, Minutes, Seconds)) Coordinate
coordinateDMSLatDMSLon =
iso (\((td, tm, ts), (nd, nm, ns)) -> Coordinate (withIso dmsLatitude (\k _ -> k (td, tm, ts))) (withIso dmsLongitude (\k _ -> k (nd, nm, ns))))
(\(Coordinate lat lon) -> (withIso dmsLatitude (\_ k -> k lat), withIso dmsLongitude (\_ k -> k lon)))
class HasCoordinate t where
coordinate ::
Lens' t Coordinate
instance HasCoordinate Coordinate where
coordinate =
id
instance HasLatitude Coordinate where
latitude =
lens (\(Coordinate lat _) -> lat) (\(Coordinate _ lon) lat -> Coordinate lat lon)
instance HasLongitude Coordinate where
longitude =
lens (\(Coordinate _ lon) -> lon) (\(Coordinate lat _) lon -> Coordinate lat lon)
instance HasDegreesLatitude Coordinate where
degreesLatitude =
latitude . degreesLatitude
instance HasDegreesLongitude Coordinate where
degreesLongitude =
longitude . degreesLongitude