{-|
Module      : Linear.Geo.Geodetic
Copyright   : Travis Whitaker 2023
License     : MIT
Maintainer  : pi.boy.travis@gmail.com
Stability   : Provisional
Portability : Portable (Windows, POSIX)

Geodetic coordinates. The ellipsoid is not indexed explicitly, but conversion functions
for WGS84 are provided.

-}

{-# LANGUAGE BangPatterns
           , DeriveAnyClass
           , DeriveDataTypeable
           , DeriveFunctor
           , DeriveGeneric
           , DerivingStrategies
           #-}

module Linear.Geo.Geodetic (
    Geo(..)
  , normalizeGeo
  , fromLatLonAlt
  , toLatLonAlt
  , simpleEllipsoid
  , earthEllipsoid
  , ecefToGeoFerrariEllipsoid
  , ecefToGeoFerrariEarth
  , geoToECEF
  , ecefToGeo
  ) where

import Control.Applicative

import Control.DeepSeq (NFData)

import Control.Monad.Fix
import Control.Monad.Zip

import Data.Data (Data)

import GHC.Generics (Generic)

import qualified Linear.V3 as L

import Linear.Geo.ECEF
import Linear.Geo.PlaneAngle

-- | A point in some geodetic coordinate system, where 'geoLat' is the angle
--   between the normal at the specified point on the ellipsoid and the
--   equatorial plane (north positive, south negative), 'geoLon' is the angle
--   formed by the intersection of the parallel and the prime meridian and the
--   specified point on the parallel, and 'geoAlt' is the magnitude of the
--   position vector minus the magnitude of the unique vector colinear and
--   coordinal with the position vector impingent on the ellipsoid's surface
--   (i.e. height above ellipsoid). Angles are in radians.
data Geo a = Geo {
    forall a. Geo a -> Radians a
geoLat :: !(Radians a)
  , forall a. Geo a -> Radians a
geoLon :: !(Radians a)
  , forall a. Geo a -> a
geoAlt :: !a
  } deriving stock ( Geo a -> Geo a -> Bool
forall a. Eq a => Geo a -> Geo a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Geo a -> Geo a -> Bool
$c/= :: forall a. Eq a => Geo a -> Geo a -> Bool
== :: Geo a -> Geo a -> Bool
$c== :: forall a. Eq a => Geo a -> Geo a -> Bool
Eq
                   , Geo a -> Geo a -> Bool
Geo a -> Geo a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (Geo a)
forall a. Ord a => Geo a -> Geo a -> Bool
forall a. Ord a => Geo a -> Geo a -> Ordering
forall a. Ord a => Geo a -> Geo a -> Geo a
min :: Geo a -> Geo a -> Geo a
$cmin :: forall a. Ord a => Geo a -> Geo a -> Geo a
max :: Geo a -> Geo a -> Geo a
$cmax :: forall a. Ord a => Geo a -> Geo a -> Geo a
>= :: Geo a -> Geo a -> Bool
$c>= :: forall a. Ord a => Geo a -> Geo a -> Bool
> :: Geo a -> Geo a -> Bool
$c> :: forall a. Ord a => Geo a -> Geo a -> Bool
<= :: Geo a -> Geo a -> Bool
$c<= :: forall a. Ord a => Geo a -> Geo a -> Bool
< :: Geo a -> Geo a -> Bool
$c< :: forall a. Ord a => Geo a -> Geo a -> Bool
compare :: Geo a -> Geo a -> Ordering
$ccompare :: forall a. Ord a => Geo a -> Geo a -> Ordering
Ord
                   , Int -> Geo a -> ShowS
forall a. Show a => Int -> Geo a -> ShowS
forall a. Show a => [Geo a] -> ShowS
forall a. Show a => Geo a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Geo a] -> ShowS
$cshowList :: forall a. Show a => [Geo a] -> ShowS
show :: Geo a -> String
$cshow :: forall a. Show a => Geo a -> String
showsPrec :: Int -> Geo a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Geo a -> ShowS
Show
                   , forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Geo a) x -> Geo a
forall a x. Geo a -> Rep (Geo a) x
$cto :: forall a x. Rep (Geo a) x -> Geo a
$cfrom :: forall a x. Geo a -> Rep (Geo a) x
Generic
                   , Geo a -> DataType
