-- | An ellipsoid with parameters such as flattening.
module Data.Geo.Ellipsoid(
                           Ellipsoid,
                           semiMajor,
                           semiMinor,
                           flattening,
                           inverseFlattening,
                           ellipsoid,
                           semiMajorInverseF,
                           semiMajorFlattening,
                           wgs84,
                           grs80,
                           grs67,
                           ans,
                           wgs72,
                           au1965,
                           krasovsky1940,
                           international1924,
                           hayford1909,
                           airy1830,
                           everest1830,
                           bessel1841,
                           clarke1858,
                           clarke1866,
                           clarke1880
                         ) where

-- | Ellipsoidal parameters. Some are derivable from others.
data Ellipsoid = Ellipsoid {
  semiMajor :: Double, -- ^ The semi major axis in metres.
  semiMinor :: Double, -- ^ The semi minor axis in metres.
  flattening :: Double, -- ^ The ellipsoidal flattening.
  inverseFlattening :: Double -- ^ The inverse of the ellipsoidal flattening.
} deriving (Eq, Show)

-- | Construct an ellipsoid with the given parameters.
ellipsoid :: Double -- ^ The semi major axis in metres.
             -> Double -- ^ The semi minor axis in metres.
             -> Double -- ^ The ellipsoidal flattening.
             -> Double -- ^ The inverse of the ellipsoidal flattening.
             -> Ellipsoid
ellipsoid = Ellipsoid

-- | Construct an ellipsoid using only a semi major axis and inverse flattening. Other parameters are computed.
semiMajorInverseF :: Double -- ^ The semi major axis.
                     -> Double -- ^ The inverse of the ellipsoidal flattening.
                     -> Ellipsoid
semiMajorInverseF s i = let f = 1 / i
                        in ellipsoid s ((1.0 - f) * s) f i

-- | Construct an ellipsoid using only a semi major axis and flattening. Other parameters are computed.
semiMajorFlattening :: Double -- ^ The semi major axis.
                       -> Double -- ^ The ellipsoidal flattening.
                       -> Ellipsoid
semiMajorFlattening s f = ellipsoid s ((1.0 - f) * s) f (1 / f)

wgs84 :: Ellipsoid
wgs84 = semiMajorInverseF 6378137 298.257223563

grs80 :: Ellipsoid
grs80 = semiMajorInverseF 6378137 298.257222101

grs67 :: Ellipsoid
grs67 = semiMajorInverseF 6378160 298.25

ans :: Ellipsoid
ans = semiMajorInverseF 6378160 298.25

wgs72 :: Ellipsoid
wgs72 = semiMajorInverseF 6378135 298.26

au1965 :: Ellipsoid
au1965 = semiMajorInverseF 6378160 298.25

krasovsky1940 :: Ellipsoid
krasovsky1940 = semiMajorInverseF 6378245 298.3

international1924 :: Ellipsoid
international1924 = semiMajorInverseF 6378388 297

hayford1909 :: Ellipsoid
hayford1909 = international1924

airy1830 :: Ellipsoid
airy1830 = semiMajorInverseF 6377563.4 299.32

everest1830 :: Ellipsoid
everest1830 = semiMajorInverseF 6377276.3 300.8

bessel1841 :: Ellipsoid
bessel1841 = semiMajorInverseF 6377397.2 299.15

clarke1858 :: Ellipsoid
clarke1858 = semiMajorInverseF 6378293.645 294.26

clarke1866 :: Ellipsoid
clarke1866 = semiMajorInverseF 6378206.4 294.98

clarke1880 :: Ellipsoid
clarke1880 = semiMajorInverseF 6378249.145 293.465