{-|
Module: Data.Astro.Planet.PlanetMechanics
Description: Planet mechanics
Copyright: Alexander Ignatyev, 2016

Planet mechanics.
-}

module Data.Astro.Planet.PlanetMechanics
(
  planetMeanAnomaly
  , planetTrueAnomaly1
  , planetTrueAnomaly2
  , planetHeliocentricRadiusVector
  , planetHeliocentricLongitude
  , planetHeliocentricLatitude
  , planetProjectedRadiusVector
  , planetProjectedLongitude
  , planetEclipticLongitude
  , planetEclipticLatitude
  , planetPosition
  , planetPosition1
  , planetDistance
  , planetDistance1
  , planetAngularDiameter
  , planetPhase1
  , planetPertubations
  , planetBrightLimbPositionAngle
)

where

import qualified Data.Astro.Utils as U
import Data.Astro.Types (DecimalDegrees(..), AstronomicalUnits(..), toRadians, fromRadians, fromDecimalHours)
import Data.Astro.Time.Epoch (j1900)
import Data.Astro.Time.JulianDate (JulianDate, numberOfDays, numberOfCenturies)
import Data.Astro.Coordinate (EquatorialCoordinates1(..), EclipticCoordinates(..), eclipticToEquatorial)
import Data.Astro.Planet.PlanetDetails (Planet(..), PlanetDetails(..), isInnerPlanet)
import Data.Astro.Sun.SunInternals (solveKeplerEquation)

{-
1. Calculate the planet position on its own orbital plane
2. Convert the planet's position to planetHeliocentric coordinates.
3. Convert from planetHeliocentric coordinates to ecliptic coordinates.
-}


-- | reduce DecimalDegrees to the range [0, 360)

reduceDegrees :: DecimalDegrees -> DecimalDegrees
reduceDegrees :: DecimalDegrees -> DecimalDegrees
reduceDegrees = DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. RealFrac a => a -> a -> a
U.reduceToZeroRange DecimalDegrees
360


-- | Calculate the planet mean anomaly.

planetMeanAnomaly :: PlanetDetails -> JulianDate -> DecimalDegrees
planetMeanAnomaly PlanetDetails
pd JulianDate
jd =
  let d :: TimeBaseType
d =  JulianDate -> JulianDate -> TimeBaseType
numberOfDays (PlanetDetails -> JulianDate
pdEpoch PlanetDetails
pd) JulianDate
jd
      n :: DecimalDegrees
n = DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> DecimalDegrees
DD (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ (TimeBaseType
360TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/TimeBaseType
U.tropicalYearLen) TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
* (TimeBaseType
dTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/(PlanetDetails -> TimeBaseType
pdTp PlanetDetails
pd))
  in DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ DecimalDegrees
n DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
+ (PlanetDetails -> DecimalDegrees
pdEpsilon PlanetDetails
pd) DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
- (PlanetDetails -> DecimalDegrees
pdOmegaBar PlanetDetails
pd)


-- | Calculate the planet true anomaly using approximate method

planetTrueAnomaly1 :: PlanetDetails -> JulianDate -> DecimalDegrees
planetTrueAnomaly1 PlanetDetails
pd JulianDate
jd =
  let meanAnomaly :: TimeBaseType
meanAnomaly = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ PlanetDetails -> JulianDate -> DecimalDegrees
planetMeanAnomaly PlanetDetails
pd JulianDate
jd
      e :: TimeBaseType
e = PlanetDetails -> TimeBaseType
pdE PlanetDetails
pd
  in DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> DecimalDegrees
fromRadians (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType
meanAnomaly TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
2TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
eTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
meanAnomaly)


-- | Calculate the planet true anomaly using the second 'more accurate' method

planetTrueAnomaly2 :: PlanetDetails -> JulianDate -> DecimalDegrees
planetTrueAnomaly2 PlanetDetails
pd JulianDate
jd =
  let meanAnomaly :: TimeBaseType
meanAnomaly = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ PlanetDetails -> JulianDate -> DecimalDegrees
planetMeanAnomaly PlanetDetails
pd JulianDate
jd
      e :: TimeBaseType
e = PlanetDetails -> TimeBaseType
pdE PlanetDetails
pd
      eccentricAnomaly :: TimeBaseType
eccentricAnomaly = TimeBaseType -> TimeBaseType -> TimeBaseType -> TimeBaseType
solveKeplerEquation TimeBaseType
e TimeBaseType
meanAnomaly TimeBaseType
0.000000001
      trueAnomaly :: TimeBaseType
trueAnomaly = TimeBaseType
2 TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
* TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
atan (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sqrt((TimeBaseType
1 TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
e) TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/ (TimeBaseType
1 TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
e)) TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
* TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
tan (TimeBaseType
eccentricAnomaly TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/ TimeBaseType
2))
  in DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> DecimalDegrees
fromRadians TimeBaseType
trueAnomaly

-- | Calculate Heliocentric Longitude.

-- It takes Planet Details and true anomaly.

planetHeliocentricLongitude :: PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude :: PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude PlanetDetails
pd DecimalDegrees
trueAnomaly = DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ (PlanetDetails -> DecimalDegrees
pdOmegaBar PlanetDetails
pd) DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
+ DecimalDegrees
trueAnomaly


-- | Calculate Heliocentric Latitude.

-- It takes Planet Details and heliocentric longitude.

planetHeliocentricLatitude :: PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLatitude :: PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLatitude PlanetDetails
pd DecimalDegrees
hcl =
  let l' :: TimeBaseType
l' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
hcl
      i' :: TimeBaseType
i' = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ PlanetDetails -> DecimalDegrees
pdI PlanetDetails
pd
      bigOmega' :: TimeBaseType
bigOmega' = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ PlanetDetails -> DecimalDegrees
pdBigOmega PlanetDetails
pd
  in TimeBaseType -> DecimalDegrees
fromRadians (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
asin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
l' TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
bigOmega')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
i')


-- | Calculate Heliocentric Radius Vector.

-- It takes Planet Details and true anomaly.

planetHeliocentricRadiusVector :: PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector :: PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector PlanetDetails
pd DecimalDegrees
trueAnomaly =
  let nu :: TimeBaseType
nu = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
trueAnomaly
      AU TimeBaseType
alpha = PlanetDetails -> AstronomicalUnits
pdAlpha PlanetDetails
pd
      e :: TimeBaseType
e = PlanetDetails -> TimeBaseType
pdE PlanetDetails
pd
  in TimeBaseType -> AstronomicalUnits
AU (TimeBaseType -> AstronomicalUnits)
-> TimeBaseType -> AstronomicalUnits
forall a b. (a -> b) -> a -> b
$ TimeBaseType
alphaTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType
1 TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
eTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
e)TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/(TimeBaseType
1TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+TimeBaseType
eTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
nu))


-- | Calculate Heliocentric Longitude projected to the ecliptic.

-- It takes Planet Details and Heliocentric Longitude

planetProjectedLongitude :: PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetProjectedLongitude :: PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetProjectedLongitude PlanetDetails
pd DecimalDegrees
hcl =
  let hcl' :: TimeBaseType
hcl' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
hcl
      bigOmega :: DecimalDegrees
bigOmega = PlanetDetails -> DecimalDegrees
pdBigOmega PlanetDetails
pd
      bigOmega' :: TimeBaseType
bigOmega' = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ DecimalDegrees
bigOmega
      i' :: TimeBaseType
i' = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ PlanetDetails -> DecimalDegrees
pdI PlanetDetails
pd
      y :: TimeBaseType
