-- | The default reader for Geodetic ground positions is flexible but slow. If you are
-- going to read positions in a known format and performance matters then use one of
-- the more specialised parsers here.
--
-- All angles are returned in degrees.

module Geodetics.LatLongParser (
   degreesMinutesSeconds,
   degreesMinutesSecondsUnits,
   degreesDecimalMinutes,
   degreesDecimalMinutesUnits,
   dms7,
   angle,
   latitudeNS,
   longitudeEW,
   signedLatLong,
   latLong
) where

import Control.Monad
import Data.Char
import Text.ParserCombinators.ReadP as P


-- | Parse an unsigned Integer value.
natural :: ReadP Integer  -- Beware arithmetic overflow of Int
natural :: ReadP Integer
natural = String -> Integer
forall a. Read a => String -> a
read (String -> Integer) -> ReadP String -> ReadP Integer
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isDigit


-- | Parse a tick sign for minutes. This accepts either the keyboard \"'\" or the unicode \"Prime\"
-- character U+2032
minuteTick :: ReadP ()
minuteTick :: ReadP ()
minuteTick = ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ [ReadP Char] -> ReadP Char
forall a. [ReadP a] -> ReadP a
choice [Char -> ReadP Char
char Char
'\'', Char -> ReadP Char
char Char
'\8242']


-- | Parse a double-tick sign for seconds. This accepts either the keyboard \" or the unicode
-- \"Double Prime\" character U+2033.
secondTick :: ReadP ()
secondTick :: ReadP ()
secondTick = ReadP Char -> ReadP ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (ReadP Char -> ReadP ()) -> ReadP Char -> ReadP ()
forall a b. (a -> b) -> a -> b
$ [ReadP Char] -> ReadP Char
forall a. [ReadP a] -> ReadP a
choice [Char -> ReadP Char
char Char
'"', Char -> ReadP Char
char Char
'\8243']


-- | Parse an unsigned decimal value with optional decimal places but no exponent.
decimal :: ReadP Double
decimal :: ReadP Double
decimal = do
   String
str1 <- (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isDigit
   -- In order to avoid ambiguity where 'decimal' and 'dms7' both match
   -- (which can happen in cases with several leading zeros for very small
   -- angles), stipulate that str1 is sufficiently short.
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
str1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
5)
   Double -> ReadP Double -> ReadP Double
forall a. a -> ReadP a -> ReadP a
option (String -> Double
forall a. Read a => String -> a
read String
str1) (ReadP Double -> ReadP Double) -> ReadP Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ do
      String
str2 <- Char -> ReadP Char
char Char
'.' ReadP Char -> ReadP String -> ReadP String
forall a b. ReadP a -> ReadP b -> ReadP b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isDigit
      Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ String -> Double
forall a. Read a => String -> a
read (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
str1 String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char
'.' Char -> String -> String
forall a. a -> [a] -> [a]
: String
str2


-- | Read a character indicating the sign of a value. Returns either +1 or -1.
signChar :: (Num a) =>
   Char        -- ^ Positive sign
   -> Char     -- ^ Negative sign
   -> ReadP a
signChar :: forall a. Num a => Char -> Char -> ReadP a
signChar Char
pos Char
neg = do
   Char
c <- Char -> ReadP Char
char Char
pos ReadP Char -> ReadP Char -> ReadP Char
forall a. ReadP a -> ReadP a -> ReadP a
+++ Char -> ReadP Char
char Char
neg
   a -> ReadP a
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> ReadP a) -> a -> ReadP a
forall a b. (a -> b) -> a -> b
$ if Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
pos then a
1 else (-a
1)


-- | Parse a signed decimal value.
signedDecimal :: ReadP Double
signedDecimal :: ReadP Double
signedDecimal = Double -> Double -> Double
forall a. Num a => a -> a -> a
(*) (Double -> Double -> Double)
-> ReadP Double -> ReadP (Double -> Double)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Double -> ReadP Double -> ReadP Double
forall a. a -> ReadP a -> ReadP a
option Double
1 (Char -> Char -> ReadP Double
forall a. Num a => Char -> Char -> ReadP a
signChar Char
'+' Char
'-') ReadP (Double -> Double) -> ReadP Double -> ReadP Double
forall a b. ReadP (a -> b) -> ReadP a -> ReadP b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ReadP Double
decimal

-- | Parse an unsigned angle written using degrees, minutes and seconds separated by spaces.
-- All except the last must be integers.
degreesMinutesSeconds :: ReadP Double
degreesMinutesSeconds :: ReadP Double
degreesMinutesSeconds = do
   Double
