La tierra plana es verdad. (Parte II)


Las pruebas de la rotundidad de la Tierra son i L efutables, podrás abrir una tienda de Vaps de THC y serás tu mejor cliente, vaya panda de vagos que sois!
 
Ya queda sólo una semana, y seguimos sin tener la lista terraplanera de premios, que en la Tierra esférica se pueden calcular perfectamente, esto es lo que genera ChatGPT para resolver el problema:
Código:
# eclipse_predictor_adaptativo.py
from math import asin
from skyfield.api import load,wgs84

R_SUN=695700.0
R_MOON=1737.4

LAT,LON,ALT=rellenar con los datos correspondientes
YEAR,MONTH,DAY=2026,8,12

COARSE_DT=5.0
FINE_DT=0.5
START_HOUR=16
END_HOUR=21

ts=load.timescale()
eph=load("de440s.bsp")
obs=eph["earth"]+wgs84.latlon(LAT,LON,elevation_m=ALT)
sun=eph["sun"]; moon=eph["moon"]

def sample(sec):
    h=int(sec//3600); m=int((sec%3600)//60); s=sec-h*3600-m*60
    t=ts.utc(YEAR,MONTH,DAY,h,m,s)
    sa=obs.at(t).observe(sun).apparent()
    ma=obs.at(t).observe(moon).apparent()
    d=sa.separation_from(ma).radians
    rs=asin(R_SUN/sa.distance().km)
    rm=asin(R_MOON/ma.distance().km)
    return (sec,d,rs,rm,d-(rs+rm),d-abs(rs-rm))

def cross(a,b,f):
    f1=a[f]; f2=b[f]
    return a[0]-f1*(b[0]-a[0])/(f2-f1)

def refine(a,b,field,sign):
    s=a
    prev=sample(s)
    s+=FINE_DT
    while s<=b+1e-9:
        cur=sample(s)
        if sign(prev[field],cur[field]):
            return cross(prev,cur,field)
        prev=cur
        s+=FINE_DT
    return None

coarse=[]
sec=START_HOUR*3600
while sec<=END_HOUR*3600+1e-9:
    coarse.append(sample(sec))
    sec+=COARSE_DT

imax=min(range(len(coarse)),key=lambda i:coarse[i][1])
max_time=coarse[imax][0]

c1=c2=c3=c4=None
for i in range(imax):
    if coarse[i][4]>0>=coarse[i+1][4]:
        c1=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a>0>=b);break
for i in range(imax):
    if coarse[i][5]>0>=coarse[i+1][5]:
        c2=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a>0>=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][5]<0<=coarse[i+1][5]:
        c3=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a<0<=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][4]<0<=coarse[i+1][4]:
        c4=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a<0<=b);break

fmt=lambda x:f"{int(x//3600):02d}:{int((x%3600)//60):02d}:{x%60:04.1f} UTC"
print("C1 ",fmt(c1));print("C2 ",fmt(c2));print("MAX",fmt(max_time));print("C3 ",fmt(c3));print("C4 ",fmt(c4))
Naturalmente hay que rellenar los datos de la localidad en la que se quiere observar el eclipse en LAT,LON,ALT, los dos primeros en grados y el último en metros (sobre el elipsoide wgs84):
(mensaje citado en revisión)

Obsérvese que el radio solar es de 695700.0 km, el lunar es de 1737.4 km
(mensaje citado en revisión)
y las efemérides del sistema solar las obtiene del modelo de440:
(mensaje citado en revisión)
que como ya se ha explicado muchas veces es una integración numérica del modelo gravitatorio de Newton del sistema solar, con correcciones relativistas:
(mensaje citado en revisión)

Ahora sólo hace falta tener la lista de premios alternativa, basada en una Tierra plana, hace falta un mapa de precisión (el equivalente a wgs84), y las coordenadas en dicho mapa de cada posible lugar de observación (el equivalente al LON,LAT,ALT), y unas efemérides del sistema solar (el equivalente a de440), aunque sólo hacen falta dos objetos, el Sol y la Luna, el resto no es imprescindible, en el modelo de Newton se ponen porque todos los objetos influyen en todos, en el modelo alternativo no tenemos ni idea de como funcionan, ese modelo debe proporcionar las trayectorias, diámetros, etc., de los objetos del modelo.
 
Última edición:
Ahora le ha tocado el turno a Claude, en este caso emplea de421 como modelo del sistema solar, y el diámetro lunar es el mismo, pero el del Sol es ligeramente diferente:
(mensaje citado en revisión)
Este es el código completo:
Código:
#!/usr/bin/env python3
"""
================================================================================
 Efemerides locales del eclipse solar del 12 de agosto de 2026
================================================================================

Calcula, para unas coordenadas geograficas dadas, los instantes de:

    C1  - Inicio del eclipse parcial (primer contacto)
    C2  - Inicio de la totalidad (segundo contacto)      [solo si es total ahi]
    Max - Eclipse maximo (minima separacion Sol-Luna)
    C3  - Fin de la totalidad (tercer contacto)           [solo si es total ahi]
    C4  - Fin del eclipse parcial (cuarto contacto)

junto con la magnitud del eclipse, el porcentaje de area solar oculta y la
duracion de la totalidad (si la hay).

El calculo es puramente geometrico: usa las efemerides JPL DE421 para obtener
posiciones topocentricas (afectadas por paralaje, ya que se calculan "desde"
el punto exacto del observador) del Sol y la Luna, y busca por metodos
numericos los instantes en que la separacion angular entre sus discos cumple
las condiciones de cada contacto.

--------------------------------------------------------------------------------
REQUISITOS
--------------------------------------------------------------------------------
    pip install skyfield scipy numpy

La primera vez que se ejecuta, skyfield descargara automaticamente el fichero
de efemerides 'de421.bsp' (~17 MB) y el fichero de tiempos 'deltat.data' /
'deltat.preds' desde servidores publicos. Se necesita conexion a internet
la primera vez; luego quedan cacheados en el directorio de trabajo.

--------------------------------------------------------------------------------
USO
--------------------------------------------------------------------------------
    python eclipse_12ago2026.py --lat 42.8805 --lon -8.5457 --elev 50 \
        --tz Europe/Madrid --nombre "A Coruna"

    python eclipse_12ago2026.py --lat 64.1466 --lon -21.9426 --elev 20 \
        --tz Atlantic/Reykjavik --nombre "Reikiavik"

Si no se especifica --tz se usa Europe/Madrid por defecto.
================================================================================
"""

import argparse
from datetime import timedelta
from zoneinfo import ZoneInfo

import numpy as np
from scipy.optimize import brentq, minimize_scalar
from skyfield.api import load, wgs84

# ------------------------------------------------------------------ #
# Constantes
# ------------------------------------------------------------------ #
FECHA_ECLIPSE = (2026, 8, 12)   # año, mes, dia (UTC, se explora el dia completo)
RADIO_SOL_KM = 696000.0
RADIO_LUNA_KM = 1737.4


# ------------------------------------------------------------------ #
# Construccion del observador
# ------------------------------------------------------------------ #
def construir_observador(lat, lon, elev_m):
    """Carga efemerides y devuelve (timescale, efemerides, posicion observador)."""
    ts = load.timescale()
    eph = load('de421.bsp')
    tierra = eph['earth']
    lugar = wgs84.latlon(lat, lon, elevation_m=elev_m)
    observador = tierra + lugar
    return ts, eph, observador


# ------------------------------------------------------------------ #
# Geometria Sol-Luna vista desde el observador
# ------------------------------------------------------------------ #
def separacion_y_radios(observador, eph, t):
    """
    Devuelve (separacion_angular_deg, radio_aparente_sol_deg,
    radio_aparente_luna_deg, altitud_sol_deg) en el instante t.
    """
    astrometrico_sol = observador.at(t).observe(eph['sun'])
    astrometrico_luna = observador.at(t).observe(eph['moon'])

    aparente_sol = astrometrico_sol.apparent()
    aparente_luna = astrometrico_luna.apparent()

    separacion = aparente_sol.separation_from(aparente_luna).degrees

    _, _, dist_sol = aparente_sol.radec()
    _, _, dist_luna = aparente_luna.radec()

    radio_sol = np.degrees(np.arcsin(RADIO_SOL_KM / dist_sol.km))
    radio_luna = np.degrees(np.arcsin(RADIO_LUNA_KM / dist_luna.km))

    alt_sol, _, _ = observador.at(t).observe(eph['sun']).apparent().altaz()

    return separacion, radio_sol, radio_luna, alt_sol.degrees


