AstroLib
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Authors: © badsector666 and © BarefootJoey

// ██████████████████████████████████████████████████████████████████████   _____ __   _      _______  _____  _______ _______ _______
// █▄─▄─▀██▀▄─██▄─▄▄▀█▄─▄▄─█▄─▄▄─█─▄▄─█─▄▄─█─▄─▄─███▄─▄█─▄▄─█▄─▄▄─█▄─█─▄█     |   | \  |      |______ |_____] |_____| |       |______
// ██─▄─▀██─▀─███─▄─▄██─▄█▀██─▄███─██─█─██─███─███─▄█─██─██─██─▄█▀██▄─▄██   __|__ |  \_|      ______| |       |     | |_____  |______ 
// █▄▄▄▄██▄▄█▄▄█▄▄█▄▄█▄▄▄▄▄█▄▄▄███▄▄▄▄█▄▄▄▄██▄▄▄██▄▄▄███▄▄▄▄█▄▄▄▄▄██▄▄▄██                                                            

//@version=5
library("AstroLib", overlay=true)

// Internal constants
tpi = math.pi * 2
pi = math.pi

// // @function ToString: Easy to.string() function
export t_(string txt) => str.tostring(txt) 

export JDNv2(float t, bool withFraction) => withFraction ? (t / 86400000) + 2440587.5 : math.floor(t / 86400000) + 2440587.5
export J2K(float t) => (t - 2451545.0)
export J2KtoUnix(float TimeInJDN) => int(math.round((TimeInJDN - 2440587.5) * 86400) * 1000)

export atan2(float y, float x) =>
	if x > 0
		math.atan(y/x)
	else if x < 0 and y >= 0
		math.atan(y/x) + pi
	else if x < 0 and y < 0
		math.atan(y/x) - pi
	else if x == 0 and y > 0
		math.sign(x / 2)
	else if x == 0 and y < 0
		math.sign(x / 2)
	else
		0

// // @function DegSinRad: Input degrees, convert to radians, and output the trigonometric sine of the angle.
export DegSin(float x) => DegSin = math.sin(math.toradians(x))
// // @function DegCosRad: Input degrees, convert to radians, and output the trigonometric cosine of the angle.
export DegCos(float x) => DegCos = math.cos(math.toradians(x))
// // @function DegTanRad: Input degrees, convert to radians, and output the trigonometric tangent of the angle.
export DegTan(float x) => DegTan = math.tan(math.toradians(x))
// // @function DegASinRad: Input radians, compute the trigonometric ArcSine of the angle, and convert to degrees.
export DegArcsin(float x) => DegArcsin = math.todegrees(math.asin(x))
// // @function DegACosRad: Input radians, compute the trigonometric ArcCosine of the angle, and convert to degrees.
export DegArccos(float x) => DegArccos = math.todegrees(math.acos(x))
// // @function DegATanRad: Input radians, compute the trigonometric ArcTangent of the angle, and convert to degrees.
export DegArctan(float x) => DegArctan = math.todegrees(math.atan(x))

export DegAtan2(float y, float x) =>
    DegAtan2 = math.todegrees(atan2(y, x)) < 0 ? math.todegrees(atan2(y, x)) + 360: math.todegrees(atan2(y, x))
export range2pi(float x) => x < 0 ? x - tpi * int(math.sign(x / tpi)) : x - tpi * int(x / tpi)
export range360(float x) => x < 0 ? x - 360 * int(math.sign(x / 360)) : x - 360 * int(x / 360)

// // @function GreenwichSidereal: Compute Sidereal time at Greenwich.
export gst(float days) =>
    T = days / 36525
    gst = 280.46061837 + 360.98564736629 * days
    gst := gst + 0.000387933 * math.pow(T, 2) - math.pow(T, 3) / 38710000
    gst := range360(gst)

// // @function DegDecimal: Input degrees/minutes/seconds, and convert to a float value.
export DegDecimal(float Degrees, float Minutes, float Seconds) =>
    if Degrees < 0
        Minutes > 0 ? Minutes * (-1) : Minutes
        Seconds > 0 ? Seconds * (-1) : Seconds
    DegDecimal = Degrees + (Minutes) + (Seconds / 3600)

export Rectangular(float R, float theta, float phi, float Index) =>
    r_cos_theta = R * DegCos(theta)
    switch Index
        1 => Rectangular = r_cos_theta * DegCos(phi)
        2 => Rectangular = r_cos_theta * DegSin(phi)
        3 => Rectangular = R * DegSin(theta)

export rLength(float x, float y, float z) => rLength = math.sqrt(x * x + y * y + z * z)
export spherical(float x, float y, float z, float Index) =>
    rho = x * x + y * y
    switch Index
        1 => spherical = math.sqrt(rho + z * z)
        2 => 
            rho := math.sqrt(rho)
            spherical = DegArctan(z / rho)
        3 => 
            rho := math.sqrt(rho)
            spherical = DegAtan2(y, x)

// // @function Obliquity: Input a day, and calculate obliquity.
export obliquity(float d) =>
    T = d / 36525
    obliquity = -(46.815 + (0.00059 - 0.001813 * T) * T) * T / 3600
    obliquity2 = obliquity + 23.43929111

// // @function Equitorial: Calculate the equatorial coordinates.
export requatorial(float x, float y, float z, float d, float Index) =>
    obl = obliquity(d)
    switch Index
        1 => requatorial = x
        2 => requatorial = y * DegCos(obl) - z * DegSin(obl)
        3 => requatorial = y * DegSin(obl) + z * DegCos(obl)

// // @function Ecliptic: Calculate the ecliptic coordinates.
export recliptic(float x, float y, float z, float d, float Index) =>
    obl = obliquity(d)
    switch Index
        1 => recliptic = x
        2 => recliptic = y * DegCos(obl) + z * DegSin(obl)
        3 => recliptic = -y * DegSin(obl) + z * DegCos(obl)

export sequatorial(float R, float theta, float phi, float d, float Index) =>
    x = Rectangular(R, theta, phi, 1)
    y = Rectangular(R, theta, phi, 2)
    z = Rectangular(R, theta, phi, 3)
    sequatorial = spherical(requatorial(x, y, z, d, 1), requatorial(x, y, z, d, 2), requatorial(x, y, z, d, 3), Index)

export secliptic(float R, float theta, float phi, float d, float Index) =>
    x = Rectangular(R, theta, phi, 1)
    y = Rectangular(R, theta, phi, 2)
    z = Rectangular(R, theta, phi, 3)
    secliptic = spherical(recliptic(x, y, z, d, 1), recliptic(x, y, z, d, 2), recliptic(x, y, z, d, 3), Index)

export precess(float d1, float d2, float DEC, float RA, float Index, float ddec, float dra) =>
    dra2 = na(dra) ? 0 : dra
    ddec2 = na(ddec) ? 0 : ddec
    T = d1 / 36525
    m = 0.01281233333333 + 0.00000775 * T
    N = 0.005567527777778 - 2.361111111111E-06 * T
    T2 = (d2 - d1) / 365.25
    switch Index
        1 => precess = DEC + (N * DegCos(RA) + ddec2 / 3600) * T2
        2 => precess = RA + (m + N * DegSin(RA) * DegTan(DEC) + dra2 / 3600) * T2