d <- Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Double) -> ReadP Integer -> ReadP Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Integer
natural
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
360
   ReadP ()
skipSpaces
   Double
m <- Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Double) -> ReadP Integer -> ReadP Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Integer
natural
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
m Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   ReadP ()
skipSpaces
   Double
s <- ReadP Double
decimal
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
s Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
m Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
60 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
s Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
3600

-- | Parse an unsigned angle written using degrees, minutes and seconds with units (° ' \").
-- At least one component must be specified.
degreesMinutesSecondsUnits :: ReadP Double
degreesMinutesSecondsUnits :: ReadP Double
degreesMinutesSecondsUnits = do
   Double
d <- Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Double) -> ReadP Integer -> ReadP Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Integer
natural ReadP Double -> ReadP Char -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> ReadP Char
char Char
'°'
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
360
   ReadP ()
skipSpaces
   Double
m <- Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Double) -> ReadP Integer -> ReadP Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Integer
natural ReadP Double -> ReadP () -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP ()
minuteTick
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
m Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   ReadP ()
skipSpaces
   Double
s <- ReadP Double
decimal ReadP Double -> ReadP () -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP ()
secondTick
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
s Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
m Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
60 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
s Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
3600

-- | Parse an unsigned angle written using degrees and decimal minutes.
degreesDecimalMinutes :: ReadP Double
degreesDecimalMinutes :: ReadP Double
degreesDecimalMinutes = do
   Double
d <- Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Double) -> ReadP Integer -> ReadP Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Integer
natural
   ReadP ()
skipSpaces
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
360   -- Difference from degreesMinutesSeconds just to shut style checker up.
   Double
m <- ReadP Double
decimal
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
m Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
mDouble -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
60


-- | Parse an unsigned angle written using degrees and decimal minutes with units (° ')
degreesDecimalMinutesUnits :: ReadP Double
degreesDecimalMinutesUnits :: ReadP Double
degreesDecimalMinutesUnits = do
   Double
d <- Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Double) -> ReadP Integer -> ReadP Double
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP Integer
natural ReadP Double -> ReadP Char -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> ReadP Char
char Char
'°'
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
360
   ReadP ()
skipSpaces
   Double
m <- ReadP Double
decimal ReadP Double -> ReadP () -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP ()
minuteTick
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
m Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
m Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
60

-- | Parse an unsigned angle written in DDDMMSS.ss format.
-- Leading zeros on the degrees and decimal places on the seconds are optional
dms7 :: ReadP Double
dms7 :: ReadP Double
dms7 = do
   String
str <- (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isDigit
   String
decs <- String -> ReadP String -> ReadP String
forall a. a -> ReadP a -> ReadP a
option String
"0" (Char -> ReadP Char
char Char
'.' ReadP Char -> ReadP String -> ReadP String
forall a b. ReadP a -> ReadP b -> ReadP b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Char -> Bool) -> ReadP String
munch1 Char -> Bool
isDigit)
   let c :: Int
c = String -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
str
       (String
ds, String
rs) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt (Int
cInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
4) String
str
       (String
ms,String
ss) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
2 String
rs
       d :: Double
d = String -> Double
forall a. Read a => String -> a
read String
ds
       m :: Double
m = String -> Double
forall a. Read a => String -> a
read String
ms
       s :: Double
s = String -> Double
forall a. Read a => String -> a
read (String -> Double) -> String -> Double
forall a b. (a -> b) -> a -> b
$ String
ss String -> String -> String
forall a. [a] -> [a] -> [a]
++ Char
'.' Char -> String -> String
forall a. a -> [a] -> [a]
: String
decs
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Int
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
5 Bool -> Bool -> Bool
&& Int
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
7
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
m Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
s Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
60
   Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ Double
d Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
m Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
60 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
s Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
3600


-- | Parse an unsigned angle, either in decimal degrees or in degrees, minutes and seconds.
-- In the latter case the unit indicators are optional.
angle :: ReadP Double
angle :: ReadP Double
angle = [ReadP Double] -> ReadP Double
forall a. [ReadP a] -> ReadP a
choice [
      ReadP Double
decimal ReadP Double -> ReadP () -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP Char -> ReadP ()
forall a. ReadP a -> ReadP ()
optional (Char -> ReadP Char
char Char
'°'),
      ReadP Double
degreesMinutesSeconds,
      ReadP Double
degreesMinutesSecondsUnits,
      ReadP Double
degreesDecimalMinutes,
      ReadP Double
degreesDecimalMinutesUnits,
      ReadP Double
dms7
   ]


-- | Parse latitude as an unsigned angle followed by 'N' or 'S'
latitudeNS :: ReadP Double
latitudeNS :: ReadP Double
latitudeNS = do
   Double