def f_contacto_exterior(t_tt, ts, observador, eph):
    """separacion - (radio_sol + radio_luna): raiz = C1 o C4."""
    t = ts.tt_jd(t_tt)
    sep, r_sol, r_luna, _ = separacion_y_radios(observador, eph, t)
    return sep - (r_sol + r_luna)


def f_contacto_interior(t_tt, ts, observador, eph):
    """separacion - |radio_luna - radio_sol|: raiz = C2 o C3 (si hay totalidad)."""
    t = ts.tt_jd(t_tt)
    sep, r_sol, r_luna, _ = separacion_y_radios(observador, eph, t)
    return sep - abs(r_luna - r_sol)


# ------------------------------------------------------------------ #
# Busqueda de instantes de contacto
# ------------------------------------------------------------------ #
def buscar_cambios_de_signo(func, ts, observador, eph, jd_ini, jd_fin, paso_min=1.0):
    """
    Muestrea func() cada 'paso_min' minutos entre jd_ini y jd_fin (dias julianos TT)
    y devuelve la lista de intervalos [t0, t1] donde hay cambio de signo.
    """
    paso_dias = paso_min / (24 * 60)
    n = int((jd_fin - jd_ini) / paso_dias) + 1
    jds = np.linspace(jd_ini, jd_fin, n)
    valores = np.array([func(jd, ts, observador, eph) for jd in jds])

    intervalos = []
    for i in range(len(jds) - 1):
        if np.sign(valores[i]) != np.sign(valores[i + 1]) and not np.isnan(valores[i]) \
                and not np.isnan(valores[i + 1]):
            intervalos.append((jds[i], jds[i + 1]))
    return intervalos


def refinar_raiz(func, ts, observador, eph, intervalo):
    a, b = intervalo
    raiz = brentq(func, a, b, args=(ts, observador, eph), xtol=1e-10)
    return ts.tt_jd(raiz)


# ------------------------------------------------------------------ #
# Calculo principal
# ------------------------------------------------------------------ #
def calcular_eclipse(lat, lon, elev_m, tz_nombre, nombre_lugar):
    ts, eph, observador = construir_observador(lat, lon, elev_m)

    anio, mes, dia = FECHA_ECLIPSE
    t_ini = ts.utc(anio, mes, dia, 0, 0, 0)
    t_fin = ts.utc(anio, mes, dia, 23, 59, 59)

    # 1) Localizar el instante de minima separacion (maximo del eclipse)
    def separacion_pura(jd_tt):
        t = ts.tt_jd(jd_tt)
        sep, _, _, _ = separacion_y_radios(observador, eph, t)
        return sep

    res = minimize_scalar(
        separacion_pura,
        bounds=(t_ini.tt, t_fin.tt),
        method='bounded',
        options={'xatol': 1e-9},
    )
    t_max = ts.tt_jd(res.x)
    sep_max, r_sol_max, r_luna_max, alt_sol_max = separacion_y_radios(observador, eph, t_max)

    # Si en el maximo el Sol esta bajo el horizonte, el eclipse no es visible ahi
    visible_localmente = alt_sol_max > -0.3  # margen por refraccion/tamano del disco

    # 2) Contactos exteriores C1 / C4 (borde a borde)
    intervalos_ext = buscar_cambios_de_signo(
        f_contacto_exterior, ts, observador, eph, t_ini.tt, t_fin.tt, paso_min=1.0
    )
    contactos_ext = [refinar_raiz(f_contacto_exterior, ts, observador, eph, iv)
                      for iv in intervalos_ext]

    # 3) Contactos interiores C2 / C3 (solo existen si hay totalidad/anularidad ahi)
    intervalos_int = buscar_cambios_de_signo(
        f_contacto_interior, ts, observador, eph, t_ini.tt, t_fin.tt, paso_min=1.0
    )
    contactos_int = [refinar_raiz(f_contacto_interior, ts, observador, eph, iv)
                      for iv in intervalos_int]

    # Magnitud del eclipse: fraccion del diametro solar cubierto en el maximo
    magnitud = (r_sol_max + r_luna_max - sep_max) / (2 * r_sol_max)
    magnitud = max(0.0, magnitud)

    # Obscuracion de area (aproximacion por interseccion de dos circulos)
    obscuracion_pct = calcular_obscuracion_area(sep_max, r_sol_max, r_luna_max)

    return {
        'lugar': nombre_lugar,
        'lat': lat,
        'lon': lon,
        'tz': tz_nombre,
        'visible': visible_localmente,
        'c1_c4': sorted(contactos_ext, key=lambda t: t.tt),
        'c2_c3': sorted(contactos_int, key=lambda t: t.tt),
        't_max': t_max,
        'alt_sol_max': alt_sol_max,
        'magnitud': magnitud,
        'obscuracion_pct': obscuracion_pct,
        'es_total_aqui': len(contactos_int) >= 2 and r_luna_max > r_sol_max,
    }


def calcular_obscuracion_area(sep, r_sol, r_luna):
    """Porcentaje de area del disco solar cubierta por la Luna (interseccion de circulos)."""
    if sep >= r_sol + r_luna:
        return 0.0
    if sep <= abs(r_sol - r_luna):
        # un disco cubre completamente al otro (total o anular)
        return 100.0 if r_luna >= r_sol else (r_luna / r_sol) ** 2 * 100.0

    d, R, rr = sep, r_sol, r_luna
    parte1 = rr**2 * np.arccos((d**2 + rr**2 - R**2) / (2 * d * rr))
    parte2 = R**2 * np.arccos((d**2 + R**2 - rr**2) / (2 * d * R))
    parte3 = 0.5 * np.sqrt(max(0.0, (-d + rr + R) * (d + rr - R) * (d - rr + R) * (d + rr + R)))
    area_interseccion = parte1 + parte2 - parte3
    area_sol = np.pi * R**2
    return 100.0 * area_interseccion / area_sol


# ------------------------------------------------------------------ #
# Presentacion de resultados
# ------------------------------------------------------------------ #
def formatear_hora(t_skyfield, tz_nombre):
    dt_utc = t_skyfield.utc_datetime()
    dt_local = dt_utc.astimezone(ZoneInfo(tz_nombre))
    return f"{dt_local.strftime('%H:%M:%S')} ({tz_nombre})  |  {dt_utc.strftime('%H:%M:%S')} UTC"


def imprimir_resultados(r):
    print("=" * 72)
    print(f"ECLIPSE DEL 12 DE AGOSTO DE 2026 — {r['lugar']}")
    print(f"Coordenadas: lat {r['lat']:.4f}, lon {r['lon']:.4f}")
    print("=" * 72)

    if not r['visible']:
        print("\nEl Sol esta bajo el horizonte durante el maximo del eclipse en esta")
        print("localidad: el eclipse NO es observable (o solo parcialmente, cerca")
        print("del horizonte, segun la hora del orto/ocaso).\n")

    print(f"\nMagnitud del eclipse:     {r['magnitud']*100:.1f} % del diametro solar")
    print(f"Obscuracion (area):       {r['obscuracion_pct']:.1f} % del disco solar")
    print(f"Tipo en esta localidad:   {'TOTAL' if r['es_total_aqui'] else 'PARCIAL'}")

    print("\n--- Contactos ---")
    etiquetas_ext = ['C1 (inicio parcial)', 'C4 (fin parcial)']
    for etiqueta, t in zip(etiquetas_ext, r['c1_c4']):
        print(f"  {etiqueta:22s}: {formatear_hora(t, r['tz'])}")

    if r['c2_c3']:
        etiquetas_int = ['C2 (inicio totalidad)', 'C3 (fin totalidad)']
        for etiqueta, t in zip(etiquetas_int, r['c2_c3']):
            print(f"  {etiqueta:22s}: {formatear_hora(t, r['tz'])}")
        if len(r['c2_c3']) == 2:
            duracion = r['c2_c3'][1].tt - r['c2_c3'][0].tt
            duracion_seg = duracion * 86400
            print(f"\nDuracion de la totalidad: {duracion_seg:.0f} s "
                  f"({duracion_seg/60:.1f} min)")

    print(f"\n  {'Maximo del eclipse':22s}: {formatear_hora(r['t_max'], r['tz'])}")
    print(f"  Altura del Sol en el maximo: {r['alt_sol_max']:.1f}°")
    print("=" * 72)


