Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import pygame, sys, math
- # bary v3
- pygame.init()
- W, H = 980, 580
- S = pygame.display.set_mode((W, H)); pygame.display.set_caption("Solar Barycenter Calculator")
- F = pygame.font.SysFont("monospace", 13)
- FB = pygame.font.SysFont("monospace", 14, bold=True)
- FT = pygame.font.SysFont("monospace", 17, bold=True)
- MS = 1.989e30 # Sun mass (kg)
- RS = 696000 # Sun radius (km)
- AU = 1.496e8 # 1 AU in km
- ME = 5.972e24 # Earth mass (kg)
- # (name, distance in AU, mass in Earth masses)
- PL = [("Mercury",0.387,0.0553),("Venus",0.723,0.815),("Earth",1.000,1.0),
- ("Mars",1.524,0.107),("Jupiter",5.204,317.8),("Saturn",9.582,95.16),
- ("Uranus",19.20,14.54),("Neptune",30.05,17.15),("Pluto",39.48,0.0022),
- ("Eris",67.78,0.00277),("Ceres",2.768,0.000158)]
- PR = [("Eris",67.78,0.00277),("Pluto",39.48,0.0022),("Haumea",43.13,6.71e-4),
- ("Makemake",45.79,5.19e-4),("Gonggong",67.49,2.93e-4),("Charon",39.48,2.66e-4),
- ("Quaoar",43.69,2.34e-4),("Sedna",506.0,1.67e-4),("Orcus",39.42,1.06e-4),
- ("Salacia",42.18,8.24e-5),("Ceres",2.768,1.58e-4)]
- SL = {"d": 5.204, "m": 317.8} # custom-row defaults: Jupiter
- DR = None
- def bc(au, me):
- r = au * AU * me * ME / (MS + me * ME)
- return r, r - RS, r < RS
- def panel(rect, col=(25,25,45), r=6):
- pygame.draw.rect(S, col, rect, border_radius=r)
- pygame.draw.rect(S, (50,50,80), rect, 1, border_radius=r)
- def sldr(lbl, k, x, y, mn, mx_, w=270):
- v = SL[k]
- pct = max(0, min(1, (math.log10(v)-math.log10(mn)) / (math.log10(mx_)-math.log10(mn))))
- kx = x + int(pct*w)
- panel(pygame.Rect(x-8, y-22, w+16, 44), (20,20,38))
- pygame.draw.rect(S, (40,40,65), (x, y+5, w, 5), border_radius=3)
- pygame.draw.rect(S, (80,170,255),(x, y+5, kx-x, 5), border_radius=3)
- pygame.draw.circle(S, (30,30,50), (kx, y+7), 9)
- pygame.draw.circle(S, (80,170,255),(kx, y+7), 7)
- pygame.draw.circle(S, (180,220,255),(kx-2, y+5), 2)
- S.blit(F.render(f"{lbl}: {v:.4g}", 1, (170,190,220)), (x, y-18))
- return pygame.Rect(x-4, y+1, w+8, 14)
- BG=(10,10,20); CI=(60,220,100); CO=(255,70,70); CH=(80,180,255); CK=(140,100,255); CY=(255,230,60)
- COLS = [("Body",120),("Dist AU",80),("Mass/ME",88),("Bary (km)",105),("Diff (km)",110),("Inside?",72)]
- TW = sum(w for _, w in COLS)
- SR = {}
- clock = pygame.time.Clock()
- D_MIN, D_MAX = 0.1, 1000.0 # AU (1000 covers Sedna's 506 AU semi-major)
- M_MIN, M_MAX = 1e-6, 400.0 # Earth masses
- # Pluto-Charon two-body system: the only known dwarf-planet pair whose barycenter
- # lies outside the primary. Computed independently of the Sun-relative bc().
- PC_D, PC_MP, PC_MC, PC_RP = 19591, 1.303e22, 1.586e21, 1188.3 # km, kg, kg, km
- PC_R = PC_D * PC_MC / (PC_MP + PC_MC) # bary distance from Pluto center (km)
- PC_OUT = PC_R > PC_RP
- def stars():
- t = pygame.time.get_ticks()
- for i in range(45):
- b = 80 + (i*37 + t//80) % 120
- pygame.draw.circle(S, (b,b,b+20), ((i*173+11)%W, (i*97+7)%110), 1 if i%3 else 0)
- while True:
- S.fill(BG); stars()
- mx, my = pygame.mouse.get_pos()
- for e in pygame.event.get():
- if e.type == pygame.QUIT: sys.exit()
- if e.type == pygame.MOUSEBUTTONUP: DR = None
- if e.type == pygame.MOUSEBUTTONDOWN:
- if SR.get("d") and SR["d"].collidepoint(e.pos): DR = "d"
- if SR.get("m") and SR["m"].collidepoint(e.pos): DR = "m"
- for i, (n, a, m) in enumerate(PR):
- if pygame.Rect(W-165, 130+i*32, 150, 26).collidepoint(e.pos):
- SL["d"] = a; SL["m"] = m
- if e.type == pygame.MOUSEMOTION and DR:
- for k, x, mn, mx_, w in [("d",30,D_MIN,D_MAX,270), ("m",340,M_MIN,M_MAX,270)]:
- if DR == k:
- SL[k] = mn * (mx_/mn) ** max(0, min(1, (mx-x)/w))
- S.blit(FT.render("SOLAR BARYCENTER CALCULATOR", 1, CH), (30, 12))
- S.blit(F.render(f"Sun radius: {RS:,} km | Inside = barycenter within solar surface", 1, (80,80,110)), (30, 34))
- SR["d"] = sldr("Distance (AU)", "d", 30, 75, D_MIN, D_MAX)
- SR["m"] = sldr("Mass (x Earth)", "m", 340, 75, M_MIN, M_MAX)
- panel(pygame.Rect(W-170, 108, 160, 22 + len(PR)*32 + 8), (18,18,36))
- S.blit(F.render("PRESETS", 1, (100,100,150)), (W-160, 113))
- for i, (n, a, m) in enumerate(PR):
- br = pygame.Rect(W-162, 130+i*32, 144, 24); hot = br.collidepoint(mx, my)
- panel(br, (45,35,80) if hot else (30,25,55))
- S.blit(FB.render(n, 1, CK if hot else (150,130,220)), (W-155, 134+i*32))
- hx, hy = 18, 140
- panel(pygame.Rect(hx-2, hy, TW+4, 22), (20,30,65))
- for h, w in COLS:
- S.blit(FB.render(h, 1, CH), (hx+3, hy+4)); hx += w
- for i, (nm, au, me) in enumerate(PL + [("Custom", SL["d"], SL["m"])]):
- r, df, ins = bc(au, me)
- ry, rx = 164 + i*20, 18
- custom = nm == "Custom"
- pygame.draw.rect(S, (30,22,55) if custom else ((24,24,42) if i%2 else (18,18,32)), (rx-2, ry, TW+4, 19))
- if custom: pygame.draw.rect(S, (70,50,120), (rx-2, ry, TW+4, 19), 1)
- vs = [nm, f"{au:.3f}", f"{me:.5g}", f"{r:,.0f}", f"{abs(df):,.0f}", "YES" if ins else "NO"]
- for j, ((h, w), v) in enumerate(zip(COLS, vs)):
- tc = CI if (j==5 and ins) else CO if j==5 else CY if custom else (200,200,210)
- S.blit(F.render(v, 1, tc), (rx+2, ry+3)); rx += w
- by = 410
- panel(pygame.Rect(16, by, TW+4, 118), (28,18,38))
- S.blit(FB.render("BINARY: Pluto-Charon (only known case where the barycenter sits outside the primary)", 1, CK), (24, by+6))
- S.blit(F.render(f"Separation: {PC_D:,} km Pluto radius: {PC_RP:,.0f} km Charon/Pluto mass ratio: {PC_MC/PC_MP*100:.2f}%", 1, (190,190,210)), (24, by+28))
- S.blit(F.render(f"Pluto mass: {PC_MP:.3e} kg Charon mass: {PC_MC:.3e} kg", 1, (190,190,210)), (24, by+46))
- S.blit(F.render(f"Barycenter: {PC_R:,.0f} km from Pluto center", 1, (200,200,220)), (24, by+64))
- pc_col = CO if PC_OUT else CI
- pc_msg = f"OUTSIDE Pluto by {PC_R-PC_RP:,.0f} km" if PC_OUT else f"INSIDE Pluto by {PC_RP-PC_R:,.0f} km"
- S.blit(FB.render(pc_msg, 1, pc_col), (24, by+86))
- pygame.draw.line(S, (40,40,70), (18, H-28), (W-18, H-28))
- S.blit(F.render("Green=inside primary Red=outside Yellow=custom Sliders are log-scale", 1, (65,65,95)), (18, H-20))
- pygame.display.flip(); clock.tick(60)
Advertisement
Add Comment
Please, Sign In to add comment