y = (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
hcl'TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
bigOmega')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
i')
      x :: TimeBaseType
x = (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
hcl'TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
bigOmega')
      n :: DecimalDegrees
n = TimeBaseType -> DecimalDegrees
fromRadians (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. RealFloat a => a -> a -> a
atan2 TimeBaseType
y TimeBaseType
x
  in DecimalDegrees
n DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
+ DecimalDegrees
bigOmega


-- | Calculate Heliocentric Radius Vector projected to the ecliptic.

-- It takes Planet Details, planetHeliocentric latitude and Radius Vector

planetProjectedRadiusVector :: PlanetDetails -> DecimalDegrees -> AstronomicalUnits -> AstronomicalUnits
planetProjectedRadiusVector :: PlanetDetails
-> DecimalDegrees -> AstronomicalUnits -> AstronomicalUnits
planetProjectedRadiusVector PlanetDetails
pd DecimalDegrees
psi (AU TimeBaseType
hcr) = TimeBaseType -> AstronomicalUnits
AU (TimeBaseType -> AstronomicalUnits)
-> TimeBaseType -> AstronomicalUnits
forall a b. (a -> b) -> a -> b
$ TimeBaseType
hcrTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos(DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
psi)


-- | Calculate ecliptic longitude for outer planets.

-- It takes planet projected longitude, planet projected radius vector

-- the Earth's longitude and radius vector.

outerPlanetEclipticLongitude :: DecimalDegrees -> AstronomicalUnits -> DecimalDegrees -> AstronomicalUnits -> DecimalDegrees
outerPlanetEclipticLongitude :: DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
outerPlanetEclipticLongitude DecimalDegrees
lp (AU TimeBaseType
rp) DecimalDegrees
le (AU TimeBaseType
re) =
  let lp' :: TimeBaseType
lp' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
lp
      le' :: TimeBaseType
le' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
le
      x :: TimeBaseType
x = TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
atan (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
re TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
* (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
lp'TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
le')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/(TimeBaseType
rp TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
reTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
lp'TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
le'))
  in DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ (TimeBaseType -> DecimalDegrees
fromRadians TimeBaseType
x) DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
+ DecimalDegrees
lp


-- | Calculate ecliptic longitude for inner planets.

-- It takes planet projected longitude, planet projected radius vector

-- the Earth's longitude and radius vector.

innerPlanetEclipticLongitude :: DecimalDegrees -> AstronomicalUnits -> DecimalDegrees -> AstronomicalUnits -> DecimalDegrees
innerPlanetEclipticLongitude :: DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
innerPlanetEclipticLongitude DecimalDegrees
lp (AU TimeBaseType
rp) DecimalDegrees
le (AU TimeBaseType
re) =
  let lp' :: TimeBaseType
lp' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
lp
      le' :: TimeBaseType
le' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
le
      x :: TimeBaseType
x = TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
atan (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
rp TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
* (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
le'TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
lp')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/(TimeBaseType
re TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
rpTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
le'TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
lp'))
  in DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ (TimeBaseType -> DecimalDegrees
fromRadians TimeBaseType
x) DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
+ DecimalDegrees
le DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
+ DecimalDegrees
180


-- | Calculate Ecliptic Longitude.

-- It takes planet projected longitude, planet projected radius vector

-- the Earth's longitude and radius vector.

planetEclipticLongitude :: PlanetDetails -> DecimalDegrees -> AstronomicalUnits -> DecimalDegrees -> AstronomicalUnits -> DecimalDegrees
planetEclipticLongitude :: PlanetDetails
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
planetEclipticLongitude PlanetDetails
pd
  | PlanetDetails -> Bool
isInnerPlanet PlanetDetails
pd = DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
innerPlanetEclipticLongitude
  | Bool
otherwise = DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
outerPlanetEclipticLongitude


-- | Calculate ecliptic Latitude.

-- It takes the planet's: heliocentric latitude, projected heliocentric longutide,

-- projected heliocentric longitude;

-- the Earth's: heliocentric longitede and heliocentric radius vector.

-- Also it takes the planet's ecliptic longitude.

planetEclipticLatitude :: DecimalDegrees
                          -> DecimalDegrees
                          -> AstronomicalUnits
                          -> DecimalDegrees
                          -> AstronomicalUnits
                          -> DecimalDegrees
                          -> DecimalDegrees
planetEclipticLatitude :: DecimalDegrees
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> DecimalDegrees
planetEclipticLatitude DecimalDegrees
psi DecimalDegrees
lp (AU TimeBaseType
rp) DecimalDegrees
le (AU TimeBaseType
re) DecimalDegrees
lambda =
  let psi' :: TimeBaseType
psi' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
psi
      lp' :: TimeBaseType
lp' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
lp
      le' :: TimeBaseType
le' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
le
      lambda' :: TimeBaseType
lambda' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
lambda
      y :: TimeBaseType
y = TimeBaseType
rpTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
tan TimeBaseType
psi')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
lambda' TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
lp')
      x :: TimeBaseType
x = TimeBaseType
re TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
* (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
lp' TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
le')
  in TimeBaseType -> DecimalDegrees
fromRadians (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
atan (TimeBaseType
yTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Fractional a => a -> a -> a
/TimeBaseType
x)


-- | Calculate the planet's postion at the given date.

-- It takes a function to calculate true anomaly,

-- planet details of the planet, planet details of the Earth

-- and JulianDate.

planetPosition :: (PlanetDetails -> JulianDate -> DecimalDegrees)
                  -> PlanetDetails -> PlanetDetails -> JulianDate
                  -> EquatorialCoordinates1
planetPosition :: (PlanetDetails -> JulianDate -> DecimalDegrees)
-> PlanetDetails
-> PlanetDetails
-> JulianDate
-> EquatorialCoordinates1
planetPosition PlanetDetails -> JulianDate -> DecimalDegrees
trueAnomaly PlanetDetails
pd PlanetDetails
ed JulianDate
jd =
      -- planet

  let nup :: DecimalDegrees
nup = PlanetDetails -> JulianDate -> DecimalDegrees
trueAnomaly PlanetDetails
pd JulianDate
jd
      lp :: DecimalDegrees
lp = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude PlanetDetails
pd DecimalDegrees
nup
      rp :: AstronomicalUnits
rp = PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector PlanetDetails
pd DecimalDegrees
nup
      psi :: DecimalDegrees
psi = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLatitude PlanetDetails
pd DecimalDegrees
lp
      lp' :: DecimalDegrees
lp' = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetProjectedLongitude PlanetDetails
pd DecimalDegrees
lp
      rp' :: AstronomicalUnits
rp' = PlanetDetails
-> DecimalDegrees -> AstronomicalUnits -> AstronomicalUnits
planetProjectedRadiusVector PlanetDetails
pd DecimalDegrees
psi AstronomicalUnits
rp
      -- earth

      nue :: DecimalDegrees
nue = PlanetDetails -> JulianDate -> DecimalDegrees
trueAnomaly PlanetDetails
ed JulianDate
jd
      le :: DecimalDegrees
le = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude PlanetDetails
ed DecimalDegrees
nue
      re :: AstronomicalUnits
re = PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector PlanetDetails
ed DecimalDegrees
nue
      -- position

      lambda :: DecimalDegrees
lambda = PlanetDetails
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
planetEclipticLongitude PlanetDetails
pd DecimalDegrees
lp' AstronomicalUnits
rp' DecimalDegrees
le AstronomicalUnits
re
      beta :: DecimalDegrees
beta = DecimalDegrees
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> DecimalDegrees
planetEclipticLatitude DecimalDegrees
psi DecimalDegrees
lp' AstronomicalUnits
rp' DecimalDegrees
le AstronomicalUnits
re DecimalDegrees
lambda
      ec :: EquatorialCoordinates1
ec = EclipticCoordinates -> JulianDate -> EquatorialCoordinates1
eclipticToEquatorial (DecimalDegrees -> DecimalDegrees -> EclipticCoordinates
EcC DecimalDegrees
beta DecimalDegrees
lambda) JulianDate
jd
    in EquatorialCoordinates1
ec


-- | Calculates the distance betweeth the planet and the Earth at the given date.

-- It takes a function to calculate true anomaly,

-- planet details of the planet, planet details of the Earth

-- and JulianDate.

planetDistance :: (PlanetDetails -> JulianDate -> DecimalDegrees)
                  -> PlanetDetails -> PlanetDetails -> JulianDate
                  -> AstronomicalUnits
planetDistance :: (PlanetDetails -> JulianDate -> DecimalDegrees)
-> PlanetDetails
-> PlanetDetails
-> JulianDate
-> AstronomicalUnits
planetDistance PlanetDetails -> JulianDate -> DecimalDegrees
trueAnomaly PlanetDetails
pd PlanetDetails
ed JulianDate
jd =
  let nup :: DecimalDegrees
nup = PlanetDetails -> JulianDate -> DecimalDegrees
trueAnomaly PlanetDetails
pd JulianDate
jd
      lp :: DecimalDegrees
lp = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude PlanetDetails
pd DecimalDegrees
nup
      AU TimeBaseType
rp = PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector PlanetDetails
pd DecimalDegrees
nup
      psi :: DecimalDegrees
psi = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLatitude PlanetDetails
pd DecimalDegrees
lp
      -- earth

      nue :: DecimalDegrees
nue = PlanetDetails -> JulianDate -> DecimalDegrees
trueAnomaly PlanetDetails
ed JulianDate
jd
      le :: DecimalDegrees
le = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude PlanetDetails
ed DecimalDegrees
nue
      AU TimeBaseType
re = PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector PlanetDetails
ed DecimalDegrees
nue
      -- distance

      ro :: TimeBaseType
ro = TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sqrt (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
reTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
re TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
rpTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
rp TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
2TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
reTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
rpTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos (TimeBaseType -> TimeBaseType)
-> (DecimalDegrees -> TimeBaseType)
-> DecimalDegrees
-> TimeBaseType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ DecimalDegrees
lp DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
- DecimalDegrees
le)TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
psi)
    in TimeBaseType -> AstronomicalUnits
AU TimeBaseType
ro


-- | Calculates the planet's angular diameter for the given distance.

planetAngularDiameter :: PlanetDetails -> AstronomicalUnits -> DecimalDegrees
planetAngularDiameter :: PlanetDetails -> AstronomicalUnits -> DecimalDegrees
planetAngularDiameter PlanetDetails
pd (AU TimeBaseType
ro) = (PlanetDetails -> DecimalDegrees
pdBigTheta PlanetDetails
pd)DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Fractional a => a -> a -> a
/(TimeBaseType -> DecimalDegrees
DD TimeBaseType
ro)


-- | Calculate the planet's phase at the given phase.

-- Phase is a fraction of the visible disc that is illuminated.

-- It takes the planet's details, the Earth's details and the julian date.

-- Returns fraction values from 0 to 1.

planetPhase1 :: PlanetDetails -> PlanetDetails -> JulianDate -> Double
planetPhase1 :: PlanetDetails -> PlanetDetails -> JulianDate -> TimeBaseType
planetPhase1 PlanetDetails
pd PlanetDetails
ed JulianDate
jd =
      -- planet

  let nup :: DecimalDegrees
nup = PlanetDetails -> JulianDate -> DecimalDegrees
planetTrueAnomaly1 PlanetDetails
pd JulianDate
jd
      lp :: DecimalDegrees
lp = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude PlanetDetails
pd DecimalDegrees
nup
      rp :: AstronomicalUnits
rp = PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector PlanetDetails
pd DecimalDegrees
nup
      psi :: DecimalDegrees
psi = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLatitude PlanetDetails
pd DecimalDegrees
lp
      lp' :: DecimalDegrees
lp' = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetProjectedLongitude PlanetDetails
pd DecimalDegrees
lp
      rp' :: AstronomicalUnits
rp' = PlanetDetails
-> DecimalDegrees -> AstronomicalUnits -> AstronomicalUnits
planetProjectedRadiusVector PlanetDetails
pd DecimalDegrees
psi AstronomicalUnits
rp
      -- earth

      nue :: DecimalDegrees
nue = PlanetDetails -> JulianDate -> DecimalDegrees
planetTrueAnomaly1 PlanetDetails
ed JulianDate
jd
      le :: DecimalDegrees
le = PlanetDetails -> DecimalDegrees -> DecimalDegrees
planetHeliocentricLongitude PlanetDetails
ed DecimalDegrees
nue
      re :: AstronomicalUnits
re = PlanetDetails -> DecimalDegrees -> AstronomicalUnits
planetHeliocentricRadiusVector PlanetDetails
ed DecimalDegrees
nue

      lambda :: DecimalDegrees
lambda = PlanetDetails
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
-> AstronomicalUnits
-> DecimalDegrees
planetEclipticLongitude PlanetDetails
pd DecimalDegrees
lp' AstronomicalUnits
rp' DecimalDegrees
le AstronomicalUnits
re
      d :: TimeBaseType
d = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ DecimalDegrees
lambda DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
- DecimalDegrees
lp
    in (TimeBaseType
1TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
d)) TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
* TimeBaseType
0.5


-- | Calculate the planet's postion at the given date using the approximate algoruthm.

-- It takes planet details of the planet, planet details of the Earth

-- and JulianDate.

planetPosition1 :: PlanetDetails -> PlanetDetails -> JulianDate
                  -> EquatorialCoordinates1
planetPosition1 :: PlanetDetails
-> PlanetDetails -> JulianDate -> EquatorialCoordinates1
planetPosition1 = (PlanetDetails -> JulianDate -> DecimalDegrees)
-> PlanetDetails
-> PlanetDetails
-> JulianDate
-> EquatorialCoordinates1
planetPosition PlanetDetails -> JulianDate -> DecimalDegrees
planetTrueAnomaly1


-- | Calculates the distance betweeth the planet and the Earth at the given date

-- using the approximate algoruthm.

-- It takes planet details of the planet, planet details of the Earth

-- and JulianDate.

planetDistance1 :: PlanetDetails -> PlanetDetails -> JulianDate
                  -> AstronomicalUnits
planetDistance1 :: PlanetDetails -> PlanetDetails -> JulianDate -> AstronomicalUnits
planetDistance1 = (PlanetDetails -> JulianDate -> DecimalDegrees)
-> PlanetDetails
-> PlanetDetails
-> JulianDate
-> AstronomicalUnits
planetDistance PlanetDetails -> JulianDate -> DecimalDegrees
planetTrueAnomaly1


-- | Calculates pertubations for the planet at the given julian date.

-- Returns a value that should be added to the mean longitude (planet heliocentric longitude).

planetPertubations :: Planet -> JulianDate -> DecimalDegrees
planetPertubations :: Planet -> JulianDate -> DecimalDegrees
planetPertubations Planet
Jupiter JulianDate
jd =
  let (TimeBaseType
a, DecimalDegrees
_, DecimalDegrees
v, DecimalDegrees
_) = JulianDate
-> (TimeBaseType, DecimalDegrees, DecimalDegrees, DecimalDegrees)
pertubationsQuantities JulianDate
jd
      v' :: TimeBaseType
v' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
v
      dl :: TimeBaseType
dl = (TimeBaseType
0.3314TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
0.0103TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
a)TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
v') TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
0.0644TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
aTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
v')
  in TimeBaseType -> DecimalDegrees
DD TimeBaseType
dl
planetPertubations Planet
Saturn JulianDate
jd =
  let (TimeBaseType
a, DecimalDegrees
q, DecimalDegrees
v, DecimalDegrees
b) = JulianDate
-> (TimeBaseType, DecimalDegrees, DecimalDegrees, DecimalDegrees)
pertubationsQuantities JulianDate
jd
      q' :: TimeBaseType
q' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
q
      v' :: TimeBaseType
v' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
v
      b' :: TimeBaseType
b' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
b
      dl :: TimeBaseType
dl = (TimeBaseType
0.1609TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
aTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
0.0105)TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
v') TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ (TimeBaseType
0.0182TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
aTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
-TimeBaseType
0.8142)TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
v') TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
0.1488TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
b')
        TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- TimeBaseType
0.0408TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin (TimeBaseType -> TimeBaseType) -> TimeBaseType -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ TimeBaseType
2TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
b') TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
0.0856TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
b')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
q') TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
0.0813TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
b')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
q')
  in TimeBaseType -> DecimalDegrees
DD TimeBaseType
dl
planetPertubations Planet
_ JulianDate
_ = DecimalDegrees
0


-- pertrubationsQuantities :: JulianDate

pertubationsQuantities :: JulianDate
-> (TimeBaseType, DecimalDegrees, DecimalDegrees, DecimalDegrees)
pertubationsQuantities JulianDate
jd =
  let t :: TimeBaseType
t = JulianDate -> JulianDate -> TimeBaseType
numberOfCenturies JulianDate
j1900 JulianDate
jd
      a :: TimeBaseType
a = TimeBaseType
tTimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
0.2 TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
0.1
      p :: DecimalDegrees
p = TimeBaseType -> DecimalDegrees
DD (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType
237.47555 TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
3034.9061TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
t
      q :: DecimalDegrees
q = TimeBaseType -> DecimalDegrees
DD (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType
265.91650 TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
+ TimeBaseType
1222.1139TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*TimeBaseType
t
      v :: DecimalDegrees
v = DecimalDegrees
5DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
*DecimalDegrees
q DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
- DecimalDegrees
2DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
*DecimalDegrees
p
      b :: DecimalDegrees
b = DecimalDegrees
q DecimalDegrees -> DecimalDegrees -> DecimalDegrees
forall a. Num a => a -> a -> a
- DecimalDegrees
p
  in (TimeBaseType
a, DecimalDegrees
q, DecimalDegrees
v, DecimalDegrees
b)


-- | Calculate the planet's position-angle of the bright limb.

-- It takes the planet's coordinates and the Sun's coordinates.

-- Position-angle is the angle of the midpoint of the illuminated limb

-- measured eastwards from the north point of the disk.

planetBrightLimbPositionAngle :: EquatorialCoordinates1 -> EquatorialCoordinates1 -> DecimalDegrees
planetBrightLimbPositionAngle :: EquatorialCoordinates1 -> EquatorialCoordinates1 -> DecimalDegrees
planetBrightLimbPositionAngle (EC1 DecimalDegrees
deltaP DecimalHours
alphaP) (EC1 DecimalDegrees
deltaS DecimalHours
alphaS) =
  let dAlpha :: TimeBaseType
dAlpha = DecimalDegrees -> TimeBaseType
toRadians (DecimalDegrees -> TimeBaseType) -> DecimalDegrees -> TimeBaseType
forall a b. (a -> b) -> a -> b
$ DecimalHours -> DecimalDegrees
fromDecimalHours (DecimalHours -> DecimalDegrees) -> DecimalHours -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ DecimalHours
alphaS DecimalHours -> DecimalHours -> DecimalHours
forall a. Num a => a -> a -> a
- DecimalHours
alphaP
      deltaP' :: TimeBaseType
deltaP' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
deltaP
      deltaS' :: TimeBaseType
deltaS' = DecimalDegrees -> TimeBaseType
toRadians DecimalDegrees
deltaS
      y :: TimeBaseType
y = (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
deltaS')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
dAlpha)
      x :: TimeBaseType
x = (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
deltaP')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
deltaS') TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
- (TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
sin TimeBaseType
deltaP')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
deltaS')TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. Num a => a -> a -> a
*(TimeBaseType -> TimeBaseType
forall a. Floating a => a -> a
cos TimeBaseType
dAlpha)
      chi :: DecimalDegrees
chi = DecimalDegrees -> DecimalDegrees
reduceDegrees (DecimalDegrees -> DecimalDegrees)
-> DecimalDegrees -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> DecimalDegrees
fromRadians (TimeBaseType -> DecimalDegrees) -> TimeBaseType -> DecimalDegrees
forall a b. (a -> b) -> a -> b
$ TimeBaseType -> TimeBaseType -> TimeBaseType
forall a. RealFloat a => a -> a -> a
atan2 TimeBaseType
y TimeBaseType
x
  in DecimalDegrees
chi