# ------------------------------------------------------------------ #
# CLI
# ------------------------------------------------------------------ #
def main():
    parser = argparse.ArgumentParser(
        description="Efemerides locales del eclipse solar del 12 de agosto de 2026."
    )
    parser.add_argument('--lat', type=float, required=True, help='Latitud en grados (norte +)')
    parser.add_argument('--lon', type=float, required=True, help='Longitud en grados (este +)')
    parser.add_argument('--elev', type=float, default=0.0, help='Elevacion en metros (opcional)')
    parser.add_argument('--tz', type=str, default='Europe/Madrid',
                         help="Zona horaria IANA, ej. Europe/Madrid, Atlantic/Reykjavik")
    parser.add_argument('--nombre', type=str, default='Localidad',
                         help='Nombre a mostrar en el informe')
    args = parser.parse_args()

    resultados = calcular_eclipse(args.lat, args.lon, args.elev, args.tz, args.nombre)
    imprimir_resultados(resultados)


if __name__ == '__main__':
    main()
pero le he pedido que además incluya el cálculo de la refracción atmosférica (con la fórmula de Bennett) y el valor de Delta T. Los resultados son muy parecidos a los del anterior, no se si la diferencia se debe al modelo empleado, al valor de Delta T o al cambio en el diámetro del Sol.

Por último, repito:
Ya queda sólo una semana, y seguimos sin tener la lista terraplanera de premios, que en la Tierra esférica se pueden calcular perfectamente, esto es lo que genera ChatGPT para resolver el problema:
Código:
# eclipse_predictor_adaptativo.py
from math import asin
from skyfield.api import load,wgs84

R_SUN=695700.0
R_MOON=1737.4

LAT,LON,ALT=rellenar con los datos correspondientes
YEAR,MONTH,DAY=2026,8,12

COARSE_DT=5.0
FINE_DT=0.5
START_HOUR=16
END_HOUR=21

ts=load.timescale()
eph=load("de440s.bsp")
obs=eph["earth"]+wgs84.latlon(LAT,LON,elevation_m=ALT)
sun=eph["sun"]; moon=eph["moon"]

def sample(sec):
    h=int(sec//3600); m=int((sec%3600)//60); s=sec-h*3600-m*60
    t=ts.utc(YEAR,MONTH,DAY,h,m,s)
    sa=obs.at(t).observe(sun).apparent()
    ma=obs.at(t).observe(moon).apparent()
    d=sa.separation_from(ma).radians
    rs=asin(R_SUN/sa.distance().km)
    rm=asin(R_MOON/ma.distance().km)
    return (sec,d,rs,rm,d-(rs+rm),d-abs(rs-rm))

def cross(a,b,f):
    f1=a[f]; f2=b[f]
    return a[0]-f1*(b[0]-a[0])/(f2-f1)

def refine(a,b,field,sign):
    s=a
    prev=sample(s)
    s+=FINE_DT
    while s<=b+1e-9:
        cur=sample(s)
        if sign(prev[field],cur[field]):
            return cross(prev,cur,field)
        prev=cur
        s+=FINE_DT
    return None

coarse=[]
sec=START_HOUR*3600
while sec<=END_HOUR*3600+1e-9:
    coarse.append(sample(sec))
    sec+=COARSE_DT

imax=min(range(len(coarse)),key=lambda i:coarse[i][1])
max_time=coarse[imax][0]

c1=c2=c3=c4=None
for i in range(imax):
    if coarse[i][4]>0>=coarse[i+1][4]:
        c1=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a>0>=b);break
for i in range(imax):
    if coarse[i][5]>0>=coarse[i+1][5]:
        c2=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a>0>=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][5]<0<=coarse[i+1][5]:
        c3=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a<0<=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][4]<0<=coarse[i+1][4]:
        c4=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a<0<=b);break

fmt=lambda x:f"{int(x//3600):02d}:{int((x%3600)//60):02d}:{x%60:04.1f} UTC"
print("C1 ",fmt(c1));print("C2 ",fmt(c2));print("MAX",fmt(max_time));print("C3 ",fmt(c3));print("C4 ",fmt(c4))
Naturalmente hay que rellenar los datos de la localidad en la que se quiere observar el eclipse en LAT,LON,ALT, los dos primeros en grados y el último en metros (sobre el elipsoide wgs84):


Obsérvese que el radio solar es de 695700.0 km, el lunar es de 1737.4 km

y las efemérides del sistema solar las obtiene del modelo de440:

que como ya se ha explicado muchas veces es una integración numérica del modelo gravitatorio de Newton del sistema solar, con correcciones relativistas:


Ahora sólo hace falta tener la lista de premios alternativa, basada en una Tierra plana, hace falta un mapa de precisión (el equivalente a wgs84), y las coordenadas en dicho mapa de cada posible lugar de observación (el equivalente al LON,LAT,ALT), y unas efemérides del sistema solar (el equivalente a de440), aunque sólo hacen falta dos objetos, el Sol y la Luna, el resto no es imprescindible, en el modelo de Newton se ponen porque todos los objetos influyen en todos, en el modelo alternativo no tenemos ni idea de como funcionan, ese modelo debe proporcionar las trayectorias, diámetros, etc., de los objetos del modelo.

Espero que lo podamos tener antes del día 12, para poder comparar con estos dos.
 
AHORA LE TOCA EL TURNO AL GEOCENTRISMO...

SE VE MUY EXCITADO MUCHOPICO CON EL ECLIPSE, POR ESO HAY QUE RECORDAR QUE UN ECLIPSE ES UN FENÓMENO ASTRONÓMICO QUE SUCEDE EN EL CIELO, Y QUE NO AFECTA DE NINGUNA MANERA NI A LA PLANITUD NI A LA INMOVILIDAD DE LA TIERRA, POR MUCHOS ASPAVIENTOS QUE SE HAGAN.

(adjunto visible para usuarios registrados)
 

Adjuntos

Archivo oculto para usuarios no registrados
Última edición:
Ya queda sólo una semana, y seguimos sin tener la lista terraplanera de premios, que en la Tierra esférica se pueden calcular perfectamente, esto es lo que genera ChatGPT para resolver el problema:
Código:
# eclipse_predictor_adaptativo.py
from math import asin
from skyfield.api import load,wgs84

R_SUN=695700.0
R_MOON=1737.4

LAT,LON,ALT=rellenar con los datos correspondientes
YEAR,MONTH,DAY=2026,8,12

COARSE_DT=5.0
FINE_DT=0.5
START_HOUR=16
END_HOUR=21

ts=load.timescale()
eph=load("de440s.bsp")
obs=eph["earth"]+wgs84.latlon(LAT,LON,elevation_m=ALT)
sun=eph["sun"]; moon=eph["moon"]

def sample(sec):
    h=int(sec//3600); m=int((sec%3600)//60); s=sec-h*3600-m*60
    t=ts.utc(YEAR,MONTH,DAY,h,m,s)
    sa=obs.at(t).observe(sun).apparent()
    ma=obs.at(t).observe(moon).apparent()
    d=sa.separation_from(ma).radians
    rs=asin(R_SUN/sa.distance().km)
    rm=asin(R_MOON/ma.distance().km)
    return (sec,d,rs,rm,d-(rs+rm),d-abs(rs-rm))

def cross(a,b,f):
    f1=a[f]; f2=b[f]
    return a[0]-f1*(b[0]-a[0])/(f2-f1)

def refine(a,b,field,sign):
    s=a
    prev=sample(s)
    s+=FINE_DT
    while s<=b+1e-9:
        cur=sample(s)
        if sign(prev[field],cur[field]):
            return cross(prev,cur,field)
        prev=cur
        s+=FINE_DT
    return None

coarse=[]
sec=START_HOUR*3600
while sec<=END_HOUR*3600+1e-9:
    coarse.append(sample(sec))
    sec+=COARSE_DT

imax=min(range(len(coarse)),key=lambda i:coarse[i][1])
max_time=coarse[imax][0]

c1=c2=c3=c4=None
for i in range(imax):
    if coarse[i][4]>0>=coarse[i+1][4]:
        c1=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a>0>=b);break