export riset(float J2000, float DEC, float RA, float GLat, float GLong, float Index) =>
    lst = gst(J2000) + GLong 
    tau = DegSin(-34 / 60) - DegSin(GLat) * DegSin(DEC)
    tau := tau / (DegCos(GLat) * DegCos(DEC))
    tau := DegArccos(tau)
    switch Index
        1 => riset = range360(360 - 0.9972696 * (lst - RA + tau))
        2 =>
            if RA > lst
                riset = math.abs(0.9972696 * (lst - RA))
            else
                riset = 360 - 0.9972696 * (lst - RA)
        3 => riset = range360(0.9972696 * (RA + tau - lst))

export ssun(float d, float Index) =>
    g = range360(357.528 + 0.9856003 * d)
    L = range360(280.461 + 0.9856474 * d)
    switch Index
        1 => ssun = 1.00014 - 0.01671 * DegCos(g) - 0.00014 * DegCos(2 * g)
        2 => ssun = 0
        3 => ssun = range360(L + 1.915 * DegSin(g) + 0.02 * DegSin(2 * g))
        4 =>
            lambda = range360(L + 1.915 * DegSin(g) + 0.02 * DegSin(2 * g))
            ssun = -1.915 * DegSin(g) - 0.02 * DegSin(2 * g)
            ssun := ssun + 2.466 * DegSin(2 * lambda)
            ssun := ssun - 0.053 * DegSin(4 * lambda)

export rsun(float d, float Index) => rsun = Rectangular(ssun(d, 1), ssun(d, 2), ssun(d, 3), Index)
export sun(float d, float Index) => sun = sequatorial(ssun(d, 1), ssun(d, 2), ssun(d, 3), d, Index)

export SunLongitude(float d, float Index) =>
    T = d / 36525
    L0 = 280.46646 + 36000.76983 * T + 0.0003032 * T * T
    L0 := range360(L0)
    m = 357.52911 + 35999.05029 * T - (0.0001537 * T * T)
    m := range360(m)
    e = 0.016708634 - 0.000042037 * T - (0.0000001267 * T * T)
    C = (1.914602 - 0.004817 * T - 0.000014 * T * T) * DegSin(m) + (0.019993 - 0.000101 * T) * DegSin(2 * m) + 0.000289 * DegSin(3 * m)
    O = L0 + C
    lam = 0.0
    if Index == 2
        ohm = 125.04 - 1934.136 * T
        lam := O - 0.00569 - 0.00478 * DegSin(ohm)
    if Index == 1
        SunLongitude = O
    else
        SunLongitude = lam

export Sunrise(float J2000, float GLat, float GLong, float Index, float altitudex) =>
    altitude = na(altitudex) or altitudex == 0 ? -0.833 : altitudex
    utold = 180.0
    utnew = 0.0
    sinalt = math.sin(math.toradians(altitude))
    sinphi = DegSin(GLat)
    cosphi = DegCos(GLat)
    signt = Index == 1 ? 1 : -1
    
    while math.abs(utold - utnew) > 0.1
        utold := utnew
        days = J2000 + utold / 360
        T = days / 36525
        L = range360(280.46 + 36000.77 * T)
        g = 357.528 + 35999.05 * T
        lambda = L + 1.915 * DegSin(g) + 0.02 * DegSin(2 * g)
        e = -1.915 * DegSin(g) - 0.02 * DegSin(2 * g) + 2.466 * DegSin(2 * lambda) - 0.053 * DegSin(4 * lambda)
        obl = 23.4393 - 0.13 * T
        gha = utold + (-180 + e)
        delta = DegArcsin(DegSin(obl) * DegSin(lambda))
        C = (sinalt - sinphi * DegSin(delta)) / (cosphi * DegCos(delta))
        act = DegArccos(C)
        if C > 1
            act := 0
        if C < -1
            act := 180
        utnew := range360(utold - (gha + GLong + signt * act))
    Sunrise = utnew

export smoon(float dx, float Index) =>
    d = dx + 1.5
    Nm = math.toradians(range360(125.1228 - 0.0529538083 * d))
    im = math.toradians(5.1454) * 100
    wm = math.toradians(range360(318.0634 + 0.1643573223 * d))
    am = 60.2666
    ecm = 0.0549
    Mm = math.toradians(range360(115.3654 + 13.0649929509 * d))
    em = Mm + ecm * math.sin(Mm) * (1 + ecm * math.cos(Mm))
    xv = am * (math.cos(em) - ecm)
    yv = am * (math.sqrt(1 - ecm * ecm) * math.sin(em))
    vm = atan2(yv, xv)
    rm = math.sqrt(xv * xv + yv * yv)
    x = math.cos(Nm) * math.cos(vm + wm)- math.sin(Nm) * math.sin(vm + wm) * math.cos((im / 100))
    x := rm * x
    y = math.sin(Nm) * math.cos(vm + wm) + math.cos(Nm) * math.sin(vm + wm) * math.cos((im / 100))
    y := rm * y
    z = rm * (math.sin(vm + wm) * math.sin((im / 100)))
    lon = atan2(y, x)
    lon2 = lon < 0 ? tpi + lon : lon
    lat = math.atan(z / math.sqrt(x * x + y * y))
    ws = math.toradians(range360(282.9404 + 0.0000470935 * d))
    Ms = math.toradians(range360(356.047 + 0.9856002585 * d))
    ls = Ms + ws
    lm = Mm + wm + Nm
    dm = lm - ls
    f = lm - Nm
    switch Index
        1 =>
            rm := rm - 0.58 * math.cos(Mm - 2 * dm)
            rm := rm - 0.46 * math.cos(2 * dm)
            smoon = rm
        2 =>
            dlat = -0.173 * math.sin(f - 2 * dm)
            dlat := dlat - 0.055 * math.sin(Mm - f - 2 * dm)
            dlat := dlat - 0.046 * math.sin(Mm + f - 2 * dm)
            dlat := dlat + 0.033 * math.sin(f + 2 * dm)
            dlat := dlat + 0.017 * math.sin(2 * Mm + f)
            smoon = math.todegrees(lat) + dlat
        3 =>
            dlon = -1.274 * math.sin(Mm - 2 * dm)
            dlon := dlon + 0.658 * math.sin(2 * dm)
            dlon := dlon - 0.186 * math.sin(Ms)
            dlon := dlon - 0.059 * math.sin(2 * Mm - 2 * dm)
            dlon := dlon - 0.057 * math.sin(Mm - 2 * dm + Ms)
            dlon := dlon + 0.053 * math.sin(Mm + 2 * dm)
            dlon := dlon + 0.046 * math.sin(2 * dm - Ms)
            dlon := dlon + 0.041 * math.sin(Mm - Ms)
            dlon := dlon - 0.035 * math.sin(dm)
            dlon := dlon - 0.031 * math.sin(Mm + Ms)
            dlon := dlon - 0.015 * math.sin(2 * f - 2 * dm)
            dlon := dlon + 0.011 * math.sin(Mm - 4 * dm)
            smoon = math.todegrees(lon2) + dlon

export rmoon(float d, float Index) => rmoon = Rectangular(smoon(d, 1), smoon(d, 2), smoon(d, 3), Index)