Geo a -> Constr
forall {a}. Data a => Typeable (Geo a)
forall a. Data a => Geo a -> DataType
forall a. Data a => Geo a -> Constr
forall a. Data a => (forall b. Data b => b -> b) -> Geo a -> Geo a
forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Geo a -> u
forall a u. Data a => (forall d. Data d => d -> u) -> Geo a -> [u]
forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Geo a -> r
forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Geo a -> r
forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Geo a)
forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Geo a -> c (Geo a)
forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Geo a))
forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Geo a))
forall a.
Typeable a
-> (forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Geo a)
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Geo a -> c (Geo a)
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Geo a))
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
$cgmapMo :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
$cgmapMp :: forall a (m :: * -> *).
(Data a, MonadPlus m) =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
$cgmapM :: forall a (m :: * -> *).
(Data a, Monad m) =>
(forall d. Data d => d -> m d) -> Geo a -> m (Geo a)
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> Geo a -> u
$cgmapQi :: forall a u.
Data a =>
Int -> (forall d. Data d => d -> u) -> Geo a -> u
gmapQ :: forall u. (forall d. Data d => d -> u) -> Geo a -> [u]
$cgmapQ :: forall a u. Data a => (forall d. Data d => d -> u) -> Geo a -> [u]
gmapQr :: forall r r'.
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Geo a -> r
$cgmapQr :: forall a r r'.
Data a =>
(r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Geo a -> r
gmapQl :: forall r r'.
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Geo a -> r
$cgmapQl :: forall a r r'.
Data a =>
(r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Geo a -> r
gmapT :: (forall b. Data b => b -> b) -> Geo a -> Geo a
$cgmapT :: forall a. Data a => (forall b. Data b => b -> b) -> Geo a -> Geo a
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Geo a))
$cdataCast2 :: forall a (t :: * -> * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (Geo a))
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c (Geo a))
$cdataCast1 :: forall a (t :: * -> *) (c :: * -> *).
(Data a, Typeable t) =>
(forall d. Data d => c (t d)) -> Maybe (c (Geo a))
dataTypeOf :: Geo a -> DataType
$cdataTypeOf :: forall a. Data a => Geo a -> DataType
toConstr :: Geo a -> Constr
$ctoConstr :: forall a. Data a => Geo a -> Constr
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Geo a)
$cgunfold :: forall a (c :: * -> *).
Data a =>
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c (Geo a)
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Geo a -> c (Geo a)
$cgfoldl :: forall a (c :: * -> *).
Data a =>
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> Geo a -> c (Geo a)
Data
                   , Geo a
forall a. a -> a -> Bounded a
forall a. Bounded a => Geo a
maxBound :: Geo a
$cmaxBound :: forall a. Bounded a => Geo a
minBound :: Geo a
$cminBound :: forall a. Bounded a => Geo a
Bounded
                   , forall a b. a -> Geo b -> Geo a
forall a b. (a -> b) -> Geo a -> Geo b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Geo b -> Geo a
$c<$ :: forall a b. a -> Geo b -> Geo a
fmap :: forall a b. (a -> b) -> Geo a -> Geo b
$cfmap :: forall a b. (a -> b) -> Geo a -> Geo b
Functor
                   )
    deriving anyclass (forall a. NFData a => Geo a -> ()
forall a. (a -> ()) -> NFData a
rnf :: Geo a -> ()
$crnf :: forall a. NFData a => Geo a -> ()
NFData)

instance Applicative Geo where
    pure :: forall a. a -> Geo a
pure a
x = forall a. Radians a -> Radians a -> a -> Geo a
Geo (forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x) (forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x) a
x
    (Geo Radians (a -> b)
pf Radians (a -> b)
lf a -> b
hf) <*> :: forall a b. Geo (a -> b) -> Geo a -> Geo b
<*> (Geo Radians a
p Radians a
l a
h) = forall a. Radians a -> Radians a -> a -> Geo a
Geo (Radians (a -> b)
pf forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Radians a
p) (Radians (a -> b)
lf forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Radians a
l) (a -> b
hf a
h)

instance Monad Geo where
    return :: forall a. a -> Geo a
return = forall (f :: * -> *) a. Applicative f => a -> f a
pure
    (Geo (Radians a
p) (Radians a
l) a
h) >>= :: forall a b. Geo a -> (a -> Geo b) -> Geo b
>>= a -> Geo b
f =
        let Geo Radians b
p' Radians b
_ b
_ = a -> Geo b
f a
p
            Geo Radians b
_ Radians b
l' b
_ = a -> Geo b
f a
l
            Geo Radians b
