Neue Seite: Sonnensystem-Baryzentrum
Zeigt die Bewegung des gemeinsamen Schwerpunkts von Sonne und Planeten von 2006 bis 2050 als animierte Canvas-Darstellung. Vergangener Pfad in Cyan, Prognose gestrichelt in Gold. Planetenbeiträge aller 8 Planeten (gewichtet nach Masse × Abstand) als Balkendiagramm. Berechnung via astronomy-engine (Python), neuer API-Action `barycenter`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -138,5 +138,6 @@ function manageablePublicPages(): array
|
||||
'satellitenhimmel.php' => 'Satellitenhimmel',
|
||||
'asteroid_temp.php' => 'Asteroid-Temperatur',
|
||||
'universesandbox.php' => 'Universe Sandbox',
|
||||
'barycenter.php' => 'Baryzentrum',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,498 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
session_start();
|
||||
|
||||
require_once __DIR__ . '/python_api.php';
|
||||
|
||||
$result = runPythonApi('barycenter', ['20', '12', '24']);
|
||||
|
||||
|
||||
require __DIR__ . '/header.php';
|
||||
?>
|
||||
|
||||
<style>
|
||||
.bc-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 1.5rem;
|
||||
align-items: start;
|
||||
}
|
||||
@media (max-width: 860px) {
|
||||
.bc-grid { grid-template-columns: 1fr; }
|
||||
}
|
||||
|
||||
#bc-canvas-wrap {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
aspect-ratio: 1;
|
||||
background: #04060e;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
overflow: hidden;
|
||||
}
|
||||
#bc-canvas {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.bc-legend {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem 1rem;
|
||||
margin-top: 0.75rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
.bc-legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
.bc-legend-dot {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 50%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.bc-stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.2rem;
|
||||
padding: 0.75rem 1rem;
|
||||
background: var(--bg-card2);
|
||||
border-radius: var(--radius);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
.bc-stat-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--text-dim);
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.bc-stat-value {
|
||||
font-size: 1.2rem;
|
||||
color: var(--gold-pale);
|
||||
font-weight: 600;
|
||||
}
|
||||
.bc-stat-sub {
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
.bc-stats-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.bc-planet-bar-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.bc-planet-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
.bc-planet-name {
|
||||
width: 70px;
|
||||
flex-shrink: 0;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
.bc-planet-bar-bg {
|
||||
flex: 1;
|
||||
height: 8px;
|
||||
background: rgba(255,255,255,0.06);
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
}
|
||||
.bc-planet-bar {
|
||||
height: 100%;
|
||||
border-radius: 4px;
|
||||
transition: width 0.8s ease;
|
||||
}
|
||||
.bc-planet-val {
|
||||
width: 50px;
|
||||
text-align: right;
|
||||
color: var(--text-dim);
|
||||
font-size: 0.78rem;
|
||||
}
|
||||
|
||||
.bc-anim-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.75rem;
|
||||
margin-top: 0.75rem;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.bc-year-label {
|
||||
font-size: 0.85rem;
|
||||
color: var(--gold-pale);
|
||||
min-width: 60px;
|
||||
}
|
||||
input[type=range].bc-slider {
|
||||
flex: 1;
|
||||
min-width: 120px;
|
||||
accent-color: var(--gold);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.bc-inside-badge {
|
||||
display: inline-block;
|
||||
padding: 0.15em 0.6em;
|
||||
border-radius: 20px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
.bc-inside-badge.inside {
|
||||
background: rgba(79,195,216,0.2);
|
||||
color: var(--cyan);
|
||||
border: 1px solid rgba(79,195,216,0.4);
|
||||
}
|
||||
.bc-inside-badge.outside {
|
||||
background: rgba(201,168,76,0.15);
|
||||
color: var(--gold);
|
||||
border: 1px solid var(--border);
|
||||
}
|
||||
</style>
|
||||
|
||||
<?php if (!$result['ok']): ?>
|
||||
<div class="card">
|
||||
<p class="msg-error"><li>Fehler beim Berechnen: <?= htmlspecialchars($result['error'] ?? 'Unbekannter Fehler', ENT_QUOTES, 'UTF-8') ?></li></p>
|
||||
</div>
|
||||
<?php else:
|
||||
$cur = $result['data']['current'];
|
||||
$distSR = $cur['dist_solar_radii'];
|
||||
$inside = $cur['inside_sun'];
|
||||
$contributions = $result['data']['contributions'];
|
||||
?>
|
||||
|
||||
<div class="bc-stats-row">
|
||||
<div class="bc-stat">
|
||||
<span class="bc-stat-label">Abstand vom Sonnenmittelpunkt</span>
|
||||
<span class="bc-stat-value"><?= number_format($distSR, 3, ',', '') ?> R☉</span>
|
||||
<span class="bc-stat-sub"><?= number_format($cur['dist_au'], 5, ',', '') ?> AU</span>
|
||||
</div>
|
||||
<div class="bc-stat">
|
||||
<span class="bc-stat-label">Position</span>
|
||||
<span class="bc-stat-value">
|
||||
<span class="bc-inside-badge <?= $inside ? 'inside' : 'outside' ?>">
|
||||
<?= $inside ? 'Innerhalb der Sonne' : 'Außerhalb der Sonne' ?>
|
||||
</span>
|
||||
</span>
|
||||
<span class="bc-stat-sub">Stand: <?= htmlspecialchars($cur['date_utc'], ENT_QUOTES, 'UTF-8') ?></span>
|
||||
</div>
|
||||
<div class="bc-stat">
|
||||
<span class="bc-stat-label">Maximum (2006–2050)</span>
|
||||
<span class="bc-stat-value"><?= number_format($result['data']['max_dist_solar_radii'], 3, ',', '') ?> R☉</span>
|
||||
<span class="bc-stat-sub">Maximaler Abstand im Zeitraum</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bc-grid">
|
||||
<div>
|
||||
<div class="card">
|
||||
<h2>Bahnkurve des Baryzentrums</h2>
|
||||
<div id="bc-canvas-wrap">
|
||||
<canvas id="bc-canvas"></canvas>
|
||||
</div>
|
||||
<div class="bc-legend">
|
||||
<span class="bc-legend-item"><span class="bc-legend-dot" style="background:#f5c842"></span> Sonne</span>
|
||||
<span class="bc-legend-item"><span class="bc-legend-dot" style="background:rgba(255,255,255,0.25);border:1px dashed #666"></span> Sonnenoberfläche</span>
|
||||
<span class="bc-legend-item"><span class="bc-legend-dot" style="background:#4fc3d8"></span> Baryzentrum (Vergangenheit)</span>
|
||||
<span class="bc-legend-item"><span class="bc-legend-dot" style="background:#c9a84c;opacity:0.7"></span> Baryzentrum (Prognose)</span>
|
||||
<span class="bc-legend-item"><span class="bc-legend-dot" style="background:#ff6060"></span> Baryzentrum (heute)</span>
|
||||
</div>
|
||||
<div class="bc-anim-controls">
|
||||
<button id="bc-play" class="btn btn-sm btn-secondary">▶ Abspielen</button>
|
||||
<input type="range" class="bc-slider" id="bc-slider" min="0" max="240" value="240" step="1">
|
||||
<span class="bc-year-label" id="bc-year-label">heute</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="card">
|
||||
<h2>Erklärung</h2>
|
||||
<p style="font-size:0.9rem;color:var(--text-dim);line-height:1.6">
|
||||
Das <strong style="color:var(--text)">Baryzentrum</strong> ist der gemeinsame Schwerpunkt des gesamten Sonnensystems.
|
||||
Die Sonne kreist – wie alle Planeten – um diesen Punkt, nicht umgekehrt.
|
||||
</p>
|
||||
<p style="font-size:0.9rem;color:var(--text-dim);line-height:1.6;margin-top:0.75rem">
|
||||
Der Schwerpunkt liegt meist nahe der Sonnenoberfläche oder knapp darüber
|
||||
(ca. 1 Sonnenradius Abstand), selten direkt im Sonnenmittelpunkt.
|
||||
<strong style="color:var(--gold)">Jupiter</strong> hat den bei weitem größten Einfluss.
|
||||
</p>
|
||||
<p style="font-size:0.9rem;color:var(--text-dim);line-height:1.6;margin-top:0.75rem">
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="card" style="margin-top:1.5rem">
|
||||
<h2>Planetenbeiträge (heliozentrisch)</h2>
|
||||
<div class="bc-planet-bar-wrap">
|
||||
<?php
|
||||
$planetColors = [
|
||||
'Merkur' => '#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';
|
||||
?>
|
||||
<div class="bc-planet-row">
|
||||
<span class="bc-planet-name"><?= htmlspecialchars($p['name'], ENT_QUOTES, 'UTF-8') ?></span>
|
||||
<div class="bc-planet-bar-bg">
|
||||
<div class="bc-planet-bar" style="width:<?= $pct ?>%;background:<?= $color ?>"></div>
|
||||
</div>
|
||||
<span class="bc-planet-val" title="<?= number_format($p['helio_dist_au'], 2, ',', '.') ?> AU Abstand"><?= $p['ssb_contribution_au'] >= 0.0001 ? number_format($p['ssb_contribution_au'], 4, ',', '') : '< 0,0001' ?> AU</span>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<p style="font-size:0.78rem;color:var(--text-dim);margin-top:0.9rem">
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
const SERIES = <?= json_encode($result['data']['series'], JSON_UNESCAPED_UNICODE) ?>;
|
||||
const DATES = <?= json_encode($result['data']['series_dates'], JSON_UNESCAPED_UNICODE) ?>;
|
||||
const CUR = <?= json_encode($cur, JSON_UNESCAPED_UNICODE) ?>;
|
||||
const NOW_INDEX = <?= (int)$result['data']['now_index'] ?>;
|
||||
const SUN_RADIUS_AU = <?= json_encode($result['data']['sun_radius_au']) ?>;
|
||||
const MAX_DIST_SR = <?= json_encode($result['data']['max_dist_solar_radii']) ?>;
|
||||
|
||||
const canvas = document.getElementById('bc-canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
let visibleUpTo = NOW_INDEX; // startet bei "heute"
|
||||
let animPlaying = false;
|
||||
let animFrame = null;
|
||||
let animIndex = 0;
|
||||
|
||||
const slider = document.getElementById('bc-slider');
|
||||
const playBtn = document.getElementById('bc-play');
|
||||
const yearLabel = document.getElementById('bc-year-label');
|
||||
|
||||
slider.max = SERIES.length - 1;
|
||||
slider.value = NOW_INDEX;
|
||||
|
||||
function formatDate(yearFrac) {
|
||||
const y = Math.floor(yearFrac);
|
||||
const m = Math.round((yearFrac - y) * 12) + 1;
|
||||
return y + '-' + String(m).padStart(2, '0');
|
||||
}
|
||||
|
||||
function resize() {
|
||||
const wrap = document.getElementById('bc-canvas-wrap');
|
||||
const size = wrap.clientWidth;
|
||||
canvas.width = size;
|
||||
canvas.height = size;
|
||||
draw();
|
||||
}
|
||||
|
||||
function draw() {
|
||||
const W = canvas.width;
|
||||
const H = canvas.height;
|
||||
const cx = W / 2;
|
||||
const cy = H / 2;
|
||||
|
||||
// Scale: fit MAX_DIST_SR * 1.3 solar radii into half-canvas
|
||||
const scale = (W * 0.42) / (MAX_DIST_SR * 1.15);
|
||||
const sunRadiusPx = scale; // 1 solar radius → scale px
|
||||
|
||||
ctx.clearRect(0, 0, W, H);
|
||||
|
||||
// Background grid rings
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.05)';
|
||||
ctx.lineWidth = 1;
|
||||
for (let r = 1; r <= Math.ceil(MAX_DIST_SR * 1.2); r++) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, r * scale, 0, Math.PI * 2);
|
||||
ctx.stroke();
|
||||
}
|
||||
// Ring labels
|
||||
ctx.font = '10px sans-serif';
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.25)';
|
||||
ctx.textAlign = 'left';
|
||||
for (let r = 1; r <= Math.ceil(MAX_DIST_SR * 1.2); r++) {
|
||||
ctx.fillText(r + ' R☉', cx + r * scale + 3, cy - 3);
|
||||
}
|
||||
|
||||
// Sun glow
|
||||
const glow = ctx.createRadialGradient(cx, cy, 0, cx, cy, sunRadiusPx * 2.5);
|
||||
glow.addColorStop(0, 'rgba(255, 220, 80, 0.6)');
|
||||
glow.addColorStop(0.4, 'rgba(255, 180, 40, 0.25)');
|
||||
glow.addColorStop(1, 'rgba(255, 140, 0, 0)');
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, sunRadiusPx * 2.5, 0, Math.PI * 2);
|
||||
ctx.fillStyle = glow;
|
||||
ctx.fill();
|
||||
|
||||
// Sun disk
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, sunRadiusPx, 0, Math.PI * 2);
|
||||
ctx.fillStyle = '#f5c842';
|
||||
ctx.fill();
|
||||
|
||||
// Sun surface dashed circle
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, sunRadiusPx, 0, Math.PI * 2);
|
||||
ctx.setLineDash([4, 4]);
|
||||
ctx.strokeStyle = 'rgba(255,255,255,0.2)';
|
||||
ctx.lineWidth = 1;
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
|
||||
// Barycenter path up to visibleUpTo
|
||||
const end = Math.min(visibleUpTo, SERIES.length - 1);
|
||||
|
||||
// Vergangener Pfad (bis NOW_INDEX) — cyan
|
||||
const pastEnd = Math.min(end, NOW_INDEX);
|
||||
if (pastEnd >= 1) {
|
||||
ctx.beginPath();
|
||||
const p0 = SERIES[0];
|
||||
ctx.moveTo(cx + p0.x / SUN_RADIUS_AU * scale, cy - p0.y / SUN_RADIUS_AU * scale);
|
||||
for (let i = 1; i <= pastEnd; i++) {
|
||||
const p = SERIES[i];
|
||||
ctx.lineTo(cx + p.x / SUN_RADIUS_AU * scale, cy - p.y / SUN_RADIUS_AU * scale);
|
||||
}
|
||||
ctx.strokeStyle = 'rgba(79, 195, 216, 0.55)';
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.setLineDash([]);
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
// Zukünftiger Pfad (ab NOW_INDEX) — gold gedimmt, gestrichelt
|
||||
if (end > NOW_INDEX) {
|
||||
ctx.beginPath();
|
||||
const pn = SERIES[NOW_INDEX];
|
||||
ctx.moveTo(cx + pn.x / SUN_RADIUS_AU * scale, cy - pn.y / SUN_RADIUS_AU * scale);
|
||||
for (let i = NOW_INDEX + 1; i <= end; i++) {
|
||||
const p = SERIES[i];
|
||||
ctx.lineTo(cx + p.x / SUN_RADIUS_AU * scale, cy - p.y / SUN_RADIUS_AU * scale);
|
||||
}
|
||||
ctx.strokeStyle = 'rgba(201, 168, 76, 0.45)';
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.setLineDash([5, 4]);
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
}
|
||||
|
||||
// Current SSB dot
|
||||
const pCur = SERIES[end];
|
||||
const px = cx + pCur.x / SUN_RADIUS_AU * scale;
|
||||
const py = cy - pCur.y / SUN_RADIUS_AU * scale;
|
||||
|
||||
// Dot glow
|
||||
const dotGlow = ctx.createRadialGradient(px, py, 0, px, py, 10);
|
||||
dotGlow.addColorStop(0, 'rgba(255, 80, 80, 0.8)');
|
||||
dotGlow.addColorStop(1, 'rgba(255, 80, 80, 0)');
|
||||
ctx.beginPath();
|
||||
ctx.arc(px, py, 10, 0, Math.PI * 2);
|
||||
ctx.fillStyle = dotGlow;
|
||||
ctx.fill();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(px, py, 4, 0, Math.PI * 2);
|
||||
ctx.fillStyle = '#ff6060';
|
||||
ctx.fill();
|
||||
|
||||
// Distance label
|
||||
ctx.font = '11px sans-serif';
|
||||
ctx.fillStyle = 'rgba(255,255,255,0.65)';
|
||||
ctx.textAlign = 'left';
|
||||
ctx.fillText(pCur.d.toFixed(3) + ' R☉', px + 8, py - 6);
|
||||
}
|
||||
|
||||
function updateLabel() {
|
||||
const idx = parseInt(slider.value, 10);
|
||||
if (idx === NOW_INDEX) {
|
||||
yearLabel.textContent = 'heute';
|
||||
} else {
|
||||
yearLabel.textContent = formatDate(DATES[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
slider.addEventListener('input', () => {
|
||||
visibleUpTo = parseInt(slider.value, 10);
|
||||
updateLabel();
|
||||
draw();
|
||||
if (animPlaying) stopAnim();
|
||||
});
|
||||
|
||||
function stopAnim() {
|
||||
animPlaying = false;
|
||||
playBtn.textContent = '▶ Abspielen';
|
||||
if (animFrame) { cancelAnimationFrame(animFrame); animFrame = null; }
|
||||
}
|
||||
|
||||
function startAnim() {
|
||||
animPlaying = true;
|
||||
playBtn.textContent = '⏸ Pause';
|
||||
// Start from beginning if at or near end
|
||||
if (visibleUpTo >= SERIES.length - 1) {
|
||||
visibleUpTo = 0;
|
||||
animIndex = 0;
|
||||
} else {
|
||||
animIndex = visibleUpTo;
|
||||
}
|
||||
|
||||
let last = null;
|
||||
const msPerStep = 30; // ~33 fps, 1 step per frame
|
||||
function step(ts) {
|
||||
if (!animPlaying) return;
|
||||
if (last === null || ts - last >= msPerStep) {
|
||||
last = ts;
|
||||
animIndex++;
|
||||
if (animIndex >= SERIES.length) {
|
||||
animIndex = SERIES.length - 1;
|
||||
visibleUpTo = animIndex;
|
||||
slider.value = animIndex;
|
||||
updateLabel();
|
||||
draw();
|
||||
stopAnim();
|
||||
return;
|
||||
}
|
||||
visibleUpTo = animIndex;
|
||||
slider.value = animIndex;
|
||||
updateLabel();
|
||||
draw();
|
||||
}
|
||||
animFrame = requestAnimationFrame(step);
|
||||
}
|
||||
animFrame = requestAnimationFrame(step);
|
||||
}
|
||||
|
||||
playBtn.addEventListener('click', () => {
|
||||
if (animPlaying) { stopAnim(); } else { startAnim(); }
|
||||
});
|
||||
|
||||
window.addEventListener('resize', resize);
|
||||
resize();
|
||||
updateLabel();
|
||||
})();
|
||||
</script>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<?php require __DIR__ . '/footer.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'],
|
||||
|
||||
@@ -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"]})
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user