export tmoon(float d, float GLat, float GLong, float Index) =>
    x = rmoon(d, 1)
    y = rmoon(d, 2)
    z = rmoon(d, 3)
    xe = requatorial(x, y, z, d, 1)
    ye = requatorial(x, y, z, d, 2)
    ze = requatorial(x, y, z, d, 3)
    R = rLength(x, y, z)
    lst = gst(d) + GLong
    xt = xe - DegCos(GLat) * DegCos(lst)
    yt = ye - DegCos(GLat) * DegSin(lst)
    zt = ze - DegSin(GLat)
    tmoon = spherical(xt, yt, zt, Index)

export moon(float d, float Index) =>
    if Index == 4
        nigel = smoon(d, 2)
        moon = d
    else
        moon = sequatorial(smoon(d, 1), smoon(d, 2), smoon(d, 3), d, Index)

// // @function KeplerianElements: Input a day and planet number, and outputs the following Keplerian Elements: semi major axis, eccentricity, inclination, mean longitude, longitude of the ascending node, and longitude of the perhelion.
export Element(float d, int pnum) =>
    switch pnum
        1 => // Mercury
            I = math.toradians(7.00487 - 0.000000178797 * d)
            O = math.toradians(48.33167 - 0.0000033942 * d)
            P = math.toradians(77.45645 + 0.00000436208 * d)
            a = 0.38709893 + 1.80698E-11 * d
            e = 0.20563069 + 0.000000000691855 * d
            L = range2pi(math.toradians(252.25084 + 4.092338796 * d))
            [I, O, P, a, e, L]
        2 => // Venus
            I = math.toradians(3.39471 - 0.0000000217507 * d)
            O = math.toradians(76.68069 - 0.0000075815 * d)
            P = math.toradians(131.53298 - 0.000000827439 * d)
            a = 0.72333199 + 2.51882E-11 * d
            e = 0.00677323 - 0.00000000135195 * d
            L = range2pi(math.toradians(181.97973 + 1.602130474 * d))
            [I, O, P, a, e, L]
        3 => // Earth
            I = math.toradians(0.00005 - 0.000000356985 * d)
            O = math.toradians(-11.26064 - 0.00013863 * d)
            P = math.toradians(102.94719 + 0.00000911309 * d)
            a = 1.00000011 - 1.36893E-12 * d
            e = 0.01671022 - 0.00000000104148 * d
            L = range2pi(math.toradians(100.46435 + 0.985609101 * d))
            [I, O, P, a, e, L]
        4 => // Mars
            I = math.toradians(1.85061 - 0.000000193703 * d)
            O = math.toradians(49.57854 - 0.0000077587 * d)
            P = math.toradians(336.04084 + 0.00001187 * d)
            a = 1.52366231 - 0.000000001977 * d
            e = 0.09341233 - 0.00000000325859 * d
            L = range2pi(math.toradians(355.45332 + 0.524033035 * d))
            [I, O, P, a, e, L]
        5 => // Jupiter
            I = math.toradians(1.3053 - 0.0000000315613 * d)
            O = math.toradians(100.55615 + 0.00000925675 * d)
            P = math.toradians(14.75385 + 0.00000638779 * d)
            a = 5.20336301 + 0.0000000166289 * d
            e = 0.04839266 - 0.00000000352635 * d
            L = range2pi(math.toradians(34.40438 + 0.083086762 * d))
            [I, O, P, a, e, L]
        6 => // Saturn
            I = math.toradians(2.48446 + 0.0000000464674 * d)
            O = math.toradians(113.71504 - 0.0000121 * d)
            P = math.toradians(92.43194 - 0.0000148216 * d)
            a = 9.53707032 - 0.0000000825544 * d
            e = 0.0541506 - 0.0000000100649 * d
            L = range2pi(math.toradians(49.94432 + 0.033470629 * d))
            [I, O, P, a, e, L]
        7 => // Uranus
            I = math.toradians(0.76986 - 0.0000000158947 * d)
            O = math.toradians(74.22988 + 0.0000127873 * d)
            P = math.toradians(170.96424 + 0.0000099822 * d)
            a = 19.19126393 + 0.0000000416222 * d
            e = 0.04716771 - 0.00000000524298 * d
            L = range2pi(math.toradians(313.23218 + 0.011731294 * d))
            [I, O, P, a, e, L]
        8 => // Neptune
            I = math.toradians(1.76917 - 0.0000000276827 * d)
            O = math.toradians(131.72169 - 0.0000011503 * d)
            P = math.toradians(44.97135 - 0.00000642201 * d)
            a = 30.06896348 - 0.0000000342768 * d
            e = 0.00858587 + 0.000000000688296 * d
            L = range2pi(math.toradians(304.88003 + 0.0059810572 * d))
            [I, O, P, a, e, L]
        9 => // Pluto?
            I = math.toradians(17.14175 + 0.0000000841889 * d)
            O = math.toradians(110.30347 - 0.0000002839 * d)
            P = math.toradians(224.06676 - 0.00000100578 * d)
            a = 39.48168677 - 0.0000000210574 * d
            e = 0.24880766 + 0.00000000177002 * d
            L = range2pi(math.toradians(238.92881 + 3.97557152635181E-03 * d))
            [I, O, P, a, e, L]

// // @function KeplerSolve: Input mean anomaly, eccintricity, and eps, Solution of Kepler's Equation.
export kepler(float m, float ecc, float eps) =>
    e = m
    delta = 0.05
    eps2 = na(eps) ? 8 : eps
    while math.abs(delta) >= math.pow(10, -eps2)
        delta := e - ecc * math.sin(e) - m
        e := e - delta / (1 - ecc * math.cos(e))
    V = 2 * math.atan( math.pow( ((1 + ecc) / (1 - ecc)), 0.5) * math.tan(0.5 * e))
    if V < 0
        V := V + tpi
    kepler = V

export rplanet(float d, int pnumber, float Index) =>
    [I, O, P, a, e, L] = Element(d, pnumber)
    m = range2pi(L - P)
    V = kepler(m, e, 8)
    R = a * (1 - e * e) / (1 + e * math.cos(V))
    switch Index
        1 => 
            rplanet = math.cos(O) * math.cos(V + P - O) - math.sin(O) * math.sin(V + P - O) * math.cos(I)
            rplanet := rplanet * R
        2 =>
            rplanet = math.sin(O) * math.cos(V + P - O) + math.cos(O) * math.sin(V + P - O) * math.cos(I)
            rplanet := rplanet * R
        3 => rplanet = R * (math.sin(V + P - O) * math.sin(I))

export planet(float d, int pnumber, float Index) =>
    [I, O, P, a, e, L] = Element(d, pnumber)
    m = range2pi(L - P)
    V = kepler(m, e, 8)
    R = a * (1 - e * e) / (1 + e * math.cos(V))
    s1 = math.sin(V + P - O)
    si = math.sin(I)
    so = math.sin(O)
    C1 = math.cos(V + P - O)
    CI = math.cos(I)
    co = math.cos(O)
    x = R * (co * C1 - so * s1 * CI)
    y = R * (so * C1 + co * s1 * CI)
    z = R * (s1 * si)
    
    [Ie, Oe, Pe, ae, ee, Le] = Element(d, 3)
    m2 = range2pi(Le - Pe)
    V2 = kepler(m2, ee, 8)
    R2 = ae * (1 - ee * ee) / (1 + ee * math.cos(V2))
    s12 = math.sin(V2 + Pe - Oe)
    si2 = math.sin(Ie)
    so2 = math.sin(Oe)
    C12 = math.cos(V2 + Pe - Oe)
    CI2 = math.cos(Ie)
    co2 = math.cos(Oe)
    xe = R2 * (co2 * C12 - so2 * s12 * CI2)
    ye = R2 * (so2 * C12 + co2 * s12 * CI2)
    ze = R2 * (s12 * si2)
    x := x - xe
    y := y - ye
    ecl = math.toradians(23.429292)
    xe := x
    ye := y * math.cos(ecl) - z * math.sin(ecl)
    ze := y * math.sin(ecl) + z * math.cos(ecl)
    switch Index
        3 => planet = math.todegrees(atan2(ye, xe)) < 0 ? math.todegrees(atan2(ye, xe)) + 360: math.todegrees(atan2(ye, xe))
        2 => planet = math.todegrees(math.atan(ze / math.sqrt(xe * xe + ye * ye)))
        1 => planet = math.sqrt(xe * xe + ye * ye + ze * ze)