_ Radians b
_ b
h' = a -> Geo b
f a
h
        in forall a. Radians a -> Radians a -> a -> Geo a
Geo Radians b
p' Radians b
l' b
h'

instance MonadZip Geo where
    mzipWith :: forall a b c. (a -> b -> c) -> Geo a -> Geo b -> Geo c
mzipWith = forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2

instance MonadFix Geo where
    mfix :: forall a. (a -> Geo a) -> Geo a
mfix a -> Geo a
f = forall a. Radians a -> Radians a -> a -> Geo a
Geo (let Geo (Radians a
p) Radians a
_ a
_ = a -> Geo a
f a
p in forall a. a -> Radians a
Radians a
p)
                 (let Geo Radians a
_ (Radians a
l) a
_ = a -> Geo a
f a
l in forall a. a -> Radians a
Radians a
l)
                 (let Geo Radians a
_ Radians a
_           a
h = a -> Geo a
f a
h in a
h)

instance Foldable Geo where
    foldMap :: forall m a. Monoid m => (a -> m) -> Geo a -> m
foldMap a -> m
f (Geo Radians a
p Radians a
l a
h) = forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f Radians a
p forall a. Semigroup a => a -> a -> a
<> forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f Radians a
l forall a. Semigroup a => a -> a -> a
<> a -> m
f a
h

instance Traversable Geo where
    traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Geo a -> f (Geo b)
traverse a -> f b
f (Geo Radians a
p Radians a
l a
h) = forall a. Radians a -> Radians a -> a -> Geo a
Geo forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f Radians a
p forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse a -> f b
f Radians a
l forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> a -> f b
f a
h

-- | Normalize the two angle components of a `Geo`.
normalizeGeo :: (Floating a, Real a) => Geo a -> Geo a
normalizeGeo :: forall a. (Floating a, Real a) => Geo a -> Geo a
normalizeGeo (Geo Radians a
p Radians a
l a
a) = forall a. Radians a -> Radians a -> a -> Geo a
Geo (forall (ang :: * -> *) a.
(PlaneAngle ang, Floating a, Real a) =>
ang a -> ang a
normalizeAngle Radians a
p) (forall (ang :: * -> *) a.
(PlaneAngle ang, Floating a, Real a) =>
ang a -> ang a
normalizeAngle Radians a
l) a
a

-- | Convert a pair of angles and a height above the ellipsoid into a 'Geo'.
fromLatLonAlt :: (PlaneAngle lat, PlaneAngle lon, Floating a, Real a)
              => lat a -- ^ Latitude
              -> lon a -- ^ Longitude
              -> a     -- ^ Altitude
              -> Geo a
fromLatLonAlt :: forall (lat :: * -> *) (lon :: * -> *) a.
(PlaneAngle lat, PlaneAngle lon, Floating a, Real a) =>
lat a -> lon a -> a -> Geo a
fromLatLonAlt lat a
lat lon a
lon a
alt = forall a. Radians a -> Radians a -> a -> Geo a
Geo (forall (ang :: * -> *) a.
(PlaneAngle ang, Floating a, Real a) =>
ang a -> Radians a
toRadians lat a
lat) (forall (ang :: * -> *) a.
(PlaneAngle ang, Floating a, Real a) =>
ang a -> Radians a
toRadians lon a
lon) a
alt

-- | Unpack a 'Geo' into latitude, longitude, and height above the ellipsoid.
toLatLonAlt :: (PlaneAngle lat, PlaneAngle lon, Floating a, Real a)
            => Geo a
            -> (lat a, lon a, a)
toLatLonAlt :: forall (lat :: * -> *) (lon :: * -> *) a.
(PlaneAngle lat, PlaneAngle lon, Floating a, Real a) =>
Geo a -> (lat a, lon a, a)
toLatLonAlt (Geo Radians a
p Radians a
l a
a) = (forall (ang :: * -> *) a.
(PlaneAngle ang, Floating a, Real a) =>
Radians a -> ang a
fromRadians Radians a
p, forall (ang :: * -> *) a.
(PlaneAngle ang, Floating a, Real a) =>
Radians a -> ang a
fromRadians Radians a
l, a
a)

-- | Convert from geodetic coordinates to ECEF by assuming the earth is an
--   ellipsoid.
simpleEllipsoid :: Floating a
                => a -- ^ Semi-major axis.
                -> a -- ^ Semi-minor axis.
                -> Geo a
                -> ECEF a