for i in range(imax):
    if coarse[i][5]>0>=coarse[i+1][5]:
        c2=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a>0>=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][5]<0<=coarse[i+1][5]:
        c3=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a<0<=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][4]<0<=coarse[i+1][4]:
        c4=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a<0<=b);break

fmt=lambda x:f"{int(x//3600):02d}:{int((x%3600)//60):02d}:{x%60:04.1f} UTC"
print("C1 ",fmt(c1));print("C2 ",fmt(c2));print("MAX",fmt(max_time));print("C3 ",fmt(c3));print("C4 ",fmt(c4))
Naturalmente hay que rellenar los datos de la localidad en la que se quiere observar el eclipse en LAT,LON,ALT, los dos primeros en grados y el último en metros (sobre el elipsoide wgs84):


Obsérvese que el radio solar es de 695700.0 km, el lunar es de 1737.4 km

y las efemérides del sistema solar las obtiene del modelo de440:

que como ya se ha explicado muchas veces es una integración numérica del modelo gravitatorio de Newton del sistema solar, con correcciones relativistas:


Ahora sólo hace falta tener la lista de premios alternativa, basada en una Tierra plana, hace falta un mapa de precisión (el equivalente a wgs84), y las coordenadas en dicho mapa de cada posible lugar de observación (el equivalente al LON,LAT,ALT), y unas efemérides del sistema solar (el equivalente a de440), aunque sólo hacen falta dos objetos, el Sol y la Luna, el resto no es imprescindible, en el modelo de Newton se ponen porque todos los objetos influyen en todos, en el modelo alternativo no tenemos ni idea de como funcionan, ese modelo debe proporcionar las trayectorias, diámetros, etc., de los objetos del modelo.

Creo que tarkus está trabajando en ello, no seamos impacientes.

Y seguro el modelo unicornio-terraplano explica por qué la trayectoria de la sombra está tan curvada:

(imagen visible para usuarios registrados)
 
AHORA LE TOCA EL TURNO AL GEOCENTRISMO...

SE VE MUY EXCITADO MUCHOPICO CON EL ECLIPSE, POR ESO HAY QUE RECORDAR QUE UN ECLIPSE ES UN FENÓMENO ASTRONÓMICO QUE SUCEDE EN EL CIELO, Y QUE NO AFECTA DE NINGUNA MANERA NI A LA PLANITUD NI A LA INMOVILIDAD DE LA TIERRA, POR MUCHOS ASPAVIENTOS QUE SE HAGAN.

(adjunto visible para usuarios registrados)

¿Puedes explicarnos de qué manera...

1. La existencia de océanos abusa la dinámica de fluidos.
2. La existencia de atmósfera abusa la Segunda Ley de la Termodinámica.

...o estás copiando y pegando afirmaciones sin saber ni qué quieren decir?
 
** El Teorema del achatamiento-desachatamiento solar de @Descansa Hombre "explicaría" los dos primeros. De momento es la explicasion más rasonable que ha aportado la Siensia de la Planisie.

Se comenta que el Genio terraplanista está trabajado en un nuevo paper sobre el achatamiento lunar que resolvería los puntos 3 y 4, pero son solo rumores.

(adjunto visible para usuarios registrados)
 

Adjuntos

Archivo oculto para usuarios no registrados
Última edición:
ASPAVIENTOS LOS QUE HACE EL 'SISTEMA' PARA METERNOS EL HELIOCENTRISMO POR LOS OJOS SEA COMO SEA.

(adjunto visible para usuarios registrados)

VUESTRA IDEA NO TIENE PARANGÓN EN LA PSIQUIATRÍA.
 

Adjuntos

Archivo oculto para usuarios no registrados
Seguimos, esta vez le toca a gemini:
Código:
from datetime import datetime, timezone
import zoneinfo
import numpy as np
from skyfield.api import load, wgs84

# ==============================================================================
# CONSTANTES ASTRONÓMICAS Y FÍSICAS (IAU)
# ==============================================================================
RADIO_SOL_KM = 696340.0   # Radio ecuatorial medio del Sol en kilómetros
RADIO_LUNA_KM = 1737.4    # Radio medio de la Luna en kilómetros

# Parámetros atmosféricos estándar
TEMP_ESTANDAR_C = 15.0     # Temperatura en °C
PRESION_ESTANDAR_MBAR = 1010.0 # Presión en mbar/hPa
# ==============================================================================


def calcular_refraccion_bennett(alt_grados, temp_c=TEMP_ESTANDAR_C, presion_mbar=PRESION_ESTANDAR_MBAR):
    """
    Calcula la refracción atmosférica en grados usando la fórmula de Bennett (1982) / Sæmundsson (1986).
    """
    if alt_grados <= -1.0:
        return 0.0
    
    alt = max(alt_grados, 0.0)
    cotan_argumento = np.radians(alt + 10.3 / (alt + 5.11))
    refraccion_minutos = 1.02 / np.tan(cotan_argumento)
    
    factor_tp = (presion_mbar / PRESION_ESTANDAR_MBAR) * (283.15 / (273.15 + temp_c))
    refraccion_corregida_min = refraccion_minutos * factor_tp
    
    return refraccion_corregida_min / 60.0