export altaz(float d, float DEC, float RA, float GLat, float GLong, float Index) =>
    h = gst(d) + GLong - RA
    sa = DegSin(DEC) * DegSin(GLat)
    sa := sa + DegCos(DEC) * DegCos(GLat) * DegCos(h)
    a = DegArcsin(sa)
    cz = DegSin(DEC) - DegSin(GLat) * sa
    cz := cz / (DegCos(GLat) * DegCos(a))
    switch Index
        1 => altaz = a
        2 =>
            if DegSin(h) < 0
                altaz = DegArccos(cz)
            else
                altaz = 360 - DegArccos(cz)

export prise(float d, int P, float GLat, float GLong, float Index) =>
    count = 0
    flag = 2 - Index
    ut0 = 0.0
    ut1 = 180.0
    slt = DegSin(GLat)
    clt = DegCos(GLat)
    while math.abs(ut0 - ut1) > 0.1 and count < 10
        count := count + 1
        ut0 := ut1
        DEC = planet(d + ut0 / 360, P, 2)
        RA = planet(d + ut0 / 360, P, 3)
        tau = (-0.009890037858741 - slt * DegSin(DEC)) / (clt * DegCos(DEC))
        switch tau
            tau >= 1 => tau := 180
            tau <= -1 => tau := -180
            => tau := DegArccos(tau)
        lst = gst(d + ut0 / 360) + GLong
        ut1 := range360(ut0 - 0.9972696 * (lst - RA + flag * tau))
    prise = ut1

export MoonSize(float d) =>
    EarthMoonDist = moon(d, 1)
    MoonSize = DegArctan(3476.28 / (EarthMoonDist * 6371)) * 3600

export Refraction(float Temperature_C, float Atmospheric_Pressure_mBar, float Altitude_Deg) =>
    P = Atmospheric_Pressure_mBar
    a = Altitude_Deg
    T = Temperature_C
    if a >= 15
        Refraction = (0.00452 * P) / ((273 + T) * DegTan(a))
    else
        Refraction = (P * (0.1594 + 0.0196 * a + 0.00002 * a * a)) / ((273 + T) * (1 + 0.505 * a + 0.0845 * a * a))

export MoonRise(float d, float Longitude, float Latitude, float Index) =>
    dr = int(d) + 0.5
    
    RA = tmoon(dr, Latitude, Longitude, 3)
    DEC = tmoon(dr, Latitude, Longitude, 2)
    
    Time0 = (riset(dr, DEC, RA, Latitude, Longitude, Index)) / 360
    Time0 := Time0 + dr
    
    RA := tmoon(Time0, Latitude, Longitude, 3)
    DEC := tmoon(Time0, Latitude, Longitude, 2)
    
    Time1 = (riset(dr, DEC, RA, Latitude, Longitude, Index)) / 360
    Time1 := Time1 + dr
    
    RA := tmoon(Time1 - (1.0 / 24), Latitude, Longitude, 3)
    DEC := tmoon(Time1 - (1.0 / 24), Latitude, Longitude, 2)
    Alt_old = altaz(Time1 - 1.0 / 24, DEC, RA, Latitude, Longitude, 1)
    moonRadius = MoonSize(Time1) / 3600
    moonRadius := moonRadius / 2
    MoonRefraction = Refraction(0, 1013.25, 0)
    Alt_old := math.abs(Alt_old + moonRadius + MoonRefraction)
    fraction = (1.0 / 24 / 60)
    
    for i = -59 to 60
        RA := tmoon(Time1 + fraction * i, Latitude, Longitude, 3)
        DEC := tmoon(Time1 + fraction * i, Latitude, Longitude, 2)
        
        Alt = altaz(Time1 + fraction * i, DEC, RA, Latitude, Longitude, 1)
        Alt := math.abs(Alt + moonRadius + MoonRefraction)
        if Index == 2
            if Alt < Alt_old
                Alt := Alt_old
                Time1 := Time1 + ((i - 1) / 24 / 60)
                break
            Alt_old := Alt
        else
            if Alt > Alt_old
                Alt := Alt_old
                Time1 := Time1 + ((i - 1) / 24 / 60)
                break
            Alt_old := Alt
        continue
    
    MoonRise = Time1 - dr
    if Time1 - dr < 0
        MoonRise := Time1 - dr + 1
    else
        MoonRise := Time1 - dr

export f_to_sec(float dec) => 
    sec = (dec * 24 * 60 * 60)

export f_to_time(float sec) =>
    hh = math.floor(sec / 3600) % 24
    mm = math.floor(sec / 60 % 60)
    ss = math.floor(sec % 60)
    totime = str.tostring(hh) + ":" + str.tostring(mm) + ":" + str.tostring(ss)

export deg_to_time(float deg) =>
    hh = int(deg)
    mm = int((deg - int(deg)) * 60)
    ss = int((((deg-hh)*60)-mm)*60)
    totime = str.tostring(hh) + ":" + str.tostring(mm) + ":" + str.tostring(ss)

export toDMS(float coordinate) =>
    absolute = math.abs(coordinate)
    degrees = math.floor(absolute)
    minutesNotTruncated = (absolute - degrees) * 60
    minutes = math.floor(minutesNotTruncated)
    seconds = math.floor((minutesNotTruncated - minutes) * 60)

    str.tostring(degrees) + "° " + str.tostring(minutes) + "' " + str.tostring(seconds)

export convertDMS(float lat, float lng) =>
    lati = toDMS(lat)
    latitudeCardinal = lat >= 0 ? "N" : "S"

    longi = toDMS(lng)
    longitudeCardinal = lng >= 0 ? "E" : "W"

    str.tostring(lati) + " " + str.tostring(latitudeCardinal) + "\n" + str.tostring(longi) + " " + str.tostring(longitudeCardinal)

export convlatdec(float deg) =>
    cCardinal = deg >= 0 ? "N" : "S"
    absolute = math.abs(deg)
    degrees = math.floor(absolute)
    minutesNotTruncated = (absolute - degrees) * 60
    minutes = math.floor(minutesNotTruncated)
    str.tostring(degrees) + "° " + cCardinal + " " + str.tostring(minutes) + "'"

// // @function PlanetName: Input planet number and output the name
export PlanetName(int pnum) =>
    switch pnum
        1 => " Mercury "
        2 => " Venus "
        3 => " Moon "
        4 => " Mars "
        5 => " Jupiter "
        6 => " Saturn "
        7 => " Uranus "
        8 => " Neptune "
        9 => " Pluto "
        10 => " Sun "
        11 => " Earth "
        12 => " Juno "
        13 => " Vesta "
        14 => " Ceres "
        15 => " True Lilith "
        16 => " Mean Lilith "
        17 => " North Node "
        18 => " South Node "

