/// <summary>
    /// Calculate selenographic (lunar) coordinates (sub-Earth)
    /// </summary>
    /// <returns>sub-earth longitude, sub-earth latitude, and position angle of pole</returns>
    public (double subEarthLongitude, double subEarthLatitude, double positionAngleOfPole) SelenographicCoordinates1(double gwdateDay, int gwdateMonth, int gwdateYear)
    {
        var julianDateDays        = PAMacros.CivilDateToJulianDate(gwdateDay, gwdateMonth, gwdateYear);
        var tCenturies            = (julianDateDays - 2451545) / 36525;
        var longAscNodeDeg        = 125.044522 - 1934.136261 * tCenturies;
        var f1                    = 93.27191 + 483202.0175 * tCenturies;
        var f2                    = f1 - 360 * (f1 / 360).Floor();
        var geocentricMoonLongDeg = PAMacros.MoonLong(0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear);
        var geocentricMoonLatRad  = (PAMacros.MoonLat(0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear)).ToRadians();
        var inclinationRad        = (PAMacros.DegreesMinutesSecondsToDecimalDegrees(1, 32, 32.7)).ToRadians();
        var nodeLongRad           = (longAscNodeDeg - geocentricMoonLongDeg).ToRadians();
        var sinBe                 = -(inclinationRad).Cosine() * (geocentricMoonLatRad).Sine() + (inclinationRad).Sine() * (geocentricMoonLatRad).Cosine() * (nodeLongRad).Sine();
        var subEarthLatDeg        = PAMacros.Degrees((sinBe).ASine());
        var aRad                  = (-(geocentricMoonLatRad).Sine() * (inclinationRad).Sine() - (geocentricMoonLatRad).Cosine() * (inclinationRad).Cosine() * (nodeLongRad).Sine()).AngleTangent2((geocentricMoonLatRad).Cosine() * (nodeLongRad).Cosine());
        var aDeg                  = PAMacros.Degrees(aRad);
        var subEarthLongDeg1      = aDeg - f2;
        var subEarthLongDeg2      = subEarthLongDeg1 - 360 * (subEarthLongDeg1 / 360).Floor();
        var subEarthLongDeg3      = (subEarthLongDeg2 > 180) ? subEarthLongDeg2 - 360 : subEarthLongDeg2;
        var c1Rad                 = ((nodeLongRad).Cosine() * (inclinationRad).Sine() / ((geocentricMoonLatRad).Cosine() * (inclinationRad).Cosine() + (geocentricMoonLatRad).Sine() * (inclinationRad).Sine() * (nodeLongRad).Sine())).AngleTangent();
        var obliquityRad          = (PAMacros.Obliq(gwdateDay, gwdateMonth, gwdateYear)).ToRadians();
        var c2Rad                 = ((obliquityRad).Sine() * ((geocentricMoonLongDeg).ToRadians()).Cosine() / ((obliquityRad).Sine() * (geocentricMoonLatRad).Sine() * ((geocentricMoonLongDeg).ToRadians()).Sine() - (obliquityRad).Cosine() * (geocentricMoonLatRad).Cosine())).AngleTangent();
        var cDeg                  = PAMacros.Degrees(c1Rad + c2Rad);

        var subEarthLongitude   = Math.Round(subEarthLongDeg3, 2);
        var subEarthLatitude    = Math.Round(subEarthLatDeg, 2);
        var positionAngleOfPole = Math.Round(cDeg, 2);

        return(subEarthLongitude, subEarthLatitude, positionAngleOfPole);
    }
    /// <summary>
    /// Convert Equatorial Coordinates to Ecliptic Coordinates
    /// </summary>
    /// <returns>Tuple (outEclLongDeg, outEclLongMin, outEclLongSec, outEclLatDeg, outEclLatMin, outEclLatSec)</returns>
    public (double outEclLongDeg, double outEclLongMin, double outEclLongSec, double outEclLatDeg, double outEclLatMin, double outEclLatSec) EquatorialCoordinateToEclipticCoordinate(double raHours, double raMinutes, double raSeconds, double decDegrees, double decMinutes, double decSeconds, double gwDay, int gwMonth, int gwYear)
    {
        var raDeg       = PAMacros.DegreeHoursToDecimalDegrees(PAMacros.HMStoDH(raHours, raMinutes, raSeconds));
        var decDeg      = PAMacros.DegreesMinutesSecondsToDecimalDegrees(decDegrees, decMinutes, decSeconds);
        var raRad       = raDeg.ToRadians();
        var decRad      = decDeg.ToRadians();
        var obliqDeg    = PAMacros.Obliq(gwDay, gwMonth, gwYear);
        var obliqRad    = obliqDeg.ToRadians();
        var sinEclLat   = decRad.Sine() * obliqRad.Cosine() - decRad.Cosine() * obliqRad.Sine() * raRad.Sine();
        var eclLatRad   = sinEclLat.ASine();
        var eclLatDeg   = PAMacros.Degrees(eclLatRad);
        var y           = raRad.Sine() * obliqRad.Cosine() + decRad.Tangent() * obliqRad.Sine();
        var x           = raRad.Cosine();
        var eclLongRad  = y.AngleTangent2(x);
        var eclLongDeg1 = PAMacros.Degrees(eclLongRad);
        var eclLongDeg2 = eclLongDeg1 - 360 * (eclLongDeg1 / 360).Floor();

        var outEclLongDeg = PAMacros.DecimalDegreesDegrees(eclLongDeg2);
        var outEclLongMin = PAMacros.DecimalDegreesMinutes(eclLongDeg2);
        var outEclLongSec = PAMacros.DecimalDegreesSeconds(eclLongDeg2);
        var outEclLatDeg  = PAMacros.DecimalDegreesDegrees(eclLatDeg);
        var outEclLatMin  = PAMacros.DecimalDegreesMinutes(eclLatDeg);
        var outEclLatSec  = PAMacros.DecimalDegreesSeconds(eclLatDeg);

        return(outEclLongDeg, outEclLongMin, outEclLongSec, outEclLatDeg, outEclLatMin, outEclLatSec);
    }
    /// <summary>
    /// Calculate heliographic coordinates for a given Greenwich date, with a given heliographic position angle and heliographic displacement in arc minutes.
    /// </summary>
    /// <returns>heliographic longitude and heliographic latitude, in degrees</returns>
    public (double helioLongDeg, double helioLatDeg) HeliographicCoordinates(double helioPositionAngleDeg, double helioDisplacementArcmin, double gwdateDay, int gwdateMonth, int gwdateYear)
    {
        var julianDateDays = PAMacros.CivilDateToJulianDate(gwdateDay, gwdateMonth, gwdateYear);
        var tCenturies     = (julianDateDays - 2415020) / 36525;
        var longAscNodeDeg = PAMacros.DegreesMinutesSecondsToDecimalDegrees(74, 22, 0) + (84 * tCenturies / 60);
        var sunLongDeg     = PAMacros.SunLong(0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear);
        var y         = ((longAscNodeDeg - sunLongDeg).ToRadians()).Sine() * ((PAMacros.DegreesMinutesSecondsToDecimalDegrees(7, 15, 0)).ToRadians()).Cosine();
        var x         = -((longAscNodeDeg - sunLongDeg).ToRadians()).Cosine();
        var aDeg      = PAMacros.Degrees(y.AngleTangent2(x));
        var mDeg1     = 360 - (360 * (julianDateDays - 2398220) / 25.38);
        var mDeg2     = mDeg1 - 360 * (mDeg1 / 360).Floor();
        var l0Deg1    = mDeg2 + aDeg;
        var b0Rad     = (((sunLongDeg - longAscNodeDeg).ToRadians()).Sine() * ((PAMacros.DegreesMinutesSecondsToDecimalDegrees(7, 15, 0)).ToRadians()).Sine()).ASine();
        var theta1Rad = (-((sunLongDeg).ToRadians()).Cosine() * ((PAMacros.Obliq(gwdateDay, gwdateMonth, gwdateYear)).ToRadians()).Tangent()).AngleTangent();
        var theta2Rad = (-((longAscNodeDeg - sunLongDeg).ToRadians()).Cosine() * ((PAMacros.DegreesMinutesSecondsToDecimalDegrees(7, 15, 0)).ToRadians()).Tangent()).AngleTangent();
        var pDeg      = PAMacros.Degrees(theta1Rad + theta2Rad);
        var rho1Deg   = helioDisplacementArcmin / 60;
        var rhoRad    = (2 * rho1Deg / PAMacros.SunDia(0, 0, 0, 0, 0, gwdateDay, gwdateMonth, gwdateYear)).ASine() - (rho1Deg).ToRadians();
        var bRad      = ((b0Rad).Sine() * (rhoRad).Cosine() + (b0Rad).Cosine() * (rhoRad).Sine() * ((pDeg - helioPositionAngleDeg).ToRadians()).Cosine()).ASine();
        var bDeg      = PAMacros.Degrees(bRad);
        var lDeg1     = PAMacros.Degrees(((rhoRad).Sine() * ((pDeg - helioPositionAngleDeg).ToRadians()).Sine() / (bRad).Cosine()).ASine()) + l0Deg1;
        var lDeg2     = lDeg1 - 360 * (lDeg1 / 360).Floor();

        var helioLongDeg = Math.Round(lDeg2, 2);
        var helioLatDeg  = Math.Round(bDeg, 2);

        return(helioLongDeg, helioLatDeg);
    }
    /// <summary>
    /// Convert Ecliptic Coordinates to Equatorial Coordinates
    /// </summary>
    /// <returns>Tuple (outRAHours, outRAMinutes, outRASeconds, outDecDegrees, outDecMinutes, outDecSeconds)</returns>
    public (double outRAHours, double outRAMinutes, double outRASeconds, double outDecDegrees, double outDecMinutes, double outDecSeconds) EclipticCoordinateToEquatorialCoordinate(double eclipticLongitudeDegrees, double eclipticLongitudeMinutes, double eclipticLongitudeSeconds, double eclipticLatitudeDegrees, double eclipticLatitudeMinutes, double eclipticLatitudeSeconds, double greenwichDay, int greenwichMonth, int greenwichYear)
    {
        var eclonDeg = PAMacros.DegreesMinutesSecondsToDecimalDegrees(eclipticLongitudeDegrees, eclipticLongitudeMinutes, eclipticLongitudeSeconds);
        var eclatDeg = PAMacros.DegreesMinutesSecondsToDecimalDegrees(eclipticLatitudeDegrees, eclipticLatitudeMinutes, eclipticLatitudeSeconds);
        var eclonRad = eclonDeg.ToRadians();
        var eclatRad = eclatDeg.ToRadians();
        var obliqDeg = PAMacros.Obliq(greenwichDay, greenwichMonth, greenwichYear);
        var obliqRad = obliqDeg.ToRadians();
        var sinDec   = eclatRad.Sine() * obliqRad.Cosine() + eclatRad.Cosine() * obliqRad.Sine() * eclonRad.Sine();
        var decRad   = sinDec.ASine();
        var decDeg   = PAMacros.Degrees(decRad);
        var y        = eclonRad.Sine() * obliqRad.Cosine() - eclatRad.Tangent() * obliqRad.Sine();
        var x        = eclonRad.Cosine();
        var raRad    = y.AngleTangent2(x);
        var raDeg1   = PAMacros.Degrees(raRad);
        var raDeg2   = raDeg1 - 360 * (raDeg1 / 360).Floor();
        var raHours  = PAMacros.DecimalDegreesToDegreeHours(raDeg2);

        var outRAHours    = PAMacros.DecimalHoursHour(raHours);
        var outRAMinutes  = PAMacros.DecimalHoursMinute(raHours);
        var outRASeconds  = PAMacros.DecimalHoursSecond(raHours);
        var outDecDegrees = PAMacros.DecimalDegreesDegrees(decDeg);
        var outDecMinutes = PAMacros.DecimalDegreesMinutes(decDeg);
        var outDecSeconds = PAMacros.DecimalDegreesSeconds(decDeg);

        return(outRAHours, outRAMinutes, outRASeconds, outDecDegrees, outDecMinutes, outDecSeconds);
    }