/// <summary>
    /// Calculate the angle between two celestial objects
    /// </summary>
    /// <returns>Tuple (angleDeg, angleMin, angleSec)</returns>
    public (double angleDeg, double angleMin, double angleSec) AngleBetweenTwoObjects(double raLong1HourDeg, double raLong1Min, double raLong1Sec, double decLat1Deg, double decLat1Min, double decLat1Sec, double raLong2HourDeg, double raLong2Min, double raLong2Sec, double decLat2Deg, double decLat2Min, double decLat2Sec, PAAngleMeasure hourOrDegree)
    {
        var raLong1Decimal = (hourOrDegree == PAAngleMeasure.Hours) ? PAMacros.HMStoDH(raLong1HourDeg, raLong1Min, raLong1Sec) : PAMacros.DegreesMinutesSecondsToDecimalDegrees(raLong1HourDeg, raLong1Min, raLong1Sec);
        var raLong1Deg     = (hourOrDegree == PAAngleMeasure.Hours) ? PAMacros.DegreeHoursToDecimalDegrees(raLong1Decimal) : raLong1Decimal;

        var raLong1Rad  = raLong1Deg.ToRadians();
        var decLat1Deg1 = PAMacros.DegreesMinutesSecondsToDecimalDegrees(decLat1Deg, decLat1Min, decLat1Sec);
        var decLat1Rad  = decLat1Deg1.ToRadians();

        var raLong2Decimal = (hourOrDegree == PAAngleMeasure.Hours) ? PAMacros.HMStoDH(raLong2HourDeg, raLong2Min, raLong2Sec) : PAMacros.DegreesMinutesSecondsToDecimalDegrees(raLong2HourDeg, raLong2Min, raLong2Sec);
        var raLong2Deg     = (hourOrDegree == PAAngleMeasure.Hours) ? PAMacros.DegreeHoursToDecimalDegrees(raLong2Decimal) : raLong2Decimal;
        var raLong2Rad     = raLong2Deg.ToRadians();
        var decLat2Deg1    = PAMacros.DegreesMinutesSecondsToDecimalDegrees(decLat2Deg, decLat2Min, decLat2Sec);
        var decLat2Rad     = decLat2Deg1.ToRadians();

        var cosD = decLat1Rad.Sine() * decLat2Rad.Sine() + decLat1Rad.Cosine() * decLat2Rad.Cosine() * (raLong1Rad - raLong2Rad).Cosine();
        var dRad = cosD.ACosine();
        var dDeg = PAMacros.Degrees(dRad);

        var angleDeg = PAMacros.DecimalDegreesDegrees(dDeg);
        var angleMin = PAMacros.DecimalDegreesMinutes(dDeg);
        var angleSec = PAMacros.DecimalDegreesSeconds(dDeg);

        return(angleDeg, angleMin, angleSec);
    }
    /// <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 precession (corrected coordinates between two epochs)
    /// </summary>
    /// <returns>Tuple (correctedRAHour, correctedRAMinutes, correctedRASeconds, correctedDecDeg, correctedDecMinutes, correctedDecSeconds)</returns>
    public (double correctedRAHour, double correctedRAMinutes, double correctedRASeconds, double correctedDecDeg, double correctedDecMinutes, double correctedDecSeconds) CorrectForPrecession(double raHour, double raMinutes, double raSeconds, double decDeg, double decMinutes, double decSeconds, double epoch1Day, int epoch1Month, int epoch1Year, double epoch2Day, int epoch2Month, int epoch2Year)
    {
        var ra1Rad     = (PAMacros.DegreeHoursToDecimalDegrees(PAMacros.HMStoDH(raHour, raMinutes, raSeconds))).ToRadians();
        var dec1Rad    = (PAMacros.DegreesMinutesSecondsToDecimalDegrees(decDeg, decMinutes, decSeconds)).ToRadians();
        var tCenturies = (PAMacros.CivilDateToJulianDate(epoch1Day, epoch1Month, epoch1Year) - 2415020) / 36525;
        var mSec       = 3.07234 + (0.00186 * tCenturies);
        var nArcsec    = 20.0468 - (0.0085 * tCenturies);
        var nYears     = (PAMacros.CivilDateToJulianDate(epoch2Day, epoch2Month, epoch2Year) - PAMacros.CivilDateToJulianDate(epoch1Day, epoch1Month, epoch1Year)) / 365.25;
        var s1Hours    = ((mSec + (nArcsec * (ra1Rad).Sine() * (dec1Rad).Tangent() / 15)) * nYears) / 3600;
        var ra2Hours   = PAMacros.HMStoDH(raHour, raMinutes, raSeconds) + s1Hours;
        var s2Deg      = (nArcsec * (ra1Rad).Cosine() * nYears) / 3600;
        var dec2Deg    = PAMacros.DegreesMinutesSecondsToDecimalDegrees(decDeg, decMinutes, decSeconds) + s2Deg;

        var correctedRAHour     = PAMacros.DecimalHoursHour(ra2Hours);
        var correctedRAMinutes  = PAMacros.DecimalHoursMinute(ra2Hours);
        var correctedRASeconds  = PAMacros.DecimalHoursSecond(ra2Hours);
        var correctedDecDeg     = PAMacros.DecimalDegreesDegrees(dec2Deg);
        var correctedDecMinutes = PAMacros.DecimalDegreesMinutes(dec2Deg);
        var correctedDecSeconds = PAMacros.DecimalDegreesSeconds(dec2Deg);

        return(correctedRAHour, correctedRAMinutes, correctedRASeconds, correctedDecDeg, correctedDecMinutes, correctedDecSeconds);
    }
    /// <summary>
    /// Convert Equatorial Coordinates to Galactic Coordinates
    /// </summary>
    /// <returns>Tuple (galLongDeg, galLongMin, galLongSec, galLatDeg, galLatMin, galLatSec)</returns>
    public (double galLongDeg, double galLongMin, double galLongSec, double galLatDeg, double galLatMin, double galLatSec) EquatorialCoordinateToGalacticCoordinate(double raHours, double raMinutes, double raSeconds, double decDegrees, double decMinutes, double decSeconds)
    {
        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 sinB     = decRad.Cosine() * (27.4).ToRadians().Cosine() * (raRad - (192.25).ToRadians()).Cosine() + decRad.Sine() * (27.4).ToRadians().Sine();
        var bRadians = sinB.ASine();
        var bDeg     = PAMacros.Degrees(bRadians);
        var y        = decRad.Sine() - sinB * (27.4).ToRadians().Sine();
        var x        = decRad.Cosine() * (raRad - (192.25).ToRadians()).Sine() * (27.4).ToRadians().Cosine();
        var longDeg1 = PAMacros.Degrees(y.AngleTangent2(x)) + 33;
        var longDeg2 = longDeg1 - 360 * (longDeg1 / 360).Floor();

        var galLongDeg = PAMacros.DecimalDegreesDegrees(longDeg2);
        var galLongMin = PAMacros.DecimalDegreesMinutes(longDeg2);
        var galLongSec = PAMacros.DecimalDegreesSeconds(longDeg2);
        var galLatDeg  = PAMacros.DecimalDegreesDegrees(bDeg);
        var galLatMin  = PAMacros.DecimalDegreesMinutes(bDeg);
        var galLatSec  = PAMacros.DecimalDegreesSeconds(bDeg);

        return(galLongDeg, galLongMin, galLongSec, galLatDeg, galLatMin, galLatSec);
    }