Astro: Planetary Aspects
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © BarefootJoey

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

//@version=5
indicator("Astro: Planetary Aspects", overlay=false)

import BarefootJoey/AstroLib/1 as AL

interplanet = input.bool(false, "Interplanetary aspects?", tooltip="Leave this box unchecked for single planet aspects.")
planet1_in = input.string("☿ Mercury", "Which planets?", options=["☉︎ Sun", "☽︎ Moon", "☿ Mercury", "♀ Venus", "🜨 Earth", "♂ Mars", "♃ Jupiter", "♄ Saturn", "⛢ Uranus", "♆ Neptune", "♇ Pluto"], inline="3")
planet2_in = input.string("♂ Mars", " ", options=["☉︎ Sun", "☽︎ Moon", "☿ Mercury", "♀ Venus", "🜨 Earth", "♂ Mars", "♃ Jupiter", "♄ Saturn", "⛢ Uranus", "♆ Neptune", "♇ Pluto"], inline="3")
precision = input.float(6.0, "Aspect Precision (+/- °)", minval=0, maxval=15)
showlast = input.int(1000, "Show last?", minval=1, tooltip="Number of historical plots to display. The fewer plots, the faster the load time (especially on loweer timeframes). Use the Time Machine feature for distant historical analysis.")
col_asp = input.color(color.white, "Aspect & Info Color")
iTxtSize=input.string("Normal", title="Text Size", options=["Auto", "Tiny", "Small", "Normal", "Large"], inline="1")
vTxtSize=iTxtSize == "Auto" ? size.auto : iTxtSize == "Tiny" ? size.tiny : iTxtSize == "Small" ? size.small : iTxtSize == "Normal" ? size.normal : iTxtSize == "Large" ? size.large : size.small
position = input.string(position.top_center, "Aspect Info Position", [position.top_center, position.top_right, position.middle_right, position.bottom_right, position.bottom_center, position.bottom_left, position.middle_left, position.top_left])

grtm = "🕜 Time Machine 🕜"
gsd = input.bool(false, "Activate Time Machine", group=grtm)
sdms = input.time(timestamp("2022-04-20T00:00:00"), "Select Date", group=grtm)
gt = gsd ? sdms : time

grol = "🔭 Observer Location 🔭"
htz = input.float(0, "Hour", step=0.5, inline="2", group=grol)
mtz = input.int(0, "Minute", minval=0, maxval=45, inline="2", group=grol)
tz = htz + math.round(mtz / 60, 4)
latitude = input.float(0, "Latitude", inline="1", group=grol)
longitude = input.float(0, "Longitude", inline="1", group=grol)
geo = input.bool(false, "Geocentric?", tooltip="Leave this box unchecked for heliocentric.", group=grol)
geoout = geo ? 1 : 0

day = AL.J2000(AL.JDN(gt, 0, tz))
dayr = AL.J2000(AL.JDN(gt, 1, tz))

if interplanet and planet1_in == planet2_in 
    runtime.error("Planet cannot aspect itself. Please select 2 different planets for interplanetary analysis.")