simpleEllipsoid :: forall a. Floating a => a -> a -> Geo a -> ECEF a
simpleEllipsoid a
a a
b =
    let -- coefficient for adjusted prime vertical radius
        dpvr :: a
dpvr  = (a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Fractional a => a -> a -> a
/ (a
a forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)
        -- square of first eccentricity
        esqr :: a
esqr  = a
1 forall a. Num a => a -> a -> a
- a
dpvr
        -- prime vertical radius as function of latitude
        pvr :: a -> a
pvr a
p = a
a forall a. Fractional a => a -> a -> a
/ (forall a. Floating a => a -> a
sqrt (a
1 forall a. Num a => a -> a -> a
- (a
esqr forall a. Num a => a -> a -> a
* ((forall a. Floating a => a -> a
sin a
p) forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2))))
        proj :: Geo a -> ECEF a
proj (Geo (Radians a
p) (Radians a
l) a
h) =
            let n :: a
n  = a -> a
pvr a
p
                nh :: a
nh = a
n forall a. Num a => a -> a -> a
+ a
h
                nd :: a
nd = (a
dpvr forall a. Num a => a -> a -> a
* a
n) forall a. Num a => a -> a -> a
+ a
h
            in forall a. V3 a -> ECEF a
ECEF (forall a. a -> a -> a -> V3 a
L.V3 (a
nh forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
cos a
p forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
cos a
l)
                          (a
nh forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
cos a
p forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sin a
l)
                          (a
nd forall a. Num a => a -> a -> a
* forall a. Floating a => a -> a
sin a
p)
                    )
    in Geo a -> ECEF a
proj

-- | Standard WGS84 ellipsoid.
earthEllipsoid :: RealFloat a
               => Geo a
               -> ECEF a
earthEllipsoid :: forall a. RealFloat a => Geo a -> ECEF a
earthEllipsoid = forall a. Floating a => a -> a -> Geo a -> ECEF a
simpleEllipsoid a
6378137 a
6356752.314245

-- | Conversion from ECEF to geodetic coordinates via a numerically stable
--   formulation of Ferrari's closed-form solution to the quartic polynomial.
--   See https://ieeexplore.ieee.org/document/303772/
ecefToGeoFerrariEllipsoid :: RealFloat a
                          => a -- ^ Semi-major axis.
                          -> a -- ^ Semi-minor axis.
                          -> ECEF a
                          -> Geo a
ecefToGeoFerrariEllipsoid :: forall a. RealFloat a => a -> a -> ECEF a -> Geo a
ecefToGeoFerrariEllipsoid a
a a
b (ECEF (L.V3 a
x a
y a
z)) =
    let r :: a
r     = forall a. Floating a => a -> a
sqrt ((a
x forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
+ (a
y forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2))
        dpvr :: a
dpvr  = (a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Fractional a => a -> a -> a
/ (a
a forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)
        esqr :: a
esqr  = a
1 forall a. Num a => a -> a -> a
- a
dpvr
        e'sqr :: a
e'sqr = ((a
a forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
- (a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)) forall a. Fractional a => a -> a -> a
/ (a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)
        eesqr :: a
eesqr = (a
a forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
- (a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)
        ff :: a
ff    = a
54 forall a. Num a => a -> a -> a
* (a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
* (a
z forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)
        gg :: a
gg    = (a
r forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
+ ((a
1 forall a. Num a => a -> a -> a
- a
esqr) forall a. Num a => a -> a -> a
* (a
z forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)) forall a. Num a => a -> a -> a
- (a
esqr forall a. Num a => a -> a -> a
* a
eesqr)
        cc :: a
cc    = ((a
esqr forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
* a
ff forall a. Num a => a -> a -> a
* (a
r forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)) forall a. Fractional a => a -> a -> a
/ (a
gg forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
3)
        ss :: a
ss    = (a
1 forall a. Num a => a -> a -> a
+ a
cc forall a. Num a => a -> a -> a
+ forall a. Floating a => a -> a
sqrt ((a
cc forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
+ (a
2 forall a. Num a => a -> a -> a
* a
cc))) forall a. Floating a => a -> a -> a
** (a
1 forall a. Fractional a => a -> a -> a
/ a
3)
        pp :: a
pp    = a
ff forall a. Fractional a => a -> a -> a
/ (a
3 forall a. Num a => a -> a -> a
* (((a
ss forall a. Num a => a -> a -> a
+ (a
1 forall a. Fractional a => a -> a -> a
/ a
ss) forall a. Num a => a -> a -> a
+ a
1)) forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
* (a
gg forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2))
        qq :: a
qq    = forall a. Floating a => a -> a
sqrt (a
1 forall a. Num a => a -> a -> a
+ (a
2 forall a. Num a => a -> a -> a
* (a
esqr forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
* a
pp))
        r0 :: a
r0    = ((-(a
pp forall a. Num a => a -> a -> a
* a
esqr forall a. Num a => a -> a -> a
* a
r)) forall a. Fractional a => a -> a -> a
/ (a
1 forall a. Num a => a -> a -> a
+ a
qq))
              forall a. Num a => a -> a -> a
+ (forall a. Floating a => a -> a
sqrt ( ((a
1 forall a. Fractional a => a -> a -> a
/ a
2) forall a. Num a => a -> a -> a
* (a
a forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
* (a
1 forall a. Num a => a -> a -> a
+ (a
1 forall a. Fractional a => a -> a -> a
/ a
qq)))
                      forall a. Num a => a -> a -> a
- ((a
pp forall a. Num a => a -> a -> a
* (a
1 forall a. Num a => a -> a -> a
- a
esqr) forall a. Num a => a -> a -> a
* (a
z forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)) forall a. Fractional a => a -> a -> a
/ (a
qq forall a. Num a => a -> a -> a
* (a
1 forall a. Num a => a -> a -> a
+ a
qq)))
                      forall a. Num a => a -> a -> a
- ((a
1 forall a. Fractional a => a -> a -> a
/ a
2) forall a. Num a => a -> a -> a
* a
pp forall a. Num a => a -> a -> a
* (a
r forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2))
                      )
                )
        uu :: a
uu    = forall a. Floating a => a -> a
sqrt (((a
r forall a. Num a => a -> a -> a
- (a
esqr forall a. Num a => a -> a -> a
* a
r0)) forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
+ (a
z forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2))
        vv :: a
vv    = forall a. Floating a => a -> a
sqrt (((a
r forall a. Num a => a -> a -> a
- a
esqr forall a. Num a => a -> a -> a
* a
r0) forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
+ ((a
1 forall a. Num a => a -> a -> a
- a
esqr) forall a. Num a => a -> a -> a
* (a
z forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2)))
        zz0 :: a
zz0   = ((a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Num a => a -> a -> a
* a
z) forall a. Fractional a => a -> a -> a
/ (a
a forall a. Num a => a -> a -> a
* a
vv)
        h :: a
h     = a
uu forall a. Num a => a -> a -> a
* (a
1 forall a. Num a => a -> a -> a
- ((a
b forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
2) forall a. Fractional a => a -> a -> a
/ (a
a forall a. Num a => a -> a -> a
* a
vv)))
        p :: a
p     = forall a. Floating a => a -> a
atan ((a
z forall a. Num a => a -> a -> a
+ (a
e'sqr forall a. Num a => a -> a -> a
* a
zz0)) forall a. Fractional a => a -> a -> a
/ a
r)
        l :: a
l     = forall a. RealFloat a => a -> a -> a
atan2 a
y a
x
    in forall a. Radians a -> Radians a -> a -> Geo a
Geo (forall a. a -> Radians a
Radians a
p) (forall a. a -> Radians a
Radians a
l) a
h

-- | Standard WGS84 ellipsoid.
ecefToGeoFerrariEarth :: RealFloat a => ECEF a -> Geo a
ecefToGeoFerrariEarth :: forall a. RealFloat a => ECEF a -> Geo a
ecefToGeoFerrariEarth = forall a. RealFloat a => a -> a -> ECEF a -> Geo a
ecefToGeoFerrariEllipsoid a
6378137 a
6356752.314245

-- | Synonym for 'earthEllipsoid'.
geoToECEF :: RealFloat a => Geo a -> ECEF a
geoToECEF :: forall a. RealFloat a => Geo a -> ECEF a
geoToECEF = forall a. RealFloat a => Geo a -> ECEF a
earthEllipsoid

-- | Synonym for 'ecefToGeoFerrariEarth'.
ecefToGeo ::  RealFloat a => ECEF a -> Geo a
ecefToGeo :: forall a. RealFloat a => ECEF a -> Geo a
ecefToGeo = forall a. RealFloat a => ECEF a -> Geo a
ecefToGeoFerrariEarth