// // @function PlanetNameVedic: Input planet number and output the Vedic name
export PlanetNameV(int pnum) =>
    switch pnum
        1 => " Bhudha "
        2 => " Shukra "
        3 => " Chandra Sandu "
        4 => " Mangal "
        5 => " Guru "
        6 => " Shani "
        7 => " Uranus "
        8 => " Neptune "
        9 => " Pluto "

// // @function PlanetName: Input planet number and output the name
export PlanetSign(int pnum) =>
    switch pnum
        1 => " ☿ "
        2 => " ♀ "
        3 => " ☽︎ "
        4 => " ♂ "
        5 => " ♃ "
        6 => " ♄ "
        7 => " ⛢ "
        8 => " ♆ "
        9 => " ♇ "
        10 => " ☉︎ "
        11 => " 🜨 "
        12 => " ⚵ "
        13 => " ⚶ "
        14 => " ⚳ "
        15 => " ⚸ "
        16 => " ⚸ "
        17 => " ☊ "
        18 => " ☋ "

// // @function PlanetColor: Input planet number and output the color
export PlanetColor(int pnum) =>
    switch pnum
        1 => color.maroon
        2 => color.green
        3 => color.silver
        4 => color.red
        5 => color.orange
        6 => color.gray
        7 => color.blue
        8 => color.fuchsia
        9 => color.black
        10 => color.yellow
        11 => color.gray
        12 => #856c44
        13 => #856c44
        14 => color.gray
        15 => color.black
        16 => color.black
        17 => color.white
        18 => color.black

// // @function DegreeToZodiacColor: Input degrees and output the Zodiac color
export zodiaccolor(float deg) => deg > 0 and deg < 30 ? color.red : 
  deg >= 30 and deg < 60 ? color.orange : 
  deg >= 60 and deg < 90 ? color.yellow :
  deg >= 90 and deg < 120 ? color.green :
  deg >= 120 and deg < 150 ? color.blue :
  deg >= 150 and deg < 180 ? color.navy :
  deg >= 180 and deg < 210 ? color.purple : 
  deg >= 210 and deg < 240 ? color.navy : 
  deg >= 240 and deg < 270 ? color.blue : 
  deg >= 270 and deg < 300 ? color.green : 
  deg >= 300 and deg < 330 ? color.yellow : 
  deg >= 330 and deg < 360 ? color.orange :  color.gray

// // @function DegreeToSign: Input degrees and output the Zodiac symbol
export degsign(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        0 => str.tostring(int(deg % 30)) + " ♈︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        1 => str.tostring(int(deg % 30)) + " ♉︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        2 => str.tostring(int(deg % 30)) + " ♊︎	" + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        3 => str.tostring(int(deg % 30)) + " ♋︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        4 => str.tostring(int(deg % 30)) + " ♌︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        5 => str.tostring(int(deg % 30)) + " ♍︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        6 => str.tostring(int(deg % 30)) + " ♎︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        7 => str.tostring(int(deg % 30)) + " ♏︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        8 => str.tostring(int(deg % 30)) + " ♐︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        9 => str.tostring(int(deg % 30)) + " ♑︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        10 => str.tostring(int(deg % 30)) + " ♒︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        11 => str.tostring(int(deg % 30)) + " ♓︎ " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))

// // @function DegreeToSignFull: Input degrees and output the full Zodiac symbol
export degsignf(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        0 => str.tostring(int(deg % 30)) + " ♈︎ Aries " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        1 => str.tostring(int(deg % 30)) + " ♉︎ Taurus " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        2 => str.tostring(int(deg % 30)) + " ♊︎	Gemini " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        3 => str.tostring(int(deg % 30)) + " ♋︎ Cancer " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        4 => str.tostring(int(deg % 30)) + " ♌︎ Leo " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        5 => str.tostring(int(deg % 30)) + " ♍︎ Virgo " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        6 => str.tostring(int(deg % 30)) + " ♎︎ Libra "  + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        7 => str.tostring(int(deg % 30)) + " ♏︎ Scorpio " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        8 => str.tostring(int(deg % 30)) + " ♐︎ Saggitarius " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        9 => str.tostring(int(deg % 30)) + " ♑︎ Capricorn " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        10 => str.tostring(int(deg % 30)) + " ♒︎ Aquarius " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        11 => str.tostring(int(deg % 30)) + " ♓︎ Pisces " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))

// // @function DegreeToNakshatra: Input degrees and output the Vedic Nakshatra
export degnash(float deg) =>
    sign = math.floor(deg / 13.20)
    switch sign
        0 => "Ashwini"
        1 => "Bharani"
        2 => "Krittika"
        3 => "Rohini"
        4 => "Mrigashirsha"
        5 => "Ardra"
        6 => "Punarvasu"
        7 => "Pushya"
        8 => "Ashlesha"
        9 => "Magha"
        10 => "Purva Phalguni"
        11 => "Uttara Phalguni"
        12 => "Hasta"
        13 => "Chitra"
        14 => "Swati"
        15 => "Vishakha"
        16 => "Anuradha"
        17 => "Jyeshta"
        18 => "Mula"
        19 => "Purva Ashadha"
        20 => "Uttara Ashadha"
        21 => "Shravana"
        22 => "Dhanistha"
        23 => "Shatabhisha"
        24 => "Purva Bhadrapada"
        25 => "Uttara Bhadrapada"
        26 => "Revathi"

// // @function DegreeToSignName: Input degrees and output the Zodiac name
export degname(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        0 => str.tostring(int(deg % 30)) + " Aries " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        1 => str.tostring(int(deg % 30)) + " Taurus " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        2 => str.tostring(int(deg % 30)) + " Gemini	" + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        3 => str.tostring(int(deg % 30)) + " Cancer " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        4 => str.tostring(int(deg % 30)) + " Leo " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        5 => str.tostring(int(deg % 30)) + " Virgo " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        6 => str.tostring(int(deg % 30)) + " Libra " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        7 => str.tostring(int(deg % 30)) + " Scorpio " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        8 => str.tostring(int(deg % 30)) + " Sagittarius " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        9 => str.tostring(int(deg % 30)) + " Capricorn " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        10 => str.tostring(int(deg % 30)) + " Aquarius " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))
        11 => str.tostring(int(deg % 30)) + " Pisces " + str.tostring(math.round(((deg % 30) - int(deg % 30)) * 60, 2))

// // @function RetrogradeSymbol: Input the variable for a planet's longitude and if the planet is in retrograde display a ℞ symbol
export retrogradesym(float deg) => deg > deg[1] ? "" : " ℞ "