ul <- ReadP Double
angle
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
ul Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
90
   ReadP ()
skipSpaces
   Double
sgn <- Char -> Char -> ReadP Double
forall a. Num a => Char -> Char -> ReadP a
signChar Char
'N' Char
'S'
   Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ Double
sgn Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
ul


-- | Parse longitude as an unsigned angle followed by 'E' or 'W'.
longitudeEW :: ReadP Double
longitudeEW :: ReadP Double
longitudeEW = do
   Double
ul <- ReadP Double
angle
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
ul Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
180
   ReadP ()
skipSpaces
   Double
sgn <- Char -> Char -> ReadP Double
forall a. Num a => Char -> Char -> ReadP a
signChar Char
'E' Char
'W'
   Double -> ReadP Double
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double -> ReadP Double) -> Double -> ReadP Double
forall a b. (a -> b) -> a -> b
$ Double
sgn Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
ul


-- | Parse latitude and longitude as two signed decimal numbers in that order, optionally separated by a comma.
-- Longitudes in the western hemisphere may be represented either by negative angles down to -180
-- or by positive angles less than 360.
signedLatLong :: ReadP (Double, Double)
signedLatLong :: ReadP (Double, Double)
signedLatLong = do
   Double
lat <- ReadP Double
signedDecimal ReadP Double -> ReadP () -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP Char -> ReadP ()
forall a. ReadP a -> ReadP ()
optional (Char -> ReadP Char
char Char
'°')
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
lat Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= (-Double
90)
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
lat Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
90
   ReadP ()
skipSpaces
   ReadP () -> ReadP ()
forall a. ReadP a -> ReadP ()
P.optional (ReadP () -> ReadP ()) -> ReadP () -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
',' ReadP Char -> ReadP () -> ReadP ()
forall a b. ReadP a -> ReadP b -> ReadP b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReadP ()
skipSpaces
   Double
long <- ReadP Double
signedDecimal ReadP Double -> ReadP () -> ReadP Double
forall a b. ReadP a -> ReadP b -> ReadP a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* ReadP Char -> ReadP ()
forall a. ReadP a -> ReadP ()
optional (Char -> ReadP Char
char Char
'°')
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
long Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
>= (-Double
180)
   Bool -> ReadP ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> ReadP ()) -> Bool -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Double
long Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
360
   (Double, Double) -> ReadP (Double, Double)
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
lat, if Double
long Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
180 then Double
longDouble -> Double -> Double
forall a. Num a => a -> a -> a
-Double
360 else Double
long)


-- | Parse latitude and longitude in any format.
latLong :: ReadP (Double, Double)
latLong :: ReadP (Double, Double)
latLong = ReadP (Double, Double)
latLong1 ReadP (Double, Double)
-> ReadP (Double, Double) -> ReadP (Double, Double)
forall a. ReadP a -> ReadP a -> ReadP a
+++ ReadP (Double, Double)
longLat ReadP (Double, Double)
-> ReadP (Double, Double) -> ReadP (Double, Double)
forall a. ReadP a -> ReadP a -> ReadP a
+++ ReadP (Double, Double)
signedLatLong
   where
      latLong1 :: ReadP (Double, Double)
latLong1 = do
         Double
lat <- ReadP Double
latitudeNS
         ReadP ()
skipSpaces
         ReadP () -> ReadP ()
forall a. ReadP a -> ReadP ()
P.optional (ReadP () -> ReadP ()) -> ReadP () -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
',' ReadP Char -> ReadP () -> ReadP ()
forall a b. ReadP a -> ReadP b -> ReadP b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReadP ()
skipSpaces
         Double
long <- ReadP Double
longitudeEW
         (Double, Double) -> ReadP (Double, Double)
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
lat, Double
long)
      longLat :: ReadP (Double, Double)
longLat = do
         Double
long <- ReadP Double
longitudeEW
         ReadP ()
skipSpaces
         ReadP () -> ReadP ()
forall a. ReadP a -> ReadP ()
P.optional (ReadP () -> ReadP ()) -> ReadP () -> ReadP ()
forall a b. (a -> b) -> a -> b
$ Char -> ReadP Char
char Char
',' ReadP Char -> ReadP () -> ReadP ()
forall a b. ReadP a -> ReadP b -> ReadP b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ReadP ()
skipSpaces
         Double
lat <- ReadP Double
latitudeNS
         (Double, Double) -> ReadP (Double, Double)
forall a. a -> ReadP a
forall (m :: * -> *) a. Monad m => a -> m a
return (Double
lat, Double
long)