long1_out = planet1_in == "☉︎ Sun" ? AL.getsun(geoout, day, dayr, latitude, longitude, tz) : planet1_in == "☽︎ Moon" ? AL.getmoon(geoout, day, dayr, latitude, longitude) : planet1_in == "☿ Mercury" ? AL.getplanet(1, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "♀ Venus" ? AL.getplanet(2, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "🜨 Earth" ? AL.getplanet(3, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "♂ Mars" ? AL.getplanet(4, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "♃ Jupiter" ? AL.getplanet(5, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "♄ Saturn" ? AL.getplanet(6, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "⛢ Uranus" ? AL.getplanet(7, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "♆ Neptune" ? AL.getplanet(8, geoout, day, dayr, latitude, longitude, tz) : planet1_in == "♇ Pluto" ? AL.getplanet(9, geoout, day, dayr, latitude, longitude, tz) : na
long2_out = planet2_in == "☉︎ Sun" ? AL.getsun(geoout, day, dayr, latitude, longitude, tz) : planet2_in == "☽︎ Moon" ? AL.getmoon(geoout, day, dayr, latitude, longitude) : planet2_in == "☿ Mercury" ? AL.getplanet(1, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "♀ Venus" ? AL.getplanet(2, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "🜨 Earth" ? AL.getplanet(3, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "♂ Mars" ? AL.getplanet(4, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "♃ Jupiter" ? AL.getplanet(5, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "♄ Saturn" ? AL.getplanet(6, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "⛢ Uranus" ? AL.getplanet(7, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "♆ Neptune" ? AL.getplanet(8, geoout, day, dayr, latitude, longitude, tz) : planet2_in == "♇ Pluto" ? AL.getplanet(9, geoout, day, dayr, latitude, longitude, tz) : na

p1p2=math.abs(AL.degtolowest180(AL.AngToCirc(long1_out - (interplanet?long2_out:0)))) 
plot(p1p2, color=col_asp, linewidth=2, show_last=showlast)

htrans=66
hline(0, color=color.new(color.red, htrans))
hline(30, color=color.new(color.orange, htrans))
hline(60, color=color.new(color.yellow, htrans))
hline(90, color=color.new(color.green, htrans))
hline(120, color=color.new(color.aqua, htrans))
hline(150, color=color.new(color.navy, htrans))
hline(180, color=color.new(color.purple, htrans))

var label conj = na
var label ssex = na
var label sext = na
var label squa = na
var label trin = na
var label inco = na
var label oppo = na

if barstate.islast
    conj := label.new(bar_index, y=0, text="☌", size=vTxtSize, style=label.style_label_left, color=color.new(color.white,100), textcolor=color.new(color.red,0), tooltip="☌ Conjunction 0°\n" + "")
    label.delete(conj[1])
    ssex := label.new(bar_index, y=30, text="⊻", size=vTxtSize, style=label.style_label_left, color=color.new(color.white,100), textcolor=color.new(color.orange,0), tooltip="⊻ Semi Sextile 30°\n" + "")
    label.delete(ssex[1])
    sext := label.new(bar_index, y=60, text="🞶", size=vTxtSize, style=label.style_label_left, color=color.new(color.white,100), textcolor=color.new(color.yellow,0), tooltip="🞶 Sextile 60°\n" + "")
    label.delete(sext[1])
    squa := label.new(bar_index, y=90, text="□", size=vTxtSize, style=label.style_label_left, color=color.new(color.white,100), textcolor=color.new(color.green,0), tooltip="□ Square 90°\n" + "")
    label.delete(squa[1])
    trin := label.new(bar_index, y=120, text="△", size=vTxtSize, style=label.style_label_left, color=color.new(color.white,100), textcolor=color.new(color.aqua,0), tooltip="△ Trine 120°\n" + "")
    label.delete(trin[1])
    inco := label.new(bar_index, y=150, text="⊼", size=vTxtSize, style=label.style_label_left, color=color.new(color.white,100), textcolor=color.new(color.navy,0), tooltip="⊼ Inconjunct 150°\n" + "")
    label.delete(inco[1])
    oppo := label.new(bar_index, y=180, text="☍", size=vTxtSize, style=label.style_label_left, color=color.new(color.white,100), textcolor=color.new(color.purple,0), tooltip="☍ Opposition 180°\n" + "")
    label.delete(oppo[1])

retro_tt(deg) => deg > deg[1] ? "" : " ℞" 
retro_tt_out = retro_tt(AL.AngToCirc(long1_out - (interplanet?long2_out:0)))

var table Info = na
table.delete(Info)
Info := table.new(position, 1, 1)
if barstate.islast
    table.cell(Info, 0, 0, 
      text = planet1_in + (interplanet?" ∡ "+planet2_in:"") + retro_tt_out, 
      text_size = vTxtSize, 
      text_color = color.new(col_asp,0),
      tooltip = AL.aspectsignprecisionV2ext(p1p2, precision) + "°\nPrecision: +/- " + str.tostring(precision) + "°")

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