// // @function DegreeToAspect: Input degrees and output the (English) Planetary Aspect sign
export degaspsign(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        0 => " ☌ "
        1 => " ⊻ "
        2 => " 🞶 "
        3 => " □ " 
        4 => " △ " 
        5 => " ⊼ " 
        6 => " ☍ " 
        7 => " ⊼ " 
        8 => " △ " 
        9 => " □ " 
        10 => " 🞶 " 
        11 => " ⊻ " 

// // @function DegreeToAspectName: Input degrees and output the (English) Planetary Aspect name
export degaspname(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        0 => " Conjunction "
        1 => " Semi Sextile " 
        2 => " Sextile	"
        3 => " Square " 
        4 => " Trine " 
        5 => " Inconjunct " 
        6 => " Opposition "
        7 => " Inconjunct " 
        8 => " Trine " 
        9 => " Square " 
        10 => " Sextile " 
        11 => " Semi Sextile " 

// // @function DegreeToAspect: Input degrees and output the (English) Planetary Aspect sign, name, and angle
export degaspfull(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        0 => " ☌ Conjunction 0° "
        1 => " ⊻ Semi Sextile 30° "
        2 => " 🞶 Sextile 60° "
        3 => " □ Square 90° " 
        4 => " △ Trine 120° " 
        5 => " ⊼ Inconjunct 150° " 
        6 => " ☍ Opposition 180° " 
        7 => " ⊼ Inconjunct 210° " 
        8 => " △ Trine 240° " 
        9 => " □ Square 270° " 
        10 => " 🞶 Sextile 300° " 
        11 => " ⊻ Semi Sextile 330° " 

// // @function DegreeToAspect: Version 2: Input degrees and output the (English) Planetary Aspect sign, name, and angle
export degaspfullV2(float deg) =>
    sign = math.round(deg / 30)
    switch sign
        0 => " ☌ Conjunction 0° "
        1 => " ⊻ Semi Sextile 30° "
        2 => " 🞶 Sextile 60° "
        3 => " □ Square 90° " 
        4 => " △ Trine 120° " 
        5 => " ⊼ Inconjunct 150° " 
        6 => " ☍ Opposition 180° " 
        7 => " ⊼ Inconjunct 210° " 
        8 => " △ Trine 240° " 
        9 => " □ Square 270° " 
        10 => " 🞶 Sextile 300° " 
        11 => " ⊻ Semi Sextile 330° " 

// // @function DegreeToAspectName: Input degrees and output the (English) Planetary Aspect name
export degaspnameV2(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        0 => " Conjunction "
        1 => " Semi Sextile " 
        2 => " Sextile	"
        3 => " Square " 
        4 => " Trine " 
        5 => " Inconjunct " 
        6 => " Opposition "
        7 => " Inconjunct " 
        8 => " Trine " 
        9 => " Square " 
        10 => " Sextile " 
        11 => " Semi Sextile " 

export degtolowest180(float deg) =>
    degout = deg>180 ? 360-deg : deg
    degout2 = degout>180 ? 360-degout : degout

// // @function DegreeToApproachingAspect: Input degrees and output the (English) approaching Planetary Aspect sign, name, and angle
export degaspfullapproach(float deg) =>
    sign = math.floor(deg / 30)
    switch sign
        11 => " ☌ Conjunction 0° "
        0 => " ⊻ Semi Sextile 30° "
        1 => " 🞶 Sextile 60° "
        2 => " □ Square 90° " 
        3 => " △ Trine 120° " 
        4 => " ⊼ Inconjunct 150° " 
        5 => " ☍ Opposition 180° " 
        6 => " ⊼ Inconjunct 210° " 
        7 => " △ Trine 240° " 
        8 => " □ Square 270° " 
        9 => " 🞶 Sextile 300° " 
        10 => " ⊻ Semi Sextile 330° " 

// // @function AspectColors: Input an angle and output the corresponding bullish or bearish aspect color. 
export virinchiaspectcol(float deg, color bull_col, color bear_col) => 
    deg_out = math.round(deg)
    deg_out == 0 ? bull_col: 
      deg_out == 6 ? bull_col :
      deg_out == 9 ? bull_col :
      deg_out == 12 ? bull_col :
      deg_out == 15 ? bear_col :
      deg_out == 18 ? bull_col : 
      deg_out == 20 ? bear_col :
      //deg_out == 22.5 ? bear_col :
      deg_out == 24 ? bull_col : 
      deg_out == 30 ? bull_col :
      deg_out == 36 ? bull_col :
      deg_out == 40 ? bull_col :
      deg_out == 45 ? bull_col :
      deg_out == 60 ? bull_col :
      deg_out == 72 ? bull_col :
      deg_out == 90 ? bear_col :
      deg_out == 120 ? bear_col :
      deg_out == 135 ? bull_col :
      deg_out == 144 ? bear_col :
      deg_out == 150 ? bull_col :
      deg_out == 180 ? bear_col : na

// // @function AspectEmojis: Input an angle and output the corresponding bullish or bearish aspect emoji. 
export virinchiaspectemo(float deg, string bull_emo, string bear_emo) => 
    deg_out = math.round(deg)
    deg_out == 0 ? bull_emo: 
      deg_out == 6 ? bull_emo :
      deg_out == 9 ? bull_emo :
      deg_out == 12 ? bull_emo :
      deg_out == 15 ? bear_emo :
      deg_out == 18 ? bull_emo : 
      deg_out == 20 ? bear_emo :
      //deg_out == 22.5 ? bear_emo :
      deg_out == 24 ? bull_emo : 
      deg_out == 30 ? bull_emo :
      deg_out == 36 ? bull_emo :
      deg_out == 40 ? bull_emo :
      deg_out == 45 ? bull_emo :
      deg_out == 60 ? bull_emo :
      deg_out == 72 ? bull_emo :
      deg_out == 90 ? bear_emo :
      deg_out == 120 ? bear_emo :
      deg_out == 135 ? bull_emo :
      deg_out == 144 ? bear_emo :
      deg_out == 150 ? bull_emo :
      deg_out == 180 ? bear_emo : na

// // @function FastAspectSign&Degree: Input an angle and output the corresponding aspect sign & degree for fast planets (within 3 degrees). 
export aspectfastsigndeg(float deg) => 
    deg > 0 and deg < 3 ? " ☌ 0° " : 
      deg > 27 and deg < 33 ? " ⊻ 30° " : 
      deg > 57 and deg < 63 ? " 🞶 60° " : 
      deg > 87 and deg < 93 ? " □ 90° " : 
      deg > 117 and deg < 123 ? " △ 120° " : 
      deg > 147 and deg < 153 ? " ⊼ 150° " : 
      deg > 177 and deg < 180 ? " ☍ 180° " : str.tostring(deg,"#")

// // @function FastAspectFull: Input an angle and output the corresponding aspect details for fast planets (within 3 degrees). 
export aspectfastfull(float deg) => 
    deg > 0 and deg < 3 ? " ☌ Conjunction 0° " : 
      deg > 27 and deg < 33 ? " ⊻ Semi Sextile 30° " : 
      deg > 57 and deg < 63 ? " 🞶 Sextile	60° " : 
      deg > 87 and deg < 93 ? " □ Square 90° " : 
      deg > 117 and deg < 123 ? " △ Trine 120° " : 
      deg > 147 and deg < 153 ? " ⊼ Inconjunct 150° " : 
      deg > 177 and deg < 180 ? " ☍ Oppostiion 180° " : str.tostring(deg,"#")

// // @function SlowAspectFull: Input an angle and output the corresponding aspect details for slow planets (within 6 degrees). 
export aspectslowfull(float deg) => 
    deg > 0 and deg < 6 ? " ☌ Conjunction 0° " : 
      deg > 24 and deg < 36 ? " ⊻ Semi Sextile 30° " : 
      deg > 54 and deg < 66 ? " 🞶 Sextile	60° " : 
      deg > 84 and deg < 96 ? " □ Square 90° " : 
      deg > 114 and deg < 126 ? " △ Trine 120° " : 
      deg > 144 and deg < 156 ? " ⊼ Inconjunct 150° " : 
      deg > 174 and deg < 180 ? " ☍ Oppostiion 180° " : str.tostring(deg,"#")

// // @function SlowAspectSign&Degree: Input an angle and output the corresponding aspect sign & degree for slow planets (within 6 degrees). 
export aspectslowsigndeg(float deg) => 
    deg > 0 and deg < 6 ? " ☌ 0° " : 
      deg > 24 and deg < 36 ? " ⊻ 30° " : 
      deg > 54 and deg < 66 ? " 🞶 60° " : 
      deg > 84 and deg < 96 ? " □ 90° " : 
      deg > 114 and deg < 126 ? " △ 120° " : 
      deg > 144 and deg < 156 ? " ⊼ 150° " : 
      deg > 174 and deg < 180 ? " ☍ 180° " : str.tostring(deg,"#")

// // @function SlowAspectSign: Input an angle and output the corresponding aspect sign for slow planets (within 6 degrees). 
export aspectslowsign(float deg) => 
    deg > 0 and deg < 6 ? " ☌ " + str.tostring(deg,"#") : 
      deg > 24 and deg < 36 ? " ⊻ " + str.tostring(deg,"#") : 
      deg > 54 and deg < 66 ? " 🞶 " + str.tostring(deg,"#") : 
      deg > 84 and deg < 96 ? " □ " + str.tostring(deg,"#") : 
      deg > 114 and deg < 126 ? " △ " + str.tostring(deg,"#") : 
      deg > 144 and deg < 156 ? " ⊼ " + str.tostring(deg,"#") : 
      deg > 174 and deg < 180 ? " ☍ " + str.tostring(deg,"#") : str.tostring(deg,"#")

// // @function PrecisionAspectSign: Input an angle & precision, then output the corresponding aspect sign for the planets. Precision 1 = +/-6°. Precision 2 = +/-3°. Precision 3 = Rounded to the nearest 1°.
export aspectsignprecision(float deg, int precision) => 
    if precision == 1
        deg > 0 and deg < 6 ? " ☌ " + str.tostring(deg,"#") : 
          deg > 24 and deg < 36 ? " ⊻ " + str.tostring(deg,"#") : 
          deg > 54 and deg < 66 ? " 🞶 " + str.tostring(deg,"#") : 
          deg > 84 and deg < 96 ? " □ " + str.tostring(deg,"#") : 
          deg > 114 and deg < 126 ? " △ " + str.tostring(deg,"#") : 
          deg > 144 and deg < 156 ? " ⊼ " + str.tostring(deg,"#") : 
          deg > 174 and deg < 180 ? " ☍ " + str.tostring(deg,"#") : str.tostring(deg,"#")
    if precision == 2
        deg > 0 and deg < 3 ? " ☌ " + str.tostring(deg,"#") : 
          deg > 27 and deg < 33 ? " ⊻ " + str.tostring(deg,"#") : 
          deg > 57 and deg < 63 ? " 🞶 " + str.tostring(deg,"#") : 
          deg > 87 and deg < 93 ? " □ " + str.tostring(deg,"#") : 
          deg > 117 and deg < 123 ? " △ " + str.tostring(deg,"#") : 
          deg > 147 and deg < 153 ? " ⊼ " + str.tostring(deg,"#") : 
          deg > 177 and deg < 183 ? " ☍ " + str.tostring(deg,"#") : str.tostring(deg,"#")
    else
        math.round(deg) == 0 ? " ☌ " + str.tostring(deg,"#") : 
          math.round(deg) == 30 ? " ⊻ " + str.tostring(deg,"#") : 
          math.round(deg) == 60 ? " 🞶 " + str.tostring(deg,"#") : 
          math.round(deg) == 90 ? " □ " + str.tostring(deg,"#") : 
          math.round(deg) == 120 ? " △ " + str.tostring(deg,"#") : 
          math.round(deg) == 150 ? " ⊼ " + str.tostring(deg,"#") : 
          math.round(deg) == 180 ? " ☍ " + str.tostring(deg,"#") : str.tostring(deg,"#")

// // @function PrecisionAspectSignV2: Input an angle & precision (both in degrees°), then output the corresponding aspect sign & angle for the planets. 
export aspectsignprecisionV2(float deg, float precision) => 
    deg > 0 and deg < (0+precision) ? " ☌ " + str.tostring(deg,"#") : 
      deg > (30-precision) and deg < (30+precision) ? " ⊻ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (60-precision) and deg < (60+precision) ? " 🞶 " + str.tostring(degtolowest180(deg),"#") : 
      deg > (90-precision) and deg < (90+precision) ? " □ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (120-precision) and deg < (120+precision) ? " △ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (150-precision) and deg < (150+precision) ? " ⊼ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (180-precision) and deg < 180 ? " ☍ " + str.tostring(degtolowest180(deg),"#") : str.tostring(degtolowest180(deg),"#")

// // @function PrecisionAspectSignV2Extended: Input an angle & precision (both in degrees°), then output the corresponding aspect sign & angle for the planets. Great for tooltips.
export aspectsignprecisionV2ext(float deg, float precision) => 
    deg > 0 and deg < (0+precision) ? "☌ Conjunction " + str.tostring(deg,"#.#") : 
      deg > (30-precision) and deg < (30+precision) ? "⊻ SemiSextile " + str.tostring(degtolowest180(deg),"#.#") : 
      deg > (60-precision) and deg < (60+precision) ? "🞶 Sextile " + str.tostring(degtolowest180(deg),"#.#") : 
      deg > (90-precision) and deg < (90+precision) ? "□ Square " + str.tostring(degtolowest180(deg),"#.#") : 
      deg > (120-precision) and deg < (120+precision) ? "△ Trine " + str.tostring(degtolowest180(deg),"#.#") : 
      deg > (150-precision) and deg < (150+precision) ? "⊼ Inconjunct " + str.tostring(degtolowest180(deg),"#.#") : 
      deg > (180-precision) and deg < 180 ? "☍ Opposition " + str.tostring(degtolowest180(deg),"#.#") : "No aspect " + str.tostring(degtolowest180(deg),"#.#")

// // @function PrecisionAspectSignV2: Input an angle & precision (both in degrees°), then output the corresponding aspect sign & angle for the planets. 
export IPaspectsignprecision(float planet1, float planet2, float precision) => 
    deg = planet1 - planet2
    deg > 0 and deg < (0+precision) ? " ☌ " + str.tostring(deg,"#") : 
      deg > (30-precision) and deg < (30+precision) ? " ⊻ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (60-precision) and deg < (60+precision) ? " 🞶 " + str.tostring(degtolowest180(deg),"#") : 
      deg > (90-precision) and deg < (90+precision) ? " □ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (120-precision) and deg < (120+precision) ? " △ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (150-precision) and deg < (150+precision) ? " ⊼ " + str.tostring(degtolowest180(deg),"#") : 
      deg > (180-precision) and deg < 180 ? " ☍ " + str.tostring(degtolowest180(deg),"#") : str.tostring(degtolowest180(deg),"#")

// // @function PrecisionAspectSignV2: Input an angle & precision (both in degrees°), then output the corresponding aspect sign & angle for the planets. 
export IPaspectsignprecisionFull(float planet1, float planet2, float precision) => 
    deg = planet1 - planet2
    deg > 0 and deg < (0+precision) ? " ☌ Conjunction " + str.tostring(deg,"#") : 
      deg > (30-precision) and deg < (30+precision) ? " ⊻ SemiSextile " + str.tostring(degtolowest180(deg),"#") : 
      deg > (60-precision) and deg < (60+precision) ? " 🞶 Sextile " + str.tostring(degtolowest180(deg),"#") : 
      deg > (90-precision) and deg < (90+precision) ? " □ Square " + str.tostring(degtolowest180(deg),"#") : 
      deg > (120-precision) and deg < (120+precision) ? " △ Trine " + str.tostring(degtolowest180(deg),"#") : 
      deg > (150-precision) and deg < (150+precision) ? " ⊼ Inconjunct " + str.tostring(degtolowest180(deg),"#") : 
      deg > (180-precision) and deg < 180 ? " ☍ Opposition " + str.tostring(degtolowest180(deg),"#") : str.tostring(degtolowest180(deg),"#")

// // @function PrecisionAspectSignV2: Input an angle & precision (both in degrees°), then output the corresponding colored vertical aspect line on the chart. 
export IPaspectlineprecision(float planet1, float planet2, float precision, string style, int width) => 
    deg = planet1 - planet2
    deg > 0 and deg < (0+precision) ? line.new(bar_index, open, bar_index, close, extend=extend.both, color=color.red, style=style, width=width) : 
      deg > (30-precision) and deg < (30+precision) ? line.new(bar_index, open, bar_index, close, extend=extend.both, color=color.orange, style=style, width=width) : 
      deg > (60-precision) and deg < (60+precision) ? line.new(bar_index, open, bar_index, close, extend=extend.both, color=color.yellow, style=style, width=width) : 
      deg > (90-precision) and deg < (90+precision) ? line.new(bar_index, open, bar_index, close, extend=extend.both, color=color.green, style=style, width=width) : 
      deg > (120-precision) and deg < (120+precision) ? line.new(bar_index, open, bar_index, close, extend=extend.both, color=color.aqua, style=style, width=width) : 
      deg > (150-precision) and deg < (150+precision) ? line.new(bar_index, open, bar_index, close, extend=extend.both, color=color.navy, style=style, width=width) : 
      deg > (180-precision) and deg < 180 ? line.new(bar_index, open, bar_index, close, extend=extend.both, color=color.purple, style=style, width=width) : na

export rDeg(float deg) => 
    h = math.abs(deg / 15)
    m = int((h - int(h)) * 60)
    rDeg = (((int(h) * 60) + m) / 1440) * 360

// Reference Angle Function
// Author: Nasser Humood  
// // @function AngleToCircle: Input an angle (even one >360) and convert it to degrees on a circle (between 0 to 360).
export AngToCirc(float angle) =>
    // if the angle is greater than or equal to 360
    if angle >= 360
        firstStep = math.floor(angle / 360) * 360
        returnedSolution = angle - firstStep
        returnedSolution
    // if the angle is less than or equal to zero
    else if angle <= 0
        firstStep = math.ceil(-angle / 360) * 360
        returnedSolution = angle + firstStep
        returnedSolution
    else
    // when the angle is correct and doesn't need any modification ex. in between 0-360 
        returnedSolution = angle
        returnedSolution

// Reference Angle Function
// Author: Nasser Humood  
// Editor: BarefootJoey
// // @function AngleToCircle180: Input an angle (even one >180) and convert it to degrees on a semi-circle (between 0 to 180).
export AngToCirc180(float angle) =>
    // if the angle is greater than or equal to 360
    if angle >= 180
        firstStep = math.floor(angle / 180) * 180
        returnedSolution = angle - firstStep
        returnedSolution
    // if the angle is less than or equal to zero
    else if angle <= 0
        firstStep = math.ceil(-angle / 180) * 180
        returnedSolution = angle + firstStep
        returnedSolution
    else
    // when the angle is correct and doesn't need any modification ex. in between 0-360 
        returnedSolution = angle
        returnedSolution

// // @function TropicalToSidereal: Input an angle (even one > or < than 360) and convert it to sidereal.
export sidereal(float deg, bool sidereal) => 
    if sidereal
        sr_in = deg - 23.42
        sr_out = AngToCirc(sr_in)
    else
        sr_out = deg
    
export J2000(float JDN) => JDN - 2451545.0 //J2000
export JDN(float t, float d, float tz) => d == 0 ? (t / 86400000) + 2440587.5 + (tz / 24) : int((t / 86400000) + 2440587.5 + (tz / 24) - 1) + 0.5

export getsun(int index, float day, float dayr, float latitude, float longitude, float tz) =>
    xsun = rsun(day,1)
    ysun = rsun(day,2)
    zsun = rsun(day,3)
    srise = Sunrise(dayr, latitude, longitude, 1, 0)/360*24 + tz
    sset = Sunrise(dayr, latitude, longitude, 0, 0)/360*24 + tz
    switch index
        0 => spherical(xsun, ysun, zsun, 3)
        1 => spherical(xsun, ysun, zsun, 3)
        2 => math.round(spherical(xsun, ysun, zsun, 2), 2)
        3 => math.round(sun(day, 2), 2)
        4 => math.round(altaz(day,sun(day, 2),sun(day, 3), 0, 0, 1), 2)
        5 => math.round(sun(day, 3), 2) / 15
        6 => srise % 24
        7 => sset % 24

export getmoon(int index, float day, float dayr, float latitude, float longitude) =>
    xmoon = rmoon(day,1)
    ymoon = rmoon(day,2)
    zmoon = rmoon(day,3)
    mrise = MoonRise(dayr, longitude, latitude, 1)
    mset = MoonRise(dayr, longitude, latitude, 3)
    switch index
        0 => spherical(xmoon, ymoon, zmoon, 3)
        1 => spherical(xmoon, ymoon, zmoon, 3)
        2 => math.round(spherical(xmoon, ymoon, zmoon, 2), 2)
        3 => math.round(moon(day, 2), 2)
        4 => math.round(altaz(day, moon(day, 2), moon(day, 3), 0, 0, 1), 2)
        5 => math.round(moon(day, 3), 2) / 15
        6 => mrise * 24
        7 => mset * 24

export getplanet(int planet, int index, float day, float dayr, float latitude, float longitude, float tz) =>
    xsun = rsun(day,1)
    ysun = rsun(day,2)
    zsun = rsun(day,3)
    xplanet = xsun + rplanet(day, planet, 1)
    yplanet = ysun + rplanet(day, planet, 2)
    zplanet = zsun + rplanet(day, planet, 3)
    srise = prise(dayr, planet, latitude, longitude, 1)/360*24 + tz
    sset = prise(dayr, planet, latitude, longitude, 0)/360*24 + tz
    switch index
        0 => spherical(xplanet, yplanet, zplanet, 3)
        1 => spherical(rplanet(day, planet, 1), rplanet(day, planet, 2), rplanet(day, planet, 3), 3)
        2 => math.round(spherical(xplanet, yplanet, zplanet, 2), 2)
        3 => math.round(planet(day, planet, 2), 2)
        4 => math.round(altaz(day,planet(day, planet, 2), planet(day, planet, 3), 0, 0, 1), 2)
        5 => math.round(planet(day, planet, 3), 2) / 15
        6 => srise % 24
        7 => sset % 24

// EoS made w/ ❤ by @BarefootJoey ✌💗📈