Merge branch 'main' of https://github.com/Eskimue/skyview.astronomiemuseum.de
This commit is contained in:
@@ -76,6 +76,10 @@
|
|||||||
"label": "Sternenhimmel",
|
"label": "Sternenhimmel",
|
||||||
"menu_group": "Himmel & Planeten"
|
"menu_group": "Himmel & Planeten"
|
||||||
},
|
},
|
||||||
|
"drehbare_sternkarte.php": {
|
||||||
|
"label": "Drehbare Sternkarte",
|
||||||
|
"menu_group": "Himmel & Planeten"
|
||||||
|
},
|
||||||
"meteorshowers.php": {
|
"meteorshowers.php": {
|
||||||
"label": "Meteorstroeme",
|
"label": "Meteorstroeme",
|
||||||
"menu_group": "Himmel & Planeten"
|
"menu_group": "Himmel & Planeten"
|
||||||
@@ -132,6 +136,7 @@
|
|||||||
"jupitersystem.php",
|
"jupitersystem.php",
|
||||||
"tagbogen.php",
|
"tagbogen.php",
|
||||||
"sternenhimmel.php",
|
"sternenhimmel.php",
|
||||||
|
"drehbare_sternkarte.php",
|
||||||
"meteorshowers.php",
|
"meteorshowers.php",
|
||||||
"geocron/index.php",
|
"geocron/index.php",
|
||||||
"geocron3d.php"
|
"geocron3d.php"
|
||||||
|
|||||||
@@ -123,6 +123,7 @@ function manageablePublicPages(): array
|
|||||||
'jupitersystem.php' => 'Jupitersystem',
|
'jupitersystem.php' => 'Jupitersystem',
|
||||||
'tagbogen.php' => 'Tagbogen',
|
'tagbogen.php' => 'Tagbogen',
|
||||||
'sternenhimmel.php' => 'Sternenhimmel',
|
'sternenhimmel.php' => 'Sternenhimmel',
|
||||||
|
'drehbare_sternkarte.php' => 'Drehbare Sternkarte',
|
||||||
'meteorshowers.php' => 'Meteorströme',
|
'meteorshowers.php' => 'Meteorströme',
|
||||||
'geocron/index.php' => 'Geocron',
|
'geocron/index.php' => 'Geocron',
|
||||||
'geocron3d.php' => 'Geocron 3D',
|
'geocron3d.php' => 'Geocron 3D',
|
||||||
|
|||||||
@@ -653,7 +653,7 @@ nav a.nav-logout:hover {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(100% + 0.8rem);
|
top: calc(100% + 0.8rem);
|
||||||
right: 0;
|
right: 0;
|
||||||
width: 480px;
|
width: 620px;
|
||||||
max-width: 96vw;
|
max-width: 96vw;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+36
-25
@@ -138,36 +138,47 @@ if ($loggedIn && isset($_SESSION['user_id']) && $pdoHeader !== null) {
|
|||||||
|
|
||||||
$menuGroups = [
|
$menuGroups = [
|
||||||
[
|
[
|
||||||
'title' => 'Himmel & Planeten',
|
'title' => 'Mond & Finsternisse',
|
||||||
'links' => [
|
'links' => [
|
||||||
['href' => 'moonphase.php', 'label' => 'Mondphase'],
|
['href' => 'moonphase.php', 'label' => 'Mondphase'],
|
||||||
['href' => 'moonyear.php', 'label' => 'Mondphasen-Jahresübersicht'],
|
['href' => 'moonyear.php', 'label' => 'Mondphasen-Jahresübersicht'],
|
||||||
['href' => 'planetensichtbarkeit.php', 'label' => 'Planetensichtbarkeit'],
|
['href' => 'mondfinsternis.php', 'label' => 'Mondfinsternis'],
|
||||||
['href' => 'ephemeriden.php', 'label' => 'Ephemeriden'],
|
['href' => 'sonnenfinsternis.php', 'label' => 'Sonnenfinsternis'],
|
||||||
['href' => 'comets.php', 'label' => 'Kometen'],
|
['href' => 'bedeckung.php', 'label' => 'Bedeckungsphänomene'],
|
||||||
['href' => 'astronomical_conversions.php', 'label' => 'Astronomical Conversions'],
|
['href' => 'sternbedeckungen.php', 'label' => 'Mond-Stern-Bedeckungen'],
|
||||||
['href' => 'tcrb_lightcurve.php', 'label' => 'T CrB Lichtkurve'],
|
|
||||||
['href' => 'solarsystem.php', 'label' => 'Sonnensystem'],
|
|
||||||
['href' => 'mars.php', 'label' => 'Mars'],
|
|
||||||
['href' => 'jupitersystem.php', 'label' => 'Jupitersystem'],
|
|
||||||
['href' => 'tagbogen.php', 'label' => 'Tagbogen'],
|
|
||||||
['href' => 'sternenhimmel.php', 'label' => 'Sternenhimmel'],
|
|
||||||
['href' => 'satellitenhimmel.php', 'label' => 'Satellitenhimmel'],
|
|
||||||
['href' => 'meteorshowers.php', 'label' => 'Meteorströme'],
|
|
||||||
['href' => 'asteroid_temp.php', 'label' => 'Asteroid-Temperatur'],
|
|
||||||
['href' => 'geocron/index.php', 'label' => 'Geocron'],
|
|
||||||
['href' => 'geocron3d.php', 'label' => 'Geocron 3D'],
|
|
||||||
['href' => 'geocron3d_C.php', 'label' => 'Geocron 3D Cesium'],
|
|
||||||
['href' => 'universesandbox.php', 'label' => 'Universe Sandbox'],
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'title' => 'Finsternisse & Bedeckungen',
|
'title' => 'Planeten & Sonnensystem',
|
||||||
'links' => [
|
'links' => [
|
||||||
['href' => 'mondfinsternis.php', 'label' => 'Mondfinsternis'],
|
['href' => 'planetensichtbarkeit.php', 'label' => 'Planetensichtbarkeit'],
|
||||||
['href' => 'sonnenfinsternis.php', 'label' => 'Sonnenfinsternis'],
|
['href' => 'ephemeriden.php', 'label' => 'Ephemeriden'],
|
||||||
['href' => 'bedeckung.php', 'label' => 'Bedeckungsphänomene'],
|
['href' => 'solarsystem.php', 'label' => 'Sonnensystem'],
|
||||||
['href' => 'sternbedeckungen.php', 'label' => 'Mond-Stern-Bedeckungen'],
|
['href' => 'mars.php', 'label' => 'Mars'],
|
||||||
|
['href' => 'jupitersystem.php', 'label' => 'Jupitersystem'],
|
||||||
|
['href' => 'asteroid_temp.php', 'label' => 'Asteroid-Temperatur'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => 'Sternenhimmel & Karten',
|
||||||
|
'links' => [
|
||||||
|
['href' => 'sternenhimmel.php', 'label' => 'Sternenhimmel'],
|
||||||
|
['href' => 'drehbare_sternkarte.php', 'label' => 'Drehbare Sternkarte'],
|
||||||
|
['href' => 'satellitenhimmel.php', 'label' => 'Satellitenhimmel'],
|
||||||
|
['href' => 'tagbogen.php', 'label' => 'Tagbogen'],
|
||||||
|
['href' => 'meteorshowers.php', 'label' => 'Meteorströme'],
|
||||||
|
['href' => 'comets.php', 'label' => 'Kometen'],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'title' => 'Tools & Simulationen',
|
||||||
|
'links' => [
|
||||||
|
['href' => 'tcrb_lightcurve.php', 'label' => 'T CrB Lichtkurve'],
|
||||||
|
['href' => 'astronomical_conversions.php', 'label' => 'Astronomical Conversions'],
|
||||||
|
['href' => 'geocron/index.php', 'label' => 'Geocron'],
|
||||||
|
['href' => 'geocron3d.php', 'label' => 'Geocron 3D'],
|
||||||
|
['href' => 'geocron3d_C.php', 'label' => 'Geocron 3D Cesium'],
|
||||||
|
['href' => 'universesandbox.php', 'label' => 'Universe Sandbox'],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
+364
-74
@@ -888,80 +888,391 @@ if (!function_exists('monthForecastBuildNarrativeText')) {
|
|||||||
static fn (array $event): bool => in_array((string) ($event['type'] ?? ''), ['moon_phase', 'golden_handle', 'moon_planet', 'moon_planet_approach', 'moon_deep_sky', 'moon_deep_sky_approach', 'moon_occultation', 'moon_apsis'], true),
|
static fn (array $event): bool => in_array((string) ($event['type'] ?? ''), ['moon_phase', 'golden_handle', 'moon_planet', 'moon_planet_approach', 'moon_deep_sky', 'moon_deep_sky_approach', 'moon_occultation', 'moon_apsis'], true),
|
||||||
10
|
10
|
||||||
);
|
);
|
||||||
|
// Jahreszahl aus Datum entfernen (z. B. "19.04.2026" → "19.04.")
|
||||||
|
$shortDate = static function (string $d): string {
|
||||||
|
return (string) preg_replace('/\.\d{4}$/', '.', $d);
|
||||||
|
};
|
||||||
|
|
||||||
if ($moonEvents !== []) {
|
if ($moonEvents !== []) {
|
||||||
// Chronologisch sortieren nach local_iso
|
|
||||||
$sortedMoonEvents = $moonEvents;
|
$sortedMoonEvents = $moonEvents;
|
||||||
usort($sortedMoonEvents, static fn (array $a, array $b): int => strcmp(
|
usort($sortedMoonEvents, static fn (array $a, array $b): int => strcmp(
|
||||||
(string) ($a['local_iso'] ?? $a['date'] ?? ''),
|
(string) ($a['local_iso'] ?? $a['date'] ?? ''),
|
||||||
(string) ($b['local_iso'] ?? $b['date'] ?? '')
|
(string) ($b['local_iso'] ?? $b['date'] ?? '')
|
||||||
));
|
));
|
||||||
|
|
||||||
// Natürlichsprachliche Liste: "Vollmond ist am 01.05., Apogäum am 05.05. und Neumond am 16.05."
|
$phaseEvents = array_values(array_filter($sortedMoonEvents, static fn (array $e): bool => (string) ($e['type'] ?? '') === 'moon_phase'));
|
||||||
$moonParts = [];
|
$nonPhaseEvents = array_values(array_filter($sortedMoonEvents, static fn (array $e): bool => (string) ($e['type'] ?? '') !== 'moon_phase'));
|
||||||
foreach ($sortedMoonEvents as $me) {
|
|
||||||
$label = trim((string) ($me['event'] ?? ''));
|
$moonSentences = [];
|
||||||
$date = trim((string) ($me['date'] ?? ''));
|
|
||||||
if ($label === '' || $date === '') {
|
// 1. Mondphasen in einem natürlichen Satz zusammenfassen
|
||||||
continue;
|
if ($phaseEvents !== []) {
|
||||||
|
$phaseParts = [];
|
||||||
|
foreach ($phaseEvents as $pe) {
|
||||||
|
$rawLabel = trim((string) ($pe['event'] ?? ''));
|
||||||
|
$date = trim((string) ($pe['date'] ?? ''));
|
||||||
|
if ($rawLabel === '' || $date === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// "Mond Erstes Viertel" → "Erstes Viertel"
|
||||||
|
$cleanLabel = (string) preg_replace('/^Mond\s+/', '', $rawLabel);
|
||||||
|
$phaseParts[] = $cleanLabel . ' am ' . $shortDate($date);
|
||||||
}
|
}
|
||||||
// "Mond bedeckt X" → "der Mond bedeckt X" für natürlicheren Satzbau
|
if ($phaseParts !== []) {
|
||||||
if (str_starts_with($label, 'Mond bedeckt ')) {
|
$lastPhase = array_pop($phaseParts);
|
||||||
$label = 'der ' . $label;
|
$phaseList = $phaseParts !== [] ? implode(', ', $phaseParts) . ' und ' . $lastPhase : $lastPhase;
|
||||||
|
$moonSentences[] = 'Die Mondphasen im Überblick: ' . $phaseList . '.';
|
||||||
}
|
}
|
||||||
$moonParts[] = ['label' => $label, 'date' => $date];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($moonParts !== []) {
|
// 2. Apsis, Begegnungen und Goldener Henkel – nach Datum gruppiert
|
||||||
$moonSentenceParts = [];
|
$byDate = [];
|
||||||
foreach ($moonParts as $idx => $part) {
|
foreach ($nonPhaseEvents as $ne) {
|
||||||
if ($idx === 0) {
|
$date = trim((string) ($ne['date'] ?? ''));
|
||||||
$moonSentenceParts[] = $part['label'] . ' ist am ' . $part['date'];
|
if ($date === '') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$byDate[$date][] = $ne;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($byDate as $date => $dateEvents) {
|
||||||
|
$apsis = null;
|
||||||
|
$approaches = [];
|
||||||
|
$goldenHandle = null;
|
||||||
|
foreach ($dateEvents as $de) {
|
||||||
|
$type = (string) ($de['type'] ?? '');
|
||||||
|
if ($type === 'moon_apsis') {
|
||||||
|
$apsis = $de;
|
||||||
|
} elseif ($type === 'golden_handle') {
|
||||||
|
$goldenHandle = $de;
|
||||||
} else {
|
} else {
|
||||||
$moonSentenceParts[] = $part['label'] . ' am ' . $part['date'];
|
$approaches[] = $de;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$lastPart = array_pop($moonSentenceParts);
|
|
||||||
$moonSentence = $moonSentenceParts !== []
|
$sd = $shortDate($date);
|
||||||
? implode(', ', $moonSentenceParts) . ' und ' . $lastPart
|
|
||||||
: $lastPart;
|
if ($goldenHandle !== null) {
|
||||||
$paragraphs[] = $moonSentence . '.';
|
$moonSentences[] = 'Am ' . $sd . ' zeigt der Mond den Goldenen Henkel: Ein Gebirgskamm am Mondrand leuchtet bereits im Sonnenlicht, während das Tal dahinter noch im Schatten liegt – ein lohnender Anblick schon im kleinen Teleskop.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($apsis !== null) {
|
||||||
|
$apsisLabel = trim((string) ($apsis['event'] ?? ''));
|
||||||
|
// Distanz aus dem Label extrahieren: "(404.960 km)"
|
||||||
|
$distanceMatch = [];
|
||||||
|
$distanceStr = '';
|
||||||
|
if (preg_match('/\(([0-9.,]+\s*km)\)\s*$/', $apsisLabel, $distanceMatch)) {
|
||||||
|
$distanceStr = ' mit nur ' . $distanceMatch[1];
|
||||||
|
}
|
||||||
|
$isPerigee = str_contains($apsisLabel, 'Erdnähe') || str_contains($apsisLabel, 'Perigäum');
|
||||||
|
if ($isPerigee) {
|
||||||
|
$apsisText = 'Am ' . $sd . ' erreicht der Mond sein Perigäum' . $distanceStr . ' – er steht der Erde in diesem Monat am nächsten';
|
||||||
|
} else {
|
||||||
|
$apsisText = 'Am ' . $sd . ' erreicht der Mond sein Apogäum' . $distanceStr . ' – er steht der Erde in diesem Monat am fernsten';
|
||||||
|
}
|
||||||
|
if ($approaches !== []) {
|
||||||
|
// Begegnungen natürlich formulieren: "und zieht dabei in nur X Grad Abstand an Y vorbei"
|
||||||
|
$approachFragments = [];
|
||||||
|
foreach ($approaches as $ap) {
|
||||||
|
$apLabel = trim((string) ($ap['event'] ?? ''));
|
||||||
|
$sepMatch = [];
|
||||||
|
$sepStr = '';
|
||||||
|
if (preg_match('/\(([0-9.,]+\s*Grad)\)/', $apLabel, $sepMatch)) {
|
||||||
|
$apLabel = trim((string) preg_replace('/\s*\([0-9.,]+\s*Grad\)/', '', $apLabel));
|
||||||
|
$sepStr = ' in nur ' . $sepMatch[1] . ' Abstand';
|
||||||
|
}
|
||||||
|
if (str_starts_with($apLabel, 'Mond nahe ')) {
|
||||||
|
$target = substr($apLabel, strlen('Mond nahe '));
|
||||||
|
$approachFragments[] = $sepStr . ' an ' . $target . ' vorbei';
|
||||||
|
} elseif (str_starts_with($apLabel, 'Mond bedeckt ')) {
|
||||||
|
$target = substr($apLabel, strlen('Mond bedeckt '));
|
||||||
|
$approachFragments[] = ' und bedeckt dabei ' . $target;
|
||||||
|
} else {
|
||||||
|
$approachFragments[] = $sepStr !== '' ? $sepStr . ' bei ' . $apLabel : ' bei ' . $apLabel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$approachClause = count($approachFragments) === 1
|
||||||
|
? ' und zieht dabei' . $approachFragments[0]
|
||||||
|
: ' und zieht dabei' . implode(' sowie', $approachFragments);
|
||||||
|
$moonSentences[] = $apsisText . $approachClause . '.';
|
||||||
|
} else {
|
||||||
|
$moonSentences[] = $apsisText . '.';
|
||||||
|
}
|
||||||
|
} elseif ($approaches !== []) {
|
||||||
|
foreach ($approaches as $ap) {
|
||||||
|
$apLabel = trim((string) ($ap['event'] ?? ''));
|
||||||
|
$apDate = trim((string) ($ap['date'] ?? ''));
|
||||||
|
$sepMatch = [];
|
||||||
|
$sepStr = '';
|
||||||
|
if (preg_match('/\(([0-9.,]+\s*Grad)\)/', $apLabel, $sepMatch)) {
|
||||||
|
$apLabel = trim((string) preg_replace('/\s*\([0-9.,]+\s*Grad\)/', '', $apLabel));
|
||||||
|
$sepStr = ' in nur ' . $sepMatch[1] . ' Abstand';
|
||||||
|
}
|
||||||
|
$apSd = $shortDate($apDate !== '' ? $apDate : $date);
|
||||||
|
if (str_starts_with($apLabel, 'Mond nahe ')) {
|
||||||
|
$target = substr($apLabel, strlen('Mond nahe '));
|
||||||
|
$moonSentences[] = 'Am ' . $apSd . ' zieht der Mond' . $sepStr . ' an ' . $target . ' vorbei.';
|
||||||
|
} elseif (str_starts_with($apLabel, 'Mond bedeckt ')) {
|
||||||
|
$target = substr($apLabel, strlen('Mond bedeckt '));
|
||||||
|
$moonSentences[] = 'Am ' . $apSd . ' bedeckt der Mond ' . $target . '.';
|
||||||
|
} else {
|
||||||
|
$moonSentences[] = $apLabel . ' am ' . $apSd . ($sepStr !== '' ? ' – ' . ltrim($sepStr) : '') . '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($moonSentences !== []) {
|
||||||
|
$paragraphs[] = implode(' ', $moonSentences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hilfsfunktion: natürlichen Satz aus einem Planeten-Event bauen
|
||||||
|
$buildPlanetSentence = static function (array $event) use ($shortDate): ?string {
|
||||||
|
$type = (string) ($event['type'] ?? '');
|
||||||
|
$label = trim((string) ($event['event'] ?? ''));
|
||||||
|
$date = trim((string) ($event['date'] ?? ''));
|
||||||
|
if ($label === '' || $date === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$sd = $shortDate($date);
|
||||||
|
|
||||||
|
if ($type === 'planet_conjunction') {
|
||||||
|
$sepMatch = [];
|
||||||
|
$sep = '';
|
||||||
|
if (preg_match('/\(([0-9.,]+\s*Grad)\)/', $label, $sepMatch)) {
|
||||||
|
$sep = $sepMatch[1];
|
||||||
|
$label = trim((string) preg_replace('/\s*\([0-9.,]+\s*Grad\)/', '', $label));
|
||||||
|
}
|
||||||
|
if (preg_match('/^(.+?)\s+nahe\s+(.+)$/i', $label, $m)) {
|
||||||
|
$p1 = trim($m[1]);
|
||||||
|
$p2 = trim($m[2]);
|
||||||
|
$sepNote = $sep !== '' ? ' – der Abstand beträgt nur ' . $sep : '';
|
||||||
|
return 'Am ' . $sd . ' rücken ' . $p1 . ' und ' . $p2 . ' eng zusammen' . $sepNote . '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'golden_gate_of_ecliptic') {
|
||||||
|
$planet = '';
|
||||||
|
if (preg_match('/^(\S+)\s+im\s+Goldenen\s+Tor/i', $label, $m)) {
|
||||||
|
$planet = $m[1];
|
||||||
|
}
|
||||||
|
if ($planet !== '') {
|
||||||
|
return 'Am ' . $sd . ' durchquert ' . $planet . ' das Goldene Tor der Ekliptik und zieht dabei zwischen Hyaden und Plejaden hindurch – ein lohnender Anblick im Fernglas.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'inner_planet_elongation') {
|
||||||
|
$sepMatch = [];
|
||||||
|
$sepStr = '';
|
||||||
|
if (preg_match('/\(([0-9.,]+\s*Grad)\)/', $label, $sepMatch)) {
|
||||||
|
$sepStr = ' (' . $sepMatch[1] . ')';
|
||||||
|
$label = trim((string) preg_replace('/\s*\([0-9.,]+\s*Grad\)/', '', $label));
|
||||||
|
}
|
||||||
|
$isWest = str_contains($label, 'westlich') || str_contains($label, 'West');
|
||||||
|
$planet = '';
|
||||||
|
if (preg_match('/^(\S+)\s+/', $label, $m)) {
|
||||||
|
$planet = $m[1];
|
||||||
|
}
|
||||||
|
$visibility = $isWest ? 'als Morgenstern am besten zu beobachten' : 'als Abendstern am besten zu beobachten';
|
||||||
|
return 'Am ' . $sd . ' erreicht ' . ($planet ?: 'der Planet') . ' seine größte Elongation' . $sepStr . ' und ist dann ' . $visibility . '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'venus_peak_magnitude') {
|
||||||
|
$magMatch = [];
|
||||||
|
$magStr = '';
|
||||||
|
if (preg_match('/\(([^)]+)\)/', $label, $magMatch)) {
|
||||||
|
$magStr = ' mit ' . $magMatch[1];
|
||||||
|
}
|
||||||
|
return 'Am ' . $sd . ' erreicht Venus ihre größte Helligkeit' . $magStr . ' – sie ist dann selbst in der Dämmerung kaum zu übersehen.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'outer_planet_event') {
|
||||||
|
$planet = '';
|
||||||
|
if (preg_match('/^(\S+)\s+/', $label, $m)) {
|
||||||
|
$planet = $m[1];
|
||||||
|
}
|
||||||
|
if (str_contains($label, 'Opposition')) {
|
||||||
|
return 'Am ' . $sd . ' steht ' . ($planet ?: 'der Planet') . ' in Opposition – er geht bei Sonnenuntergang auf, ist die ganze Nacht sichtbar und leuchtet so hell wie selten.';
|
||||||
|
}
|
||||||
|
if (str_contains($label, 'Konjunktion')) {
|
||||||
|
return 'Am ' . $sd . ' steht ' . ($planet ?: 'der Planet') . ' in Konjunktion mit der Sonne und ist für einige Wochen nicht zu beobachten.';
|
||||||
|
}
|
||||||
|
if (str_contains($label, 'Quadratur')) {
|
||||||
|
return 'Am ' . $sd . ' befindet sich ' . ($planet ?: 'der Planet') . ' in Quadratur – er steht 90 Grad von der Sonne entfernt und ist in der ersten oder zweiten Nachthälfte gut sichtbar.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'mercury_good_visibility') {
|
||||||
|
return 'Um den ' . $sd . ' zeigt sich Merkur günstig am Himmel und lässt sich in der Dämmerung tief über dem Horizont aufspüren.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'planet_parade') {
|
||||||
|
return 'Am ' . $sd . ' sind mehrere Planeten gleichzeitig am Himmel zu sehen – eine seltene Planetenparade, die einen Blick Richtung Süden lohnt.';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback
|
||||||
|
return 'Am ' . $sd . ' ist zu beobachten: ' . $label . '.';
|
||||||
|
};
|
||||||
|
|
||||||
|
$buildPlanetMotionSentence = static function (array $event) use ($shortDate): ?string {
|
||||||
|
$type = (string) ($event['type'] ?? '');
|
||||||
|
$label = trim((string) ($event['event'] ?? ''));
|
||||||
|
$date = trim((string) ($event['date'] ?? ''));
|
||||||
|
if ($label === '' || $date === '') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$sd = $shortDate($date);
|
||||||
|
|
||||||
|
if ($type === 'outer_planet_station') {
|
||||||
|
$planet = '';
|
||||||
|
$isRetrograde = str_contains($label, 'rückläufig') || str_contains($label, 'Rückläufig');
|
||||||
|
$isPrograde = str_contains($label, 'rechtläufig') || str_contains($label, 'Rechtläufig') || str_contains($label, 'direkt');
|
||||||
|
if (preg_match('/^(\S+)\s+/', $label, $m)) {
|
||||||
|
$planet = $m[1];
|
||||||
|
}
|
||||||
|
if ($isRetrograde) {
|
||||||
|
return 'Ab dem ' . $sd . ' läuft ' . ($planet ?: 'der Planet') . ' rückläufig – er bewegt sich scheinbar rückwärts vor dem Sternhintergrund, was seine Beobachtung besonders interessant macht.';
|
||||||
|
}
|
||||||
|
if ($isPrograde) {
|
||||||
|
return 'Ab dem ' . $sd . ' setzt ' . ($planet ?: 'der Planet') . ' seine normale Vorwärtsbewegung am Himmel wieder fort.';
|
||||||
|
}
|
||||||
|
return 'Am ' . $sd . ' wird ' . ($planet ?: 'der Planet') . ' stationär und ändert seine Bewegungsrichtung am Himmel.';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($type === 'planet_constellation_change') {
|
||||||
|
// Label-Format: "Mars wechselt vom Sternbild Wassermann in das Sternbild Fische"
|
||||||
|
if (preg_match('/^(.+?)\s+wechselt\s+vom\s+Sternbild\s+(.+?)\s+in\s+das\s+Sternbild\s+(.+)$/i', $label, $m)) {
|
||||||
|
$planet = trim($m[1]);
|
||||||
|
$from = trim($m[2]);
|
||||||
|
$to = trim($m[3]);
|
||||||
|
// Formulierung deterministisch variieren (nach erstem Buchstaben des Planetennamens)
|
||||||
|
$variant = ord($planet[0]) % 3;
|
||||||
|
if ($variant === 1) {
|
||||||
|
return 'Am ' . $sd . ' verlässt ' . $planet . ' das Sternbild ' . $from . ' und zieht weiter in das Sternbild ' . $to . '.';
|
||||||
|
}
|
||||||
|
if ($variant === 2) {
|
||||||
|
return 'Am ' . $sd . ' tritt ' . $planet . ' aus dem Sternbild ' . $from . ' in das Sternbild ' . $to . ' über.';
|
||||||
|
}
|
||||||
|
return 'Am ' . $sd . ' wechselt ' . $planet . ' vom Sternbild ' . $from . ' in das Sternbild ' . $to . '.';
|
||||||
|
}
|
||||||
|
// Fallback ohne "vom"-Angabe
|
||||||
|
if (preg_match('/^(.+?)\s+wechselt\s+(?:in\s+das\s+Sternbild\s+|ins?\s+(?:Sternbild\s+)?)(.+)$/i', $label, $m)) {
|
||||||
|
return 'Am ' . $sd . ' wechselt ' . trim($m[1]) . ' in das Sternbild ' . trim($m[2]) . '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 'Am ' . $sd . ' ist zu beobachten: ' . $label . '.';
|
||||||
|
};
|
||||||
|
|
||||||
$planetObservationEvents = $findEvents(
|
$planetObservationEvents = $findEvents(
|
||||||
$filteredEvents,
|
$filteredEvents,
|
||||||
static fn (array $event): bool => in_array((string) ($event['type'] ?? ''), ['inner_planet_event', 'venus_peak_magnitude', 'outer_planet_event', 'planet_conjunction', 'planet_parade', 'mercury_good_visibility', 'golden_gate_of_ecliptic'], true),
|
static fn (array $event): bool => in_array((string) ($event['type'] ?? ''), ['inner_planet_event', 'venus_peak_magnitude', 'outer_planet_event', 'planet_conjunction', 'planet_parade', 'mercury_good_visibility', 'golden_gate_of_ecliptic'], true),
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
if ($planetObservationEvents !== []) {
|
if ($planetObservationEvents !== []) {
|
||||||
$planetIntro = $pickRandomText([
|
$planetSentences = [];
|
||||||
'Bei den Planeten lohnt sich vor allem der Blick auf',
|
foreach ($planetObservationEvents as $pe) {
|
||||||
'Planetarisch besonders interessant sind in diesem Monat',
|
$sentence = $buildPlanetSentence($pe);
|
||||||
'Bei den Planeten stechen in diesem Monat vor allem',
|
if ($sentence !== null) {
|
||||||
'Einen planetaren Schwerpunkt bilden in diesem Monat',
|
$planetSentences[] = $sentence;
|
||||||
], 'Bei den Planeten lohnt sich vor allem der Blick auf');
|
}
|
||||||
$planetOutro = $pickRandomText([
|
}
|
||||||
'Diese Termine geben dem Monat seinen charakteristischen planetaren Akzent.',
|
if ($planetSentences !== []) {
|
||||||
'Damit bekommt der Monat einen klaren planetaren Schwerpunkt.',
|
$paragraphs[] = implode(' ', $planetSentences);
|
||||||
'Solche Termine prägen den planetaren Charakter dieses Monats besonders deutlich.',
|
}
|
||||||
'Sie setzen im Monatsverlauf markante planetare Akzente.',
|
|
||||||
], 'Diese Termine geben dem Monat seinen charakteristischen planetaren Akzent.');
|
|
||||||
$paragraphs[] = $planetIntro . ' ' . $describeEvents($planetObservationEvents) . '. ' . $planetOutro;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$planetMotionEvents = $findEvents(
|
$planetMotionEvents = $findEvents(
|
||||||
$filteredEvents,
|
$filteredEvents,
|
||||||
static fn (array $event): bool => in_array((string) ($event['type'] ?? ''), ['outer_planet_station', 'planet_constellation_change'], true),
|
static fn (array $event): bool => in_array((string) ($event['type'] ?? ''), ['outer_planet_station', 'planet_constellation_change'], true),
|
||||||
4
|
8
|
||||||
);
|
);
|
||||||
if ($planetMotionEvents !== []) {
|
if ($planetMotionEvents !== []) {
|
||||||
$planetMotionIntro = $pickRandomText([
|
// Sternbild-Akkusativformen für natürliche Sätze ohne "Sternbild"-Wiederholung
|
||||||
'Im Monatsverlauf zeigen sich bei den Planeten auch auffällige Positionswechsel.',
|
$constellationAkk = [
|
||||||
'Auch in ihrer Stellung am Himmel verändern sich die Planeten in diesem Monat sichtbar.',
|
'Widder' => 'den Widder', 'Stier' => 'den Stier', 'Zwillinge' => 'die Zwillinge',
|
||||||
'Neben den Beobachtungshighlights fallen bei den Planeten auch einige Positionswechsel auf.',
|
'Krebs' => 'den Krebs', 'Löwe' => 'den Löwen', 'Jungfrau' => 'die Jungfrau',
|
||||||
'Auch die Bewegung der Planeten vor dem Sternhintergrund macht sich in diesem Monat bemerkbar.',
|
'Waage' => 'die Waage', 'Skorpion' => 'den Skorpion', 'Schütze' => 'den Schützen',
|
||||||
], 'Im Monatsverlauf zeigen sich bei den Planeten auch auffaellige Positionswechsel.');
|
'Steinbock' => 'den Steinbock', 'Wassermann' => 'den Wassermann', 'Fische' => 'die Fische',
|
||||||
$paragraphs[] = $planetMotionIntro . ' Dazu gehören ' . $describeEvents($planetMotionEvents) . '.';
|
'Walfisch' => 'den Walfisch', 'Orion' => 'den Orion', 'Fuhrmann' => 'den Fuhrmann',
|
||||||
|
'Stier' => 'den Stier', 'Kassiopeia' => 'die Kassiopeia', 'Andromeda' => 'die Andromeda',
|
||||||
|
'Perseus' => 'den Perseus', 'Pegasus' => 'den Pegasus', 'Leier' => 'die Leier',
|
||||||
|
'Schwan' => 'den Schwan', 'Adler' => 'den Adler', 'Schlange' => 'die Schlange',
|
||||||
|
'Schlangenträger' => 'den Schlangenträger', 'Herkules' => 'den Herkules',
|
||||||
|
'Bärenhüter' => 'den Bärenhüter', 'Großer Bär' => 'den Großen Bären',
|
||||||
|
'Drache' => 'den Drachen', 'Nördliche Krone' => 'die Nördliche Krone',
|
||||||
|
'Kleiner Löwe' => 'den Kleinen Löwen', 'Rabe' => 'den Raben', 'Becher' => 'den Becher',
|
||||||
|
'Wasserschlange' => 'die Wasserschlange', 'Eridanus' => 'den Eridanus',
|
||||||
|
'Hase' => 'den Hasen', 'Großer Hund' => 'den Großen Hund',
|
||||||
|
'Kleiner Hund' => 'den Kleinen Hund', 'Einhorn' => 'das Einhorn',
|
||||||
|
'Delfin' => 'den Delfin', 'Pfeil' => 'den Pfeil', 'Fuchs' => 'den Fuchs',
|
||||||
|
'Kepheus' => 'den Kepheus', 'Südlicher Fisch' => 'den Südlichen Fisch',
|
||||||
|
'Jagdhunde' => 'die Jagdhunde', 'Löwchen' => 'das Löwchen',
|
||||||
|
];
|
||||||
|
$akkusativ = static function (string $name) use ($constellationAkk): string {
|
||||||
|
return $constellationAkk[$name] ?? 'das Sternbild ' . $name;
|
||||||
|
};
|
||||||
|
|
||||||
|
$stationEvents = array_values(array_filter($planetMotionEvents, static fn (array $e): bool => (string) ($e['type'] ?? '') === 'outer_planet_station'));
|
||||||
|
$changeEvents = array_values(array_filter($planetMotionEvents, static fn (array $e): bool => (string) ($e['type'] ?? '') === 'planet_constellation_change'));
|
||||||
|
|
||||||
|
$motionSentences = [];
|
||||||
|
|
||||||
|
// Rückläufigkeits-Ereignisse einzeln als Satz
|
||||||
|
foreach ($stationEvents as $se) {
|
||||||
|
$sentence = $buildPlanetMotionSentence($se);
|
||||||
|
if ($sentence !== null) {
|
||||||
|
$motionSentences[] = $sentence;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sternbild-Wechsel: nach Planet gruppieren, kompakt als eine Aussage
|
||||||
|
if ($changeEvents !== []) {
|
||||||
|
$byPlanet = [];
|
||||||
|
$planetOrder = [];
|
||||||
|
foreach ($changeEvents as $ce) {
|
||||||
|
$label = trim((string) ($ce['event'] ?? ''));
|
||||||
|
$date = trim((string) ($ce['date'] ?? ''));
|
||||||
|
if (!preg_match('/^(.+?)\s+wechselt\s+vom\s+Sternbild\s+(.+?)\s+in\s+das\s+Sternbild\s+(.+)$/i', $label, $m)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$planet = trim($m[1]);
|
||||||
|
$to = trim($m[3]);
|
||||||
|
if (!isset($byPlanet[$planet])) {
|
||||||
|
$byPlanet[$planet] = [];
|
||||||
|
$planetOrder[] = $planet;
|
||||||
|
}
|
||||||
|
$byPlanet[$planet][] = ['date' => $date, 'to' => $to];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($byPlanet !== []) {
|
||||||
|
$parts = [];
|
||||||
|
foreach ($planetOrder as $planet) {
|
||||||
|
$moves = $byPlanet[$planet];
|
||||||
|
if (count($moves) === 1) {
|
||||||
|
$parts[] = $planet . ' am ' . $shortDate($moves[0]['date']) . ' in ' . $akkusativ($moves[0]['to']);
|
||||||
|
} else {
|
||||||
|
// Mehrfacher Wechsel desselben Planeten
|
||||||
|
$moveParts = [];
|
||||||
|
foreach ($moves as $move) {
|
||||||
|
$moveParts[] = 'am ' . $shortDate($move['date']) . ' in ' . $akkusativ($move['to']);
|
||||||
|
}
|
||||||
|
$lastMove = array_pop($moveParts);
|
||||||
|
$parts[] = $planet . ' ' . ($moveParts !== [] ? implode(', ', $moveParts) . ' und dann ' . $lastMove : $lastMove);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$lastPart = array_pop($parts);
|
||||||
|
$changeText = count($byPlanet) > 1
|
||||||
|
? implode(', ', $parts) . ' und ' . $lastPart
|
||||||
|
: $lastPart;
|
||||||
|
$motionSentences[] = 'Sternbildwechsel im Monatsverlauf: ' . $changeText . '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($motionSentences !== []) {
|
||||||
|
$paragraphs[] = implode(' ', $motionSentences);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$cometEvents = $findEvents(
|
$cometEvents = $findEvents(
|
||||||
@@ -3138,40 +3449,13 @@ async function composeExportCanvas(sourceCanvas, logoPosition, options) {
|
|||||||
const caption = monthChartExportCaption();
|
const caption = monthChartExportCaption();
|
||||||
if (showCaption && caption !== '') {
|
if (showCaption && caption !== '') {
|
||||||
const padding = Math.round(exportCanvas.width * 0.024);
|
const padding = Math.round(exportCanvas.width * 0.024);
|
||||||
const fontSize = Math.max(26, Math.round(exportCanvas.width * 0.022));
|
const fontSize = Math.max(18, Math.round(exportCanvas.width * 0.015));
|
||||||
exportCtx.save();
|
exportCtx.save();
|
||||||
exportCtx.font = '600 ' + fontSize + 'px Rajdhani, sans-serif';
|
exportCtx.font = '600 ' + fontSize + 'px Rajdhani, sans-serif';
|
||||||
exportCtx.textAlign = 'right';
|
exportCtx.textAlign = 'right';
|
||||||
exportCtx.textBaseline = 'bottom';
|
exportCtx.textBaseline = 'bottom';
|
||||||
|
|
||||||
const metrics = exportCtx.measureText(caption);
|
|
||||||
const textWidth = metrics.width;
|
|
||||||
const ascent = metrics.actualBoundingBoxAscent || fontSize * 0.8;
|
|
||||||
const descent = metrics.actualBoundingBoxDescent || fontSize * 0.2;
|
|
||||||
const boxPadX = Math.round(fontSize * 0.45);
|
|
||||||
const boxPadY = Math.round(fontSize * 0.3);
|
|
||||||
const boxWidth = textWidth + boxPadX * 2;
|
|
||||||
const boxHeight = ascent + descent + boxPadY * 2;
|
|
||||||
const boxX = exportCanvas.width - padding - boxWidth;
|
|
||||||
const boxY = exportCanvas.height - padding - boxHeight;
|
|
||||||
const radius = Math.round(fontSize * 0.28);
|
|
||||||
|
|
||||||
exportCtx.fillStyle = 'rgba(3, 7, 14, 0.7)';
|
|
||||||
exportCtx.beginPath();
|
|
||||||
exportCtx.moveTo(boxX + radius, boxY);
|
|
||||||
exportCtx.lineTo(boxX + boxWidth - radius, boxY);
|
|
||||||
exportCtx.quadraticCurveTo(boxX + boxWidth, boxY, boxX + boxWidth, boxY + radius);
|
|
||||||
exportCtx.lineTo(boxX + boxWidth, boxY + boxHeight - radius);
|
|
||||||
exportCtx.quadraticCurveTo(boxX + boxWidth, boxY + boxHeight, boxX + boxWidth - radius, boxY + boxHeight);
|
|
||||||
exportCtx.lineTo(boxX + radius, boxY + boxHeight);
|
|
||||||
exportCtx.quadraticCurveTo(boxX, boxY + boxHeight, boxX, boxY + boxHeight - radius);
|
|
||||||
exportCtx.lineTo(boxX, boxY + radius);
|
|
||||||
exportCtx.quadraticCurveTo(boxX, boxY, boxX + radius, boxY);
|
|
||||||
exportCtx.closePath();
|
|
||||||
exportCtx.fill();
|
|
||||||
|
|
||||||
exportCtx.fillStyle = 'rgba(235, 242, 255, 0.96)';
|
exportCtx.fillStyle = 'rgba(235, 242, 255, 0.96)';
|
||||||
exportCtx.fillText(caption, exportCanvas.width - padding - boxPadX, exportCanvas.height - padding - boxPadY);
|
exportCtx.fillText(caption, exportCanvas.width - padding, exportCanvas.height - padding);
|
||||||
exportCtx.restore();
|
exportCtx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3211,7 +3495,13 @@ function monthChartExportCaption() {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
return 'Sternhimmel für ' + String(hour).padStart(2, '0') + ':' + String(minute).padStart(2, '0') + ' Uhr';
|
const parts = String(MONTH_CHART_CONFIG.localTimeLabel || '').split(' ');
|
||||||
|
const date = parts[0] || '';
|
||||||
|
const hh = String(hour).padStart(2, '0');
|
||||||
|
const mm = String(minute).padStart(2, '0');
|
||||||
|
return date !== ''
|
||||||
|
? 'Sternhimmel am ' + date + ' um ' + hh + ':' + mm + ' Uhr'
|
||||||
|
: 'Sternhimmel um ' + hh + ':' + mm + ' Uhr';
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatGermanDate(date) {
|
function formatGermanDate(date) {
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ $constellationDataError = null;
|
|||||||
$starDataError = null;
|
$starDataError = null;
|
||||||
$messierData = [];
|
$messierData = [];
|
||||||
$messierDataError = null;
|
$messierDataError = null;
|
||||||
$milkyWayData = null;
|
|
||||||
$milkyWayDataError = null;
|
|
||||||
$availableLocations = [];
|
$availableLocations = [];
|
||||||
$starDbMagLimit = 12.0;
|
$starDbMagLimit = 12.0;
|
||||||
|
|
||||||
@@ -236,16 +234,6 @@ try {
|
|||||||
$messierDataError = $e->getMessage();
|
$messierDataError = $e->getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
|
||||||
$milkyWayPath = __DIR__ . '/js/mw.json';
|
|
||||||
if (is_file($milkyWayPath)) {
|
|
||||||
$milkyWayData = json_decode((string) file_get_contents($milkyWayPath), true, 512, JSON_THROW_ON_ERROR);
|
|
||||||
}
|
|
||||||
} catch (Throwable $e) {
|
|
||||||
$milkyWayData = null;
|
|
||||||
$milkyWayDataError = $e->getMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
$favCometDataJson = json_encode(
|
$favCometDataJson = json_encode(
|
||||||
$favCometData ?? [],
|
$favCometData ?? [],
|
||||||
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
||||||
@@ -271,14 +259,6 @@ $messierDataErrorJson = json_encode(
|
|||||||
$messierDataError,
|
$messierDataError,
|
||||||
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
||||||
);
|
);
|
||||||
$milkyWayDataJson = json_encode(
|
|
||||||
$milkyWayData,
|
|
||||||
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
|
||||||
);
|
|
||||||
$milkyWayDataErrorJson = json_encode(
|
|
||||||
$milkyWayDataError,
|
|
||||||
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES
|
|
||||||
);
|
|
||||||
?>
|
?>
|
||||||
<?php require __DIR__ . '/header.php'; ?>
|
<?php require __DIR__ . '/header.php'; ?>
|
||||||
<?php
|
<?php
|
||||||
@@ -393,13 +373,6 @@ if (!$availableLocations) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sp-row">
|
|
||||||
<span class="sp-label">Milchstraße</span>
|
|
||||||
<div class="sp-toggles">
|
|
||||||
<label class="sp-toggle"><input type="checkbox" id="cfgMilkyWayShow" checked><span class="sp-pill"></span><span class="sp-text">an</span></label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="sp-row">
|
<div class="sp-row">
|
||||||
<span class="sp-label">Sternbilder</span>
|
<span class="sp-label">Sternbilder</span>
|
||||||
<div class="sp-toggles">
|
<div class="sp-toggles">
|
||||||
@@ -522,14 +495,6 @@ const CFG_DEFAULT = {
|
|||||||
ecliptic: {
|
ecliptic: {
|
||||||
color: 'rgba(255,175,35,0.52)', width: 1.1, dash: [5,5]
|
color: 'rgba(255,175,35,0.52)', width: 1.1, dash: [5,5]
|
||||||
},
|
},
|
||||||
milkyWay: {
|
|
||||||
fillSoft: 'rgba(180, 208, 255, 0.018)',
|
|
||||||
fillMain: 'rgba(210, 228, 255, 0.028)',
|
|
||||||
stroke: 'rgba(220, 235, 255, 0.035)',
|
|
||||||
glow: 'rgba(185, 210, 255, 0.10)',
|
|
||||||
blur: 16,
|
|
||||||
minPoints: 20
|
|
||||||
},
|
|
||||||
constellations: {
|
constellations: {
|
||||||
color: 'rgba(100,160,220,0.38)', width: 0.8, dash: [],
|
color: 'rgba(100,160,220,0.38)', width: 0.8, dash: [],
|
||||||
colorLabels: 'rgba(120,175,230,0.50)', fontLabels: '9px Rajdhani, sans-serif'
|
colorLabels: 'rgba(120,175,230,0.50)', fontLabels: '9px Rajdhani, sans-serif'
|
||||||
@@ -631,7 +596,6 @@ let showAltaz = false;
|
|||||||
let showPlanets = true;
|
let showPlanets = true;
|
||||||
let showSunMoon = true;
|
let showSunMoon = true;
|
||||||
let showEclip = true;
|
let showEclip = true;
|
||||||
let showMilkyWay = true;
|
|
||||||
let showMessier = true;
|
let showMessier = true;
|
||||||
let showConst = true;
|
let showConst = true;
|
||||||
let showComets = true;
|
let showComets = true;
|
||||||
@@ -654,8 +618,6 @@ const STAR_DATA_URL = 'sternenhimmel.php?stars_api=1';
|
|||||||
const EMBEDDED_STAR_ERROR = <?php echo $starDataErrorJson ?: 'null'; ?>;
|
const EMBEDDED_STAR_ERROR = <?php echo $starDataErrorJson ?: 'null'; ?>;
|
||||||
const EMBEDDED_MESSIER_DATA = <?php echo $messierDataJson ?: '[]'; ?>;
|
const EMBEDDED_MESSIER_DATA = <?php echo $messierDataJson ?: '[]'; ?>;
|
||||||
const EMBEDDED_MESSIER_ERROR = <?php echo $messierDataErrorJson ?: 'null'; ?>;
|
const EMBEDDED_MESSIER_ERROR = <?php echo $messierDataErrorJson ?: 'null'; ?>;
|
||||||
const EMBEDDED_MILKY_WAY_DATA = <?php echo $milkyWayDataJson ?: 'null'; ?>;
|
|
||||||
const EMBEDDED_MILKY_WAY_ERROR = <?php echo $milkyWayDataErrorJson ?: 'null'; ?>;
|
|
||||||
const MESSIER = Array.isArray(EMBEDDED_MESSIER_DATA) ? EMBEDDED_MESSIER_DATA : [];
|
const MESSIER = Array.isArray(EMBEDDED_MESSIER_DATA) ? EMBEDDED_MESSIER_DATA : [];
|
||||||
const FAV_COMETS = <?php echo $favCometDataJson ?: '[]'; ?>;
|
const FAV_COMETS = <?php echo $favCometDataJson ?: '[]'; ?>;
|
||||||
let constellationData = EMBEDDED_CONSTELLATION_DATA;
|
let constellationData = EMBEDDED_CONSTELLATION_DATA;
|
||||||
@@ -674,66 +636,6 @@ function buildMStyle() {
|
|||||||
}
|
}
|
||||||
let M_STYLE = buildMStyle();
|
let M_STYLE = buildMStyle();
|
||||||
|
|
||||||
function buildMilkyWayRings(data) {
|
|
||||||
if (!data || !Array.isArray(data.features)) return [];
|
|
||||||
|
|
||||||
const rings = [];
|
|
||||||
for (const feature of data.features) {
|
|
||||||
const geometry = feature && feature.geometry ? feature.geometry : null;
|
|
||||||
if (!geometry) continue;
|
|
||||||
|
|
||||||
const polygons = geometry.type === 'Polygon'
|
|
||||||
? [geometry.coordinates]
|
|
||||||
: geometry.type === 'MultiPolygon'
|
|
||||||
? geometry.coordinates
|
|
||||||
: [];
|
|
||||||
|
|
||||||
for (const polygon of polygons) {
|
|
||||||
if (!Array.isArray(polygon)) continue;
|
|
||||||
for (const rawRing of polygon) {
|
|
||||||
if (!Array.isArray(rawRing) || rawRing.length < CFG.milkyWay.minPoints) continue;
|
|
||||||
|
|
||||||
const coords = [];
|
|
||||||
let area = 0;
|
|
||||||
|
|
||||||
for (let i = 0; i < rawRing.length; i++) {
|
|
||||||
const point = rawRing[i];
|
|
||||||
if (!Array.isArray(point) || point.length < 2) continue;
|
|
||||||
const lon = Number(point[0]);
|
|
||||||
const lat = Number(point[1]);
|
|
||||||
if (!Number.isFinite(lon) || !Number.isFinite(lat)) continue;
|
|
||||||
|
|
||||||
coords.push([lon, lat]);
|
|
||||||
|
|
||||||
if (i < rawRing.length - 1) {
|
|
||||||
const next = rawRing[i + 1];
|
|
||||||
const lon2 = Array.isArray(next) ? Number(next[0]) : NaN;
|
|
||||||
const lat2 = Array.isArray(next) ? Number(next[1]) : NaN;
|
|
||||||
if (Number.isFinite(lon2) && Number.isFinite(lat2)) {
|
|
||||||
area += (lon * lat2) - (lon2 * lat);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (coords.length < CFG.milkyWay.minPoints) continue;
|
|
||||||
|
|
||||||
const areaAbs = Math.abs(area / 2);
|
|
||||||
if (!Number.isFinite(areaAbs)) continue;
|
|
||||||
|
|
||||||
rings.push({
|
|
||||||
coords,
|
|
||||||
areaAbs,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rings.sort((a, b) => b.areaAbs - a.areaAbs);
|
|
||||||
return rings;
|
|
||||||
}
|
|
||||||
|
|
||||||
const MILKY_WAY_RINGS = buildMilkyWayRings(EMBEDDED_MILKY_WAY_DATA);
|
|
||||||
|
|
||||||
function getTime() { return liveMode ? new Date() : simTime; }
|
function getTime() { return liveMode ? new Date() : simTime; }
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════════════
|
||||||
@@ -1968,7 +1870,6 @@ function render() {
|
|||||||
ctx.fill();
|
ctx.fill();
|
||||||
ctx.clip();
|
ctx.clip();
|
||||||
|
|
||||||
if (showMilkyWay) drawMilkyWay(date);
|
|
||||||
if (showAltaz) drawAltazGrid();
|
if (showAltaz) drawAltazGrid();
|
||||||
if (showEq) drawEquatorialGrid(date);
|
if (showEq) drawEquatorialGrid(date);
|
||||||
if (showEclip) drawEcliptic(date);
|
if (showEclip) drawEcliptic(date);
|
||||||
@@ -2303,7 +2204,6 @@ spBind('cfgPlanetsShow', () => showPlanets, v => showPlanets = v);
|
|||||||
spBind('cfgCometsShow', () => showComets, v => showComets = v);
|
spBind('cfgCometsShow', () => showComets, v => showComets = v);
|
||||||
spBind('cfgCometsLabels', () => labelComets, v => labelComets = v);
|
spBind('cfgCometsLabels', () => labelComets, v => labelComets = v);
|
||||||
spBind('cfgEclipShow', () => showEclip, v => showEclip = v);
|
spBind('cfgEclipShow', () => showEclip, v => showEclip = v);
|
||||||
spBind('cfgMilkyWayShow', () => showMilkyWay, v => showMilkyWay = v);
|
|
||||||
spBind('cfgMessierShow', () => showMessier, v => showMessier = v);
|
spBind('cfgMessierShow', () => showMessier, v => showMessier = v);
|
||||||
spBind('cfgSunMoonShow', () => showSunMoon, v => showSunMoon = v);
|
spBind('cfgSunMoonShow', () => showSunMoon, v => showSunMoon = v);
|
||||||
|
|
||||||
@@ -2394,10 +2294,6 @@ if (EMBEDDED_MESSIER_ERROR) {
|
|||||||
console.warn('Messier-Daten aus der Datenbank nicht geladen:', EMBEDDED_MESSIER_ERROR);
|
console.warn('Messier-Daten aus der Datenbank nicht geladen:', EMBEDDED_MESSIER_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EMBEDDED_MILKY_WAY_ERROR) {
|
|
||||||
console.warn('Milchstraßen-Daten nicht geladen:', EMBEDDED_MILKY_WAY_ERROR);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateStarLoadingUi(done, total) {
|
function updateStarLoadingUi(done, total) {
|
||||||
if (!starLoadingOverlay || !starLoadingFill || !starLoadingStatus || !starLoadingNote) return;
|
if (!starLoadingOverlay || !starLoadingFill || !starLoadingStatus || !starLoadingNote) return;
|
||||||
const safeTotal = Math.max(1, total);
|
const safeTotal = Math.max(1, total);
|
||||||
|
|||||||
Reference in New Issue
Block a user