diff --git a/public/auth_helpers.php b/public/auth_helpers.php
index 15c706c..a537259 100644
--- a/public/auth_helpers.php
+++ b/public/auth_helpers.php
@@ -138,5 +138,6 @@ function manageablePublicPages(): array
'satellitenhimmel.php' => 'Satellitenhimmel',
'asteroid_temp.php' => 'Asteroid-Temperatur',
'universesandbox.php' => 'Universe Sandbox',
+ 'barycenter.php' => 'Baryzentrum',
];
}
diff --git a/public/barycenter.php b/public/barycenter.php
new file mode 100644
index 0000000..888ce6b
--- /dev/null
+++ b/public/barycenter.php
@@ -0,0 +1,498 @@
+
+
+
+
+
+
+
Fehler beim Berechnen: = htmlspecialchars($result['error'] ?? 'Unbekannter Fehler', ENT_QUOTES, 'UTF-8') ?>
+
+
+
+
+
+ Abstand vom Sonnenmittelpunkt
+ = number_format($distSR, 3, ',', '') ?> R☉
+ = number_format($cur['dist_au'], 5, ',', '') ?> AU
+
+
+ Position
+
+
+ = $inside ? 'Innerhalb der Sonne' : 'Außerhalb der Sonne' ?>
+
+
+ Stand: = htmlspecialchars($cur['date_utc'], ENT_QUOTES, 'UTF-8') ?>
+
+
+ Maximum (2006–2050)
+ = number_format($result['data']['max_dist_solar_radii'], 3, ',', '') ?> R☉
+ Maximaler Abstand im Zeitraum
+
+
+
+
+
+
+
Bahnkurve des Baryzentrums
+
+
+
+
+ Sonne
+ Sonnenoberfläche
+ Baryzentrum (Vergangenheit)
+ Baryzentrum (Prognose)
+ Baryzentrum (heute)
+
+
+ ▶ Abspielen
+
+ heute
+
+
+
+
+
+
Erklärung
+
+ Das Baryzentrum ist der gemeinsame Schwerpunkt des gesamten Sonnensystems.
+ Die Sonne kreist – wie alle Planeten – um diesen Punkt, nicht umgekehrt.
+
+
+ Der Schwerpunkt liegt meist nahe der Sonnenoberfläche oder knapp darüber
+ (ca. 1 Sonnenradius Abstand), selten direkt im Sonnenmittelpunkt.
+ Jupiter hat den bei weitem größten Einfluss.
+
+
+ Der dargestellte Zeitraum reicht von 2006 bis 2050 (Vergangenheit + Prognose).
+ Die Bahn folgt keinem einfachen Kreis –
+ die Überlagerung der Planetenumläufe erzeugt eine komplexe Spirale.
+
+
+
+
+
Planetenbeiträge (heliozentrisch)
+
+ '#b0b0b0',
+ 'Venus' => '#e8c97a',
+ 'Erde' => '#4fc3d8',
+ 'Mars' => '#e05050',
+ 'Jupiter' => '#c9a84c',
+ 'Saturn' => '#d4a96a',
+ 'Uranus' => '#7fd4e8',
+ 'Neptun' => '#6a8fd8',
+ ];
+ $maxContrib = max(array_column($contributions, 'ssb_contribution_au'));
+ foreach ($contributions as $p):
+ $pct = $maxContrib > 0 ? round($p['ssb_contribution_au'] / $maxContrib * 100, 1) : 0;
+ $color = $planetColors[$p['name']] ?? '#888';
+ ?>
+
+
= htmlspecialchars($p['name'], ENT_QUOTES, 'UTF-8') ?>
+
+
= $p['ssb_contribution_au'] >= 0.0001 ? number_format($p['ssb_contribution_au'], 4, ',', '') : '< 0,0001' ?> AU
+
+
+
+
+ Balken zeigen den gewichteten Beitrag zum SSB-Offset (Masse × Abstand).
+ Jupiter dominiert mit ~71 % der gesamten Planetenmasse. Die inneren Planeten
+ (Merkur bis Mars) tragen zusammen weniger als 0,1 % bei.
+
+
+
+
+
+
+
+
+
+
diff --git a/public/header.php b/public/header.php
index a06cabf..f0c66e8 100644
--- a/public/header.php
+++ b/public/header.php
@@ -154,6 +154,7 @@ $menuGroups = [
['href' => 'planetensichtbarkeit.php', 'label' => 'Planetensichtbarkeit'],
['href' => 'ephemeriden.php', 'label' => 'Ephemeriden'],
['href' => 'solarsystem.php', 'label' => 'Sonnensystem'],
+ ['href' => 'barycenter.php', 'label' => 'Baryzentrum'],
['href' => 'mars.php', 'label' => 'Mars'],
['href' => 'jupitersystem.php', 'label' => 'Jupitersystem'],
['href' => 'asteroid_temp.php', 'label' => 'Asteroid-Temperatur'],
diff --git a/public/py/api.py b/public/py/api.py
index 4a44e0b..50d9a28 100644
--- a/public/py/api.py
+++ b/public/py/api.py
@@ -5505,6 +5505,122 @@ def action_satellite_passes(args: list[str]) -> dict:
}
+_SUN_RADIUS_AU = 0.00465047 # 1 Sonnenradius in AU
+
+
+def action_barycenter(args: list[str]) -> dict:
+ """Berechnet SSB-Position relativ zur Sonne: aktuell, Zeitreihe, Planetenbeiträge."""
+ # Argumente: years_back, steps_per_year, years_forward
+ years_back = int(args[0]) if len(args) > 0 and args[0].isdigit() else 20
+ steps_per_year = int(args[1]) if len(args) > 1 and args[1].isdigit() else 12
+ years_forward = int(args[2]) if len(args) > 2 and args[2].isdigit() else 0
+ years_back = max(1, min(years_back, 100))
+ steps_per_year = max(4, min(steps_per_year, 52))
+ years_forward = max(0, min(years_forward, 100))
+
+ now = datetime.now(timezone.utc)
+ now_time = dt_to_time(now)
+
+ # -- Aktuelle Position --
+ sun_state = astronomy.BaryState(astronomy.Body.Sun, now_time)
+ # BaryState(Sun) = Position der Sonne relativ zum SSB → negieren = SSB relativ zur Sonne
+ cur_x = -sun_state.x
+ cur_y = -sun_state.y
+ cur_dist_au = math.hypot(cur_x, cur_y, -sun_state.z)
+ cur_dist_sr = cur_dist_au / _SUN_RADIUS_AU
+
+ # -- Zeitreihe --
+ total_steps = (years_back + years_forward) * steps_per_year
+ days_per_step = 365.25 / steps_per_year
+ start_jd = now_time.tt - years_back * 365.25
+ series = []
+ max_dist_au = 0.0
+ for i in range(total_steps + 1):
+ t = astronomy.Time(start_jd + i * days_per_step)
+ s = astronomy.BaryState(astronomy.Body.Sun, t)
+ tx, ty = -s.x, -s.y
+ d = math.hypot(tx, ty, -s.z)
+ if d > max_dist_au:
+ max_dist_au = d
+ dt_utc = datetime(2000, 1, 1, 12, tzinfo=timezone.utc) + timedelta(days=t.tt - 0.0)
+ # Epoche J2000.0 = 2000-01-01 12:00 TT ≈ UTC (Differenz <1 min hier vernachlässigt)
+ series.append({"x": round(tx, 6), "y": round(ty, 6), "d": round(d / _SUN_RADIUS_AU, 3)})
+
+ # Zeitstempel für Animationslabel (nur Jahr.Monat reicht)
+ series_dates = []
+ for i in range(total_steps + 1):
+ t_days = start_jd + i * days_per_step
+ # Grobe Umrechnung J2000-TT → Jahr
+ year_frac = 2000.0 + (t_days / 365.25)
+ series_dates.append(round(year_frac, 3))
+
+ # -- Planetenmassen (GM relativ zur Sonne = 1) für gewichteten Beitrag --
+ # Quellen: IAU 2012 / astronomy-engine Konstanten
+ _PLANET_MASS_FRACTION = {
+ astronomy.Body.Mercury: 1.6601e-7,
+ astronomy.Body.Venus: 2.4478e-6,
+ astronomy.Body.Earth: 3.0034e-6, # inkl. Mond
+ astronomy.Body.Mars: 3.2272e-7,
+ astronomy.Body.Jupiter: 9.5479e-4,
+ astronomy.Body.Saturn: 2.8589e-4,
+ astronomy.Body.Uranus: 4.3662e-5,
+ astronomy.Body.Neptune: 5.1514e-5,
+ }
+
+ contrib_bodies = [
+ (astronomy.Body.Mercury, "Merkur"),
+ (astronomy.Body.Venus, "Venus"),
+ (astronomy.Body.Earth, "Erde"),
+ (astronomy.Body.Mars, "Mars"),
+ (astronomy.Body.Jupiter, "Jupiter"),
+ (astronomy.Body.Saturn, "Saturn"),
+ (astronomy.Body.Uranus, "Uranus"),
+ (astronomy.Body.Neptune, "Neptun"),
+ ]
+ contributions = []
+ for body, name in contrib_bodies:
+ s = astronomy.BaryState(body, now_time)
+ hx = s.x - sun_state.x
+ hy = s.y - sun_state.y
+ hz = s.z - sun_state.z
+ helio_dist = math.hypot(hx, hy, hz)
+ bary_dist = math.hypot(s.x, s.y, s.z)
+ mass_frac = _PLANET_MASS_FRACTION.get(body, 0.0)
+ # Beitrag zum SSB-Offset = Masse × heliozentrischer Abstand (in AU)
+ ssb_contribution_au = mass_frac * helio_dist
+ contributions.append({
+ "name": name,
+ "helio_dist_au": round(helio_dist, 4),
+ "bary_dist_au": round(bary_dist, 4),
+ "bary_x": round(s.x, 6),
+ "bary_y": round(s.y, 6),
+ "mass_fraction": mass_frac,
+ "ssb_contribution_au": round(ssb_contribution_au, 8),
+ })
+
+ now_index = years_back * steps_per_year
+
+ return {
+ "ok": True,
+ "current": {
+ "x": round(cur_x, 6),
+ "y": round(cur_y, 6),
+ "dist_au": round(cur_dist_au, 6),
+ "dist_solar_radii": round(cur_dist_sr, 4),
+ "inside_sun": cur_dist_sr <= 1.0,
+ "date_utc": now.strftime("%Y-%m-%dT%H:%M:%SZ"),
+ },
+ "series": series,
+ "series_dates": series_dates,
+ "now_index": now_index,
+ "max_dist_solar_radii": round(max_dist_au / _SUN_RADIUS_AU, 3),
+ "sun_radius_au": _SUN_RADIUS_AU,
+ "contributions": contributions,
+ "years_back": years_back,
+ "years_forward": years_forward,
+ }
+
+
def main() -> None:
if len(sys.argv) < 2:
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "astronomical_conversions", "comet_brightnesses", "favorite_comet_events_for_month", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "planet_ephemeris", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "golden_gate_of_ecliptic_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "moon_star_occultations_for_month"]})
@@ -5687,6 +5803,11 @@ def main() -> None:
print(json.dumps(result, ensure_ascii=True))
return
+ if action == "barycenter":
+ result = action_barycenter(args)
+ print(json.dumps(result, ensure_ascii=True))
+ return
+
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "solar_longitude_to_datetime", "current_solar_longitude", "astronomical_conversions", "comet_brightnesses", "favorite_comet_events_for_month", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "planet_ephemeris", "planet_visibility_chart", "month_sky_context", "moon_phases_for_month", "golden_handle_for_month", "season_changes_for_month", "time_changes_for_month", "moon_planet_approaches", "moon_deep_sky_approaches_for_month", "planet_bright_star_approaches_for_month", "golden_gate_of_ecliptic_for_month", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "venus_peak_magnitude_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "jupiter_moons_one_side_for_month", "mercury_good_visibility_for_month", "planet_parades_for_month", "planet_constellation_changes_for_month", "moon_star_occultations_for_month"]})