def calcular_efemerides_eclipse(latitud, longitud, elevacion_m=0, 
                                temp_c=TEMP_ESTANDAR_C, 
                                presion_mbar=PRESION_ESTANDAR_MBAR, 
                                zona_horaria="Europe/Madrid"):
    """
    Calcula las efemérides del eclipse solar del 12 de agosto de 2026.
    """
    print("Cargando efemérides planetarias y tablas IERS...")
    ts = load.timescale()
    eph = load('de421.bsp')
    
    sun = eph['sun']
    moon = eph['moon']
    earth = eph['earth']
    
    tz_local = zoneinfo.ZoneInfo(zona_horaria)
    observador = earth + wgs84.latlon(latitud, longitud, elevation_m=elevacion_m)
    
    # Rango de evaluación: 14:00 UTC a 21:00 UTC
    t0 = ts.utc(2026, 8, 12, 14, 0, 0)
    t1 = ts.utc(2026, 8, 12, 21, 0, 0)
    
    minutos = int((t1 - t0) * 24 * 60)
    tiempos = ts.utc(2026, 8, 12, 14, np.linspace(0, minutos, minutos * 60)) # Muestreo por segundo
    
    delta_t = tiempos[0].delta_t
    
    print("Calculando posiciones topocéntricas y contactos de totalidad...")
    pos_sol = observador.at(tiempos).observe(sun).apparent()
    pos_luna = observador.at(tiempos).observe(moon).apparent()
    
    # Separación angular geométrica entre los centros
    separaciones = pos_sol.separation_from(pos_luna).degrees
    
    # Distancias topocéntricas en km
    dist_sol_km = pos_sol.distance().km
    dist_luna_km = pos_luna.distance().km
    
    # CÁLCULO DE RADIOS APARENTES USANDO LAS CONSTANTES GLOBALES
    radio_sol_deg = np.degrees(np.arcsin(RADIO_SOL_KM / dist_sol_km))
    radio_luna_deg = np.degrees(np.arcsin(RADIO_LUNA_KM / dist_luna_km))
    
    # Umbral eclipse parcial (Suma de radios: C1 y C4)
    umbral_parcial = radio_sol_deg + radio_luna_deg
    en_eclipse_parcial = separaciones < umbral_parcial
    
    # Umbral eclipse total (Diferencia de radios: C2 y C3)
    umbral_total = radio_luna_deg - radio_sol_deg
    en_eclipse_total = separaciones < umbral_total
    
    if not np.any(en_eclipse_parcial):
        print("\n[!] En esta ubicación no se observará el eclipse el 12 de agosto de 2026.")
        return

    # Máximo eclipse
    idx_max = np.argmin(separaciones)
    t_max = tiempos[idx_max]
    
    # Contactos Parciales C1 y C4
    indices_parcial = np.where(en_eclipse_parcial)[0]
    idx_c1 = indices_parcial[0]
    idx_c4 = indices_parcial[-1]
    
    # Altura y refracción en el máximo
    alt_geom, az_max, _ = pos_sol[idx_max].altaz()
    refraccion = calcular_refraccion_bennett(alt_geom.degrees, temp_c, presion_mbar)
    alt_refractada = alt_geom.degrees + refraccion
    
    # Cobertura del diámetro solar
    d_min = separaciones[idx_max]
    r_s = radio_sol_deg[idx_max]
    r_m = radio_luna_deg[idx_max]
    cobertura_diametro = max(0.0, min(1.0, (r_s + r_m - d_min) / (2 * r_s))) * 100

    def fmt_tiempos(t_skyfield):
        dt_utc = t_skyfield.utc_datetime()
        dt_local = dt_utc.astimezone(tz_local)
        return f"{dt_local.strftime('%H:%M:%S')} (Hora local) | {dt_utc.strftime('%H:%M:%S')} UTC"

    print("\n" + "="*70)
    print(f" EFEMÉRIDES DEL ECLIPSE SOLAR - 12 DE AGOSTO DE 2026")
    print(f" Coordenadas: Lat {latitud:.4f}°, Lon {longitud:.4f}° | Alt: {elevacion_m} m")
    print(f" Zona Horaria Configurada: {zona_horaria}")
    print("="*70)
    print(f" Parámetro Delta T (ΔT)        : {delta_t:.2f} s")
    print("-" * 70)
    print(f" Inicio Parcial (Contacto C1)  : {fmt_tiempos(tiempos[idx_c1])}")
    
    # Comprobar si hay totalidad
    es_total = np.any(en_eclipse_total)
    
    if es_total:
        indices_total = np.where(en_eclipse_total)[0]
        idx_c2 = indices_total[0]
        idx_c3 = indices_total[-1]
        
        duracion_seg = (tiempos[idx_c3].utc_datetime() - tiempos[idx_c2].utc_datetime()).total_seconds()
        minutos_tot = int(duracion_seg // 60)
        segundos_tot = int(duracion_seg % 60)
        
        print(f" Inicio Totalidad (Contacto C2): {fmt_tiempos(tiempos[idx_c2])}")
        print(f" Máximo del Eclipse           : {fmt_tiempos(t_max)}")
        print(f" Fin Totalidad (Contacto C3)   : {fmt_tiempos(tiempos[idx_c3])}")
    else:
        print(f" Máximo del Eclipse           : {fmt_tiempos(t_max)}")
        
    print(f" Fin Parcial (Contacto C4)     : {fmt_tiempos(tiempos[idx_c4])}")
    print("-" * 70)
    
    if es_total:
        print(f" Duración de la Totalidad      : {minutos_tot}m {segundos_tot}s")
        
    print(f" Altura del Sol (geométrica)   : {alt_geom.degrees:.2f}°")
    print(f" Refracción estimada           : +{refraccion:.2f}° (Temp: {temp_c}°C, P: {presion_mbar} mbar)")
    print(f" Altura del Sol (aparente)     : {alt_refractada:.2f}° sobre el horizonte")
    print(f" Azimut del Sol en el máximo   : {az_max.degrees:.1f}° (Oeste-Suroeste)")
    print(f" Cobertura solar máxima        : {cobertura_diametro:.1f}%")
    
    if es_total:
        print(" ESTADO                        : ¡ECLIPSE TOTAL!")
    else:
        print(" ESTADO                        : Eclipse Parcial")
    print("="*70 + "\n")

if __name__ == "__main__":
    LATITUD = ponga el valor correcto (º)
    LONGITUD = ponga el valor correcto (º)
    ELEVACION_M = ponga el valor correcto (m)
    ZONA_HORARIA = "Europe/Madrid"
    
    calcular_efemerides_eclipse(
        latitud=LATITUD, 
        longitud=LONGITUD, 
        elevacion_m=ELEVACION_M, 
        zona_horaria=ZONA_HORARIA
    )
en este caso el valor del radio del Sol vuelve a ser diferente, cosas de que sea un cuerpo gaseoso:
(mensaje citado en revisión)
emplea de421, y tiene variables para cambiar la presión y la temperatura para corregir mejor la refracción:
(mensaje citado en revisión)

Y seguimos esperando el modelo terraplanero, no vuelvo a repetir todo lo que tienen que incluir.

Creo que tarkus está trabajando en ello, no seamos impacientes.

Y seguro el modelo unicornio-terraplano explica por qué la trayectoria de la sombra está tan curvada:

(imagen visible para usuarios registrados)
Francamente lo dudo, no le interesó lo más mínimo cuando hubo un eclipse en Argentina, pero por si ahora no llega a tiempo, tenemos otros dos los años venideros, si se pone ahora quizá consiga las predicciones del último, que es anular, de esos imposibles con una sombra cilíndrica como defiende él.
 
Seguimos, esta vez le toca a gemini:
Código:
from datetime import datetime, timezone
import zoneinfo
import numpy as np
from skyfield.api import load, wgs84

# ==============================================================================
# CONSTANTES ASTRONÓMICAS Y FÍSICAS (IAU)
# ==============================================================================
RADIO_SOL_KM = 696340.0   # Radio ecuatorial medio del Sol en kilómetros
RADIO_LUNA_KM = 1737.4    # Radio medio de la Luna en kilómetros

# Parámetros atmosféricos estándar
TEMP_ESTANDAR_C = 15.0     # Temperatura en °C
PRESION_ESTANDAR_MBAR = 1010.0 # Presión en mbar/hPa
# ==============================================================================


def calcular_refraccion_bennett(alt_grados, temp_c=TEMP_ESTANDAR_C, presion_mbar=PRESION_ESTANDAR_MBAR):
    """
    Calcula la refracción atmosférica en grados usando la fórmula de Bennett (1982) / Sæmundsson (1986).
    """
    if alt_grados <= -1.0:
        return 0.0
    
    alt = max(alt_grados, 0.0)
    cotan_argumento = np.radians(alt + 10.3 / (alt + 5.11))
    refraccion_minutos = 1.02 / np.tan(cotan_argumento)
    
    factor_tp = (presion_mbar / PRESION_ESTANDAR_MBAR) * (283.15 / (273.15 + temp_c))
    refraccion_corregida_min = refraccion_minutos * factor_tp
    
    return refraccion_corregida_min / 60.0


def calcular_efemerides_eclipse(latitud, longitud, elevacion_m=0, 
                                temp_c=TEMP_ESTANDAR_C, 
                                presion_mbar=PRESION_ESTANDAR_MBAR, 
                                zona_horaria="Europe/Madrid"):
    """
    Calcula las efemérides del eclipse solar del 12 de agosto de 2026.
    """
    print("Cargando efemérides planetarias y tablas IERS...")
    ts = load.timescale()
    eph = load('de421.bsp')
    
    sun = eph['sun']
    moon = eph['moon']
    earth = eph['earth']
    
    tz_local = zoneinfo.ZoneInfo(zona_horaria)
    observador = earth + wgs84.latlon(latitud, longitud, elevation_m=elevacion_m)
    
    # Rango de evaluación: 14:00 UTC a 21:00 UTC
    t0 = ts.utc(2026, 8, 12, 14, 0, 0)
    t1 = ts.utc(2026, 8, 12, 21, 0, 0)
    
    minutos = int((t1 - t0) * 24 * 60)
    tiempos = ts.utc(2026, 8, 12, 14, np.linspace(0, minutos, minutos * 60)) # Muestreo por segundo
    
    delta_t = tiempos[0].delta_t
    
    print("Calculando posiciones topocéntricas y contactos de totalidad...")
    pos_sol = observador.at(tiempos).observe(sun).apparent()
    pos_luna = observador.at(tiempos).observe(moon).apparent()
    
    # Separación angular geométrica entre los centros
    separaciones = pos_sol.separation_from(pos_luna).degrees
    
    # Distancias topocéntricas en km
    dist_sol_km = pos_sol.distance().km
    dist_luna_km = pos_luna.distance().km
    
    # CÁLCULO DE RADIOS APARENTES USANDO LAS CONSTANTES GLOBALES
    radio_sol_deg = np.degrees(np.arcsin(RADIO_SOL_KM / dist_sol_km))
    radio_luna_deg = np.degrees(np.arcsin(RADIO_LUNA_KM / dist_luna_km))
    
    # Umbral eclipse parcial (Suma de radios: C1 y C4)
    umbral_parcial = radio_sol_deg + radio_luna_deg
    en_eclipse_parcial = separaciones < umbral_parcial
    
    # Umbral eclipse total (Diferencia de radios: C2 y C3)
    umbral_total = radio_luna_deg - radio_sol_deg
    en_eclipse_total = separaciones < umbral_total
    
    if not np.any(en_eclipse_parcial):
        print("\n[!] En esta ubicación no se observará el eclipse el 12 de agosto de 2026.")
        return

    # Máximo eclipse
    idx_max = np.argmin(separaciones)
    t_max = tiempos[idx_max]
    
    # Contactos Parciales C1 y C4
    indices_parcial = np.where(en_eclipse_parcial)[0]
    idx_c1 = indices_parcial[0]
    idx_c4 = indices_parcial[-1]
    
    # Altura y refracción en el máximo
    alt_geom, az_max, _ = pos_sol[idx_max].altaz()
    refraccion = calcular_refraccion_bennett(alt_geom.degrees, temp_c, presion_mbar)
    alt_refractada = alt_geom.degrees + refraccion
    
    # Cobertura del diámetro solar
    d_min = separaciones[idx_max]
    r_s = radio_sol_deg[idx_max]
    r_m = radio_luna_deg[idx_max]
    cobertura_diametro = max(0.0, min(1.0, (r_s + r_m - d_min) / (2 * r_s))) * 100

    def fmt_tiempos(t_skyfield):
        dt_utc = t_skyfield.utc_datetime()
        dt_local = dt_utc.astimezone(tz_local)
        return f"{dt_local.strftime('%H:%M:%S')} (Hora local) | {dt_utc.strftime('%H:%M:%S')} UTC"

    print("\n" + "="*70)
    print(f" EFEMÉRIDES DEL ECLIPSE SOLAR - 12 DE AGOSTO DE 2026")
    print(f" Coordenadas: Lat {latitud:.4f}°, Lon {longitud:.4f}° | Alt: {elevacion_m} m")
    print(f" Zona Horaria Configurada: {zona_horaria}")
    print("="*70)
    print(f" Parámetro Delta T (ΔT)        : {delta_t:.2f} s")
    print("-" * 70)
    print(f" Inicio Parcial (Contacto C1)  : {fmt_tiempos(tiempos[idx_c1])}")
    
    # Comprobar si hay totalidad
    es_total = np.any(en_eclipse_total)
    
    if es_total:
        indices_total = np.where(en_eclipse_total)[0]
        idx_c2 = indices_total[0]
        idx_c3 = indices_total[-1]
        
        duracion_seg = (tiempos[idx_c3].utc_datetime() - tiempos[idx_c2].utc_datetime()).total_seconds()
        minutos_tot = int(duracion_seg // 60)
        segundos_tot = int(duracion_seg % 60)
        
        print(f" Inicio Totalidad (Contacto C2): {fmt_tiempos(tiempos[idx_c2])}")
        print(f" Máximo del Eclipse           : {fmt_tiempos(t_max)}")
        print(f" Fin Totalidad (Contacto C3)   : {fmt_tiempos(tiempos[idx_c3])}")
    else:
        print(f" Máximo del Eclipse           : {fmt_tiempos(t_max)}")
        
    print(f" Fin Parcial (Contacto C4)     : {fmt_tiempos(tiempos[idx_c4])}")
    print("-" * 70)
    
    if es_total:
        print(f" Duración de la Totalidad      : {minutos_tot}m {segundos_tot}s")
        
    print(f" Altura del Sol (geométrica)   : {alt_geom.degrees:.2f}°")
    print(f" Refracción estimada           : +{refraccion:.2f}° (Temp: {temp_c}°C, P: {presion_mbar} mbar)")
    print(f" Altura del Sol (aparente)     : {alt_refractada:.2f}° sobre el horizonte")
    print(f" Azimut del Sol en el máximo   : {az_max.degrees:.1f}° (Oeste-Suroeste)")
    print(f" Cobertura solar máxima        : {cobertura_diametro:.1f}%")
    
    if es_total:
        print(" ESTADO                        : ¡ECLIPSE TOTAL!")
    else:
        print(" ESTADO                        : Eclipse Parcial")
    print("="*70 + "\n")

if __name__ == "__main__":
    LATITUD = ponga el valor correcto (º)
    LONGITUD = ponga el valor correcto (º)
    ELEVACION_M = ponga el valor correcto (m)
    ZONA_HORARIA = "Europe/Madrid"
    
    calcular_efemerides_eclipse(
        latitud=LATITUD, 
        longitud=LONGITUD, 
        elevacion_m=ELEVACION_M, 
        zona_horaria=ZONA_HORARIA
    )
en este caso el valor del radio del Sol vuelve a ser diferente, cosas de que sea un cuerpo gaseoso:

emplea de421, y tiene variables para cambiar la presión y la temperatura para corregir mejor la refracción:


Y seguimos esperando el modelo terraplanero, no vuelvo a repetir todo lo que tienen que incluir.


Francamente lo dudo, no le interesó lo más mínimo cuando hubo un eclipse en Argentina, pero por si ahora no llega a tiempo, tenemos otros dos los años venideros, si se pone ahora quizá consiga las predicciones del último, que es anular, de esos imposibles con una sombra cilíndrica como defiende él.
Es duro que la realidad se obstine en refutar tus afirmaciones con tanta insistencia. ¿Observar un fenómeno espectacular que podrás ver unas pocas veces al largo de la vida? Eso no importa nada, lo suyo es hacer como que no lo ves y difundir ideas erróneas...
 
Ya queda sólo una semana, y seguimos sin tener la lista terraplanera de premios, que en la Tierra esférica se pueden calcular perfectamente, esto es lo que genera ChatGPT para resolver el problema:
Código:
# eclipse_predictor_adaptativo.py
from math import asin
from skyfield.api import load,wgs84

R_SUN=695700.0
R_MOON=1737.4

LAT,LON,ALT=rellenar con los datos correspondientes
YEAR,MONTH,DAY=2026,8,12

COARSE_DT=5.0
FINE_DT=0.5
START_HOUR=16
END_HOUR=21

ts=load.timescale()
eph=load("de440s.bsp")
obs=eph["earth"]+wgs84.latlon(LAT,LON,elevation_m=ALT)
sun=eph["sun"]; moon=eph["moon"]

def sample(sec):
    h=int(sec//3600); m=int((sec%3600)//60); s=sec-h*3600-m*60
    t=ts.utc(YEAR,MONTH,DAY,h,m,s)
    sa=obs.at(t).observe(sun).apparent()
    ma=obs.at(t).observe(moon).apparent()
    d=sa.separation_from(ma).radians
    rs=asin(R_SUN/sa.distance().km)
    rm=asin(R_MOON/ma.distance().km)
    return (sec,d,rs,rm,d-(rs+rm),d-abs(rs-rm))

def cross(a,b,f):
    f1=a[f]; f2=b[f]
    return a[0]-f1*(b[0]-a[0])/(f2-f1)

def refine(a,b,field,sign):
    s=a
    prev=sample(s)
    s+=FINE_DT
    while s<=b+1e-9:
        cur=sample(s)
        if sign(prev[field],cur[field]):
            return cross(prev,cur,field)
        prev=cur
        s+=FINE_DT
    return None

coarse=[]
sec=START_HOUR*3600
while sec<=END_HOUR*3600+1e-9:
    coarse.append(sample(sec))
    sec+=COARSE_DT

imax=min(range(len(coarse)),key=lambda i:coarse[i][1])
max_time=coarse[imax][0]

c1=c2=c3=c4=None
for i in range(imax):
    if coarse[i][4]>0>=coarse[i+1][4]:
        c1=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a>0>=b);break
for i in range(imax):
    if coarse[i][5]>0>=coarse[i+1][5]:
        c2=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a>0>=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][5]<0<=coarse[i+1][5]:
        c3=refine(coarse[i][0],coarse[i+1][0],5,lambda a,b:a<0<=b);break
for i in range(imax,len(coarse)-1):
    if coarse[i][4]<0<=coarse[i+1][4]:
        c4=refine(coarse[i][0],coarse[i+1][0],4,lambda a,b:a<0<=b);break

fmt=lambda x:f"{int(x//3600):02d}:{int((x%3600)//60):02d}:{x%60:04.1f} UTC"
print("C1 ",fmt(c1));print("C2 ",fmt(c2));print("MAX",fmt(max_time));print("C3 ",fmt(c3));print("C4 ",fmt(c4))
Naturalmente hay que rellenar los datos de la localidad en la que se quiere observar el eclipse en LAT,LON,ALT, los dos primeros en grados y el último en metros (sobre el elipsoide wgs84):


Obsérvese que el radio solar es de 695700.0 km, el lunar es de 1737.4 km

y las efemérides del sistema solar las obtiene del modelo de440:

que como ya se ha explicado muchas veces es una integración numérica del modelo gravitatorio de Newton del sistema solar, con correcciones relativistas:


Ahora sólo hace falta tener la lista de premios alternativa, basada en una Tierra plana, hace falta un mapa de precisión (el equivalente a wgs84), y las coordenadas en dicho mapa de cada posible lugar de observación (el equivalente al LON,LAT,ALT), y unas efemérides del sistema solar (el equivalente a de440), aunque sólo hacen falta dos objetos, el Sol y la Luna, el resto no es imprescindible, en el modelo de Newton se ponen porque todos los objetos influyen en todos, en el modelo alternativo no tenemos ni idea de como funcionan, ese modelo debe proporcionar las trayectorias, diámetros, etc., de los objetos del modelo.
Lo tuyo es más de locutor de deportes de radio, y tu querido eclipse se verá desde el centro aproximado de la Tierra.

Ya te pusiste el sombrero de papel? Soplando una serpentina y con las gafitas podrás ver el eclipse .

Creo que ninguno de vosotros podréis llegar a ser tan incompetentes, sois peores que "lado oscuro Luna"
 
Última edición:
Seguimos, esta vez le toca a gemini:
Código:
from datetime import datetime, timezone
import zoneinfo
import numpy as np
from skyfield.api import load, wgs84

# ==============================================================================
# CONSTANTES ASTRONÓMICAS Y FÍSICAS (IAU)
# ==============================================================================
RADIO_SOL_KM = 696340.0   # Radio ecuatorial medio del Sol en kilómetros
RADIO_LUNA_KM = 1737.4    # Radio medio de la Luna en kilómetros

# Parámetros atmosféricos estándar
TEMP_ESTANDAR_C = 15.0     # Temperatura en °C
PRESION_ESTANDAR_MBAR = 1010.0 # Presión en mbar/hPa
# ==============================================================================


def calcular_refraccion_bennett(alt_grados, temp_c=TEMP_ESTANDAR_C, presion_mbar=PRESION_ESTANDAR_MBAR):
    """
    Calcula la refracción atmosférica en grados usando la fórmula de Bennett (1982) / Sæmundsson (1986).
    """
    if alt_grados <= -1.0:
        return 0.0
    
    alt = max(alt_grados, 0.0)
    cotan_argumento = np.radians(alt + 10.3 / (alt + 5.11))
    refraccion_minutos = 1.02 / np.tan(cotan_argumento)
    
    factor_tp = (presion_mbar / PRESION_ESTANDAR_MBAR) * (283.15 / (273.15 + temp_c))
    refraccion_corregida_min = refraccion_minutos * factor_tp
    
    return refraccion_corregida_min / 60.0


def calcular_efemerides_eclipse(latitud, longitud, elevacion_m=0, 
                                temp_c=TEMP_ESTANDAR_C, 
                                presion_mbar=PRESION_ESTANDAR_MBAR, 
                                zona_horaria="Europe/Madrid"):
    """
    Calcula las efemérides del eclipse solar del 12 de agosto de 2026.
    """
    print("Cargando efemérides planetarias y tablas IERS...")
    ts = load.timescale()
    eph = load('de421.bsp')
    
    sun = eph['sun']
    moon = eph['moon']
    earth = eph['earth']
    
    tz_local = zoneinfo.ZoneInfo(zona_horaria)
    observador = earth + wgs84.latlon(latitud, longitud, elevation_m=elevacion_m)
    
    # Rango de evaluación: 14:00 UTC a 21:00 UTC
    t0 = ts.utc(2026, 8, 12, 14, 0, 0)
    t1 = ts.utc(2026, 8, 12, 21, 0, 0)
    
    minutos = int((t1 - t0) * 24 * 60)
    tiempos = ts.utc(2026, 8, 12, 14, np.linspace(0, minutos, minutos * 60)) # Muestreo por segundo
    
    delta_t = tiempos[0].delta_t
    
    print("Calculando posiciones topocéntricas y contactos de totalidad...")
    pos_sol = observador.at(tiempos).observe(sun).apparent()
    pos_luna = observador.at(tiempos).observe(moon).apparent()
    
    # Separación angular geométrica entre los centros
    separaciones = pos_sol.separation_from(pos_luna).degrees
    
    # Distancias topocéntricas en km
    dist_sol_km = pos_sol.distance().km
    dist_luna_km = pos_luna.distance().km
    
    # CÁLCULO DE RADIOS APARENTES USANDO LAS CONSTANTES GLOBALES
    radio_sol_deg = np.degrees(np.arcsin(RADIO_SOL_KM / dist_sol_km))
    radio_luna_deg = np.degrees(np.arcsin(RADIO_LUNA_KM / dist_luna_km))
    
    # Umbral eclipse parcial (Suma de radios: C1 y C4)
    umbral_parcial = radio_sol_deg + radio_luna_deg
    en_eclipse_parcial = separaciones < umbral_parcial
    
    # Umbral eclipse total (Diferencia de radios: C2 y C3)
    umbral_total = radio_luna_deg - radio_sol_deg
    en_eclipse_total = separaciones < umbral_total
    
    if not np.any(en_eclipse_parcial):
        print("\n[!] En esta ubicación no se observará el eclipse el 12 de agosto de 2026.")
        return

    # Máximo eclipse
    idx_max = np.argmin(separaciones)
    t_max = tiempos[idx_max]
    
    # Contactos Parciales C1 y C4
    indices_parcial = np.where(en_eclipse_parcial)[0]
    idx_c1 = indices_parcial[0]
    idx_c4 = indices_parcial[-1]
    
    # Altura y refracción en el máximo
    alt_geom, az_max, _ = pos_sol[idx_max].altaz()
    refraccion = calcular_refraccion_bennett(alt_geom.degrees, temp_c, presion_mbar)
    alt_refractada = alt_geom.degrees + refraccion
    
    # Cobertura del diámetro solar
    d_min = separaciones[idx_max]
    r_s = radio_sol_deg[idx_max]
    r_m = radio_luna_deg[idx_max]
    cobertura_diametro = max(0.0, min(1.0, (r_s + r_m - d_min) / (2 * r_s))) * 100

    def fmt_tiempos(t_skyfield):
        dt_utc = t_skyfield.utc_datetime()
        dt_local = dt_utc.astimezone(tz_local)
        return f"{dt_local.strftime('%H:%M:%S')} (Hora local) | {dt_utc.strftime('%H:%M:%S')} UTC"

    print("\n" + "="*70)
    print(f" EFEMÉRIDES DEL ECLIPSE SOLAR - 12 DE AGOSTO DE 2026")
    print(f" Coordenadas: Lat {latitud:.4f}°, Lon {longitud:.4f}° | Alt: {elevacion_m} m")
    print(f" Zona Horaria Configurada: {zona_horaria}")
    print("="*70)
    print(f" Parámetro Delta T (ΔT)        : {delta_t:.2f} s")
    print("-" * 70)
    print(f" Inicio Parcial (Contacto C1)  : {fmt_tiempos(tiempos[idx_c1])}")
    
    # Comprobar si hay totalidad
    es_total = np.any(en_eclipse_total)
    
    if es_total:
        indices_total = np.where(en_eclipse_total)[0]
        idx_c2 = indices_total[0]
        idx_c3 = indices_total[-1]
        
        duracion_seg = (tiempos[idx_c3].utc_datetime() - tiempos[idx_c2].utc_datetime()).total_seconds()
        minutos_tot = int(duracion_seg // 60)
        segundos_tot = int(duracion_seg % 60)
        
        print(f" Inicio Totalidad (Contacto C2): {fmt_tiempos(tiempos[idx_c2])}")
        print(f" Máximo del Eclipse           : {fmt_tiempos(t_max)}")
        print(f" Fin Totalidad (Contacto C3)   : {fmt_tiempos(tiempos[idx_c3])}")
    else:
        print(f" Máximo del Eclipse           : {fmt_tiempos(t_max)}")
        
    print(f" Fin Parcial (Contacto C4)     : {fmt_tiempos(tiempos[idx_c4])}")
    print("-" * 70)
    
    if es_total:
        print(f" Duración de la Totalidad      : {minutos_tot}m {segundos_tot}s")
        
    print(f" Altura del Sol (geométrica)   : {alt_geom.degrees:.2f}°")
    print(f" Refracción estimada           : +{refraccion:.2f}° (Temp: {temp_c}°C, P: {presion_mbar} mbar)")
    print(f" Altura del Sol (aparente)     : {alt_refractada:.2f}° sobre el horizonte")
    print(f" Azimut del Sol en el máximo   : {az_max.degrees:.1f}° (Oeste-Suroeste)")
    print(f" Cobertura solar máxima        : {cobertura_diametro:.1f}%")
    
    if es_total:
        print(" ESTADO                        : ¡ECLIPSE TOTAL!")
    else:
        print(" ESTADO                        : Eclipse Parcial")
    print("="*70 + "\n")

if __name__ == "__main__":
    LATITUD = ponga el valor correcto (º)
    LONGITUD = ponga el valor correcto (º)
    ELEVACION_M = ponga el valor correcto (m)
    ZONA_HORARIA = "Europe/Madrid"
    
    calcular_efemerides_eclipse(
        latitud=LATITUD, 
        longitud=LONGITUD, 
        elevacion_m=ELEVACION_M, 
        zona_horaria=ZONA_HORARIA
    )
en este caso el valor del radio del Sol vuelve a ser diferente, cosas de que sea un cuerpo gaseoso:

emplea de421, y tiene variables para cambiar la presión y la temperatura para corregir mejor la refracción:


Y seguimos esperando el modelo terraplanero, no vuelvo a repetir todo lo que tienen que incluir.


Francamente lo dudo, no le interesó lo más mínimo cuando hubo un eclipse en Argentina, pero por si ahora no llega a tiempo, tenemos otros dos los años venideros, si se pone ahora quizá consiga las predicciones del último, que es anular, de esos imposibles con una sombra cilíndrica como defiende él.
Pobre muchopico, estás equivocado por completo jajaja

(adjunto visible para usuarios registrados)
 

Adjuntos

Archivo oculto para usuarios no registrados
Es duro que la realidad se obstine en refutar tus afirmaciones con tanta insistencia. ¿Observar un fenómeno espectacular que podrás ver unas pocas veces al largo de la vida? Eso no importa nada, lo suyo es hacer como que no lo ves y difundir ideas erróneas...
Siguen siendo fenómenos que ocurren bajo una Planicie, al Psiquiatra tendrás tú que explicarle cómo es posible "que haya gente que crea que en la Luna no se puede poner ningún pie!!", a ver qué te dice, os daréis la razón mutuamente junto con el Mayordomo de Marcus H.
 
Siguen siendo fenómenos que ocurren bajo una Planicie, al Psiquiatra tendrás tú que explicarle cómo es posible "que haya gente que crea que en la Luna no se puede poner ningún pie!!", a ver qué te dice, os daréis la razón mutuamente junto con el Mayordomo de Marcus H.

Ah sí? Explícame cómo funcionan los eclipses en Planilandia.
 
Terraplanistas el día 12.

(adjunto visible para usuarios registrados)
Te veo más con las gafitas haciendo el paripé a alguna mujer que te encuentres, podrás hacer de trilero con inane33 .

(imagen visible para usuarios registrados)

Y este mapa se trata de centrarlo y extenderlo sobre una Planicie, y entender que la Luna es un fenómeno astrológico, una influencia, y ningún sitio sólido donde se pueda poner ningún pie, y el Sol aun astro más cercano, Local de una Tierra mucho más extensa.
 
Te veo más con las gafitas haciendo el paripé a alguna mujer que te encuentres, podrás hacer de trilero con inane33 .

(imagen visible para usuarios registrados)

Y este mapa se trata de centrarlo y extenderlo sobre una Planicie, y entender que la Luna es un fenómeno astrológico, una influencia, y ningún sitio sólido donde se pueda poner ningún pie, y el Sol aun astro más cercano, Local de una Tierra mucho más extensa.
Que no sabes explicar nada, vamos. De hecho, eres incapaz de redactar un texto con un mínimo de coherencia interna.
 
Última edición:
¿Puedes explicarnos de qué manera...

1. La existencia de océanos abusa la dinámica de fluidos.
2. La existencia de atmósfera abusa la Segunda Ley de la Termodinámica.

...o estás copiando y pegando afirmaciones sin saber ni qué quieren decir?
Eres tan torpe que no sabes ni formular preguntas sin usar falacias.

Lo que abusa la mecánica de fluidos es el agua pegada a la superficie de una esfera en rotación.

Lo que abusa la Segunda Ley de la Termodinámica es mantener una atmósfera estable en un sistema abierto junto a un vacuo infinito.

¿Te crees que tus burdos y ridículos intentos de tergiversar funcionan para convencer a alguien de nada?
Es justamente lo contrario, lo único que conseguís es hacer mas terraplanistas.
 
Que no sabes explicar nada, vamos. De hecho, eres incapaz de redactar un texto con un mínimo de coherencia interna.
Y tú de comer sin tener que escribir con la boca llena, troll. Se te llenará el PC de grasa.

Pretendes dar mil vueltas a lo que solo es un Dato Técnico ya comprobado a simple vista, reconocido en ingeniería de misiles, y ya visto desde las Islas Canarias o Baleares.

Y usa una servilleta de vez en cuando
 
Y tú de comer sin tener que escribir con la boca llena, troll. Se te llenará el PC de grasa.

Pretendes dar mil vueltas a lo que solo es un Dato Técnico ya comprobado a simple vista, reconocido en ingeniería de misiles, y ya visto desde las Islas Canarias o Baleares.

Y usa una servilleta de vez en cuando
Mucho hablar pero de explicar cómo funcionan los eclipses en Planilandia, nada de nada.
 
Si no te lo vas a creer para qué te lo tenemos que explicar ......eres un provocador .....vete a navegar por el Nilo cuesta arriba....
Ahora lloriqueas porque os provoco? No os provoco hombre, sino que directamente me río de vuestras caras. Sois personas que no entendéis siquiera porque en un mapa arriba no significa cuesta arriba y pretendéis daros de despiertos investigadores de la verdad de la planicie. Es gracioso.
 
Ahora lloriqueas porque os provoco? No os provoco hombre, sino que directamente me río de vuestras caras. Sois personas que no entendéis siquiera porque en un mapa arriba no significa cuesta arriba y pretendéis daros de despiertos investigadores de la verdad de la planicie. Es gracioso.
Y tú deja el tema que te viene muy grande
 

Estadísticas del foro

Temas
2.055.827
Mensajes
58.329.857
Miembros
190.984
Último miembro
Salguero87

El blog de burbuja.info

Volver