stationäre Punkte drin

This commit is contained in:
Eskimue
2026-04-03 15:06:09 +02:00
parent e7dae6667f
commit a4e2367f33
4 changed files with 217 additions and 2 deletions
+24
View File
@@ -626,3 +626,27 @@ Stack trace:
[Fri Apr 3 14:43:53 2026] 127.0.0.1:63593 Accepted
[Fri Apr 3 14:43:55 2026] 127.0.0.1:63593 [200]: GET /favicon.ico
[Fri Apr 3 14:43:55 2026] 127.0.0.1:63593 Closing
[Fri Apr 3 14:50:16 2026] 127.0.0.1:61254 Accepted
[Fri Apr 3 14:50:34 2026] 127.0.0.1:61254 [200]: GET /monatsvorhersage_old.php?year=2026&month=1
[Fri Apr 3 14:50:34 2026] 127.0.0.1:61254 Closing
[Fri Apr 3 14:50:34 2026] 127.0.0.1:61256 Accepted
[Fri Apr 3 14:50:51 2026] 127.0.0.1:61256 [200]: GET /monatsvorhersage_old.php?year=2026&month=1
[Fri Apr 3 14:50:51 2026] 127.0.0.1:61256 Closing
[Fri Apr 3 14:51:26 2026] 127.0.0.1:52317 Accepted
[Fri Apr 3 14:51:41 2026] 127.0.0.1:52317 [200]: GET /monatsvorhersage_old.php?year=2026&month=1
[Fri Apr 3 14:51:41 2026] 127.0.0.1:52317 Closing
[Fri Apr 3 14:51:41 2026] 127.0.0.1:63047 Accepted
[Fri Apr 3 14:51:41 2026] 127.0.0.1:61026 Accepted
[Fri Apr 3 14:51:41 2026] 127.0.0.1:63047 [200]: GET /css/style.css
[Fri Apr 3 14:51:41 2026] 127.0.0.1:61026 [200]: GET /js/astronomy.browser.min.js
[Fri Apr 3 14:51:41 2026] 127.0.0.1:63047 Closing
[Fri Apr 3 14:51:41 2026] 127.0.0.1:61026 Closing
[Fri Apr 3 14:51:41 2026] 127.0.0.1:52369 Accepted
[Fri Apr 3 14:51:41 2026] 127.0.0.1:61642 Accepted
[Fri Apr 3 14:51:41 2026] 127.0.0.1:52369 [200]: GET /images/star16x16.png
[Fri Apr 3 14:51:41 2026] 127.0.0.1:61642 [200]: GET /images/star16x16_rays.png
[Fri Apr 3 14:51:41 2026] 127.0.0.1:52369 Closing
[Fri Apr 3 14:51:41 2026] 127.0.0.1:61642 Closing
[Fri Apr 3 14:51:41 2026] 127.0.0.1:57770 Accepted
[Fri Apr 3 14:51:43 2026] 127.0.0.1:57770 [200]: GET /favicon.ico
[Fri Apr 3 14:51:43 2026] 127.0.0.1:57770 Closing
+40
View File
@@ -64,6 +64,7 @@ $moonApsisEvents = [];
$sunApsisEvents = [];
$innerPlanetElongationEvents = [];
$outerPlanetEvents = [];
$outerPlanetStationEvents = [];
$moonOccultations = [];
$seasonChanges = [];
$monthEventList = [];
@@ -440,6 +441,23 @@ if (is_array($outerPlanetDecoded) && ($outerPlanetDecoded['ok'] ?? false)) {
$outerPlanetEvents = is_array($outerPlanetDecoded['events'] ?? null) ? $outerPlanetDecoded['events'] : [];
}
$outerPlanetStationOutput = [];
$outerPlanetStationExitCode = 0;
$outerPlanetStationArgs = [
$pythonScriptPath,
'outer_planet_stations_for_month',
(string) $selectedYear,
(string) $selectedMonth,
$chartTimezone,
];
$outerPlanetStationCommand = $pythonExecutable . ' ' . implode(' ', array_map('escapeshellarg', $outerPlanetStationArgs)) . ' 2>&1';
exec($outerPlanetStationCommand, $outerPlanetStationOutput, $outerPlanetStationExitCode);
$outerPlanetStationRaw = trim(implode("\n", $outerPlanetStationOutput));
$outerPlanetStationDecoded = json_decode($outerPlanetStationRaw, true);
if (is_array($outerPlanetStationDecoded) && ($outerPlanetStationDecoded['ok'] ?? false)) {
$outerPlanetStationEvents = is_array($outerPlanetStationDecoded['events'] ?? null) ? $outerPlanetStationDecoded['events'] : [];
}
$moonPlanetOutput = [];
$moonPlanetExitCode = 0;
$moonPlanetArgs = [
@@ -672,6 +690,28 @@ foreach ($outerPlanetEvents as $outerPlanetEvent) {
];
}
foreach ($outerPlanetStationEvents as $outerPlanetStationEvent) {
if (!is_array($outerPlanetStationEvent)) {
continue;
}
$stationPlanet = (string) ($outerPlanetStationEvent['planet_label'] ?? 'Planet');
$stationKind = (string) ($outerPlanetStationEvent['kind'] ?? '');
$stationLabel = $stationKind === 'retrograde'
? $stationPlanet . ' stationär, dann rückläufig'
: ($stationKind === 'prograde'
? $stationPlanet . ' stationär, dann rechtläufig'
: (string) ($outerPlanetStationEvent['label'] ?? 'Stationärer Punkt'));
$monthEventList[] = [
'event' => $stationLabel,
'date' => (string) ($outerPlanetStationEvent['local_date'] ?? ''),
'time' => (string) ($outerPlanetStationEvent['local_time'] ?? ''),
'local_iso' => (string) ($outerPlanetStationEvent['local_iso'] ?? ''),
'type' => 'outer_planet_station',
];
}
foreach ($moonPlanetApproaches as $approachEvent) {
if (!is_array($approachEvent)) {
continue;
Binary file not shown.
+153 -2
View File
@@ -1308,6 +1308,152 @@ def action_outer_planet_events_for_month(args: list[str]) -> dict:
}
def geocentric_ecliptic_longitude_deg(body: astronomy.Body, dt_utc: datetime) -> float:
time_value = dt_to_time(dt_utc)
vector = astronomy.GeoVector(body, time_value, True)
ecliptic = astronomy.Ecliptic(vector)
return float(ecliptic.elon)
def longitude_delta_deg(left_deg: float, right_deg: float) -> float:
delta = right_deg - left_deg
while delta <= -180.0:
delta += 360.0
while delta > 180.0:
delta -= 360.0
return delta
def planet_longitude_rate_deg_per_day(body: astronomy.Body, dt_utc: datetime) -> float:
step = timedelta(hours=12)
left = geocentric_ecliptic_longitude_deg(body, dt_utc - step)
right = geocentric_ecliptic_longitude_deg(body, dt_utc + step)
return longitude_delta_deg(left, right)
def refine_stationary_time(body: astronomy.Body, left_utc: datetime, right_utc: datetime) -> datetime:
left = left_utc
right = right_utc
f_left = planet_longitude_rate_deg_per_day(body, left)
f_right = planet_longitude_rate_deg_per_day(body, right)
for _ in range(40):
mid = left + (right - left) / 2
f_mid = planet_longitude_rate_deg_per_day(body, mid)
if f_left == 0:
return left
if f_right == 0:
return right
if f_left * f_mid <= 0:
right = mid
f_right = f_mid
else:
left = mid
f_left = f_mid
return left + (right - left) / 2
def action_outer_planet_stations_for_month(args: list[str]) -> dict:
if len(args) != 3:
fail(
"Aktion outer_planet_stations_for_month erwartet 3 Argumente: year month timezone",
extra={"argv": args},
)
try:
year = int(args[0])
month = int(args[1])
except ValueError as exc:
fail("Jahr oder Monat sind ungueltig.", extra={"details": str(exc), "argv": args})
if month < 1 or month > 12:
fail("Monat muss zwischen 1 und 12 liegen.", extra={"month": month})
timezone_name = args[2]
try:
tz = ZoneInfo(timezone_name)
except Exception as exc:
fail("Zeitzone ist ungueltig oder auf dem Server nicht verfuegbar.", extra={"details": str(exc)})
local_start = datetime(year, month, 1, 0, 0, 0, tzinfo=tz)
if month == 12:
local_end = datetime(year + 1, 1, 1, 0, 0, 0, tzinfo=tz)
else:
local_end = datetime(year, month + 1, 1, 0, 0, 0, tzinfo=tz)
utc_start = local_start.astimezone(timezone.utc)
utc_end = local_end.astimezone(timezone.utc)
scan_start = utc_start - timedelta(days=70)
scan_end = utc_end + timedelta(days=70)
scan_step = timedelta(hours=12)
planet_defs = [
("Mars", astronomy.Body.Mars, "mars"),
("Jupiter", astronomy.Body.Jupiter, "jupiter"),
("Saturn", astronomy.Body.Saturn, "saturn"),
("Uranus", astronomy.Body.Uranus, "uranus"),
("Neptun", astronomy.Body.Neptune, "neptune"),
]
events: list[dict] = []
for label, body, key in planet_defs:
current = scan_start
previous_time = current
previous_rate = planet_longitude_rate_deg_per_day(body, current)
current += scan_step
while current <= scan_end:
current_rate = planet_longitude_rate_deg_per_day(body, current)
if previous_rate == 0 or current_rate == 0 or previous_rate * current_rate < 0:
station_time_utc = refine_stationary_time(body, previous_time, current)
local_dt = station_time_utc.astimezone(tz)
if local_start <= local_dt < local_end:
rate_before = planet_longitude_rate_deg_per_day(body, station_time_utc - timedelta(days=3))
rate_after = planet_longitude_rate_deg_per_day(body, station_time_utc + timedelta(days=3))
if rate_before > 0 and rate_after < 0:
kind = "retrograde"
text = "stationaer, dann ruecklaeufig"
elif rate_before < 0 and rate_after > 0:
kind = "prograde"
text = "stationaer, dann rechtlaeufig"
else:
kind = "stationary"
text = "stationaer"
if not any(
item["planet_key"] == key and abs(datetime.fromisoformat(item["local_iso"]).timestamp() - local_dt.timestamp()) < 3600
for item in events
):
events.append({
"planet_key": key,
"planet_label": label,
"kind": kind,
"label": f"{label} {text}",
"utc_iso": station_time_utc.isoformat().replace("+00:00", "Z"),
"local_iso": local_dt.isoformat(),
"local_date": local_dt.strftime("%d.%m.%Y"),
"local_time": local_dt.strftime("%H:%M"),
})
previous_time = current
previous_rate = current_rate
current += scan_step
events.sort(key=lambda item: item["local_iso"])
return {
"ok": True,
"action": "outer_planet_stations_for_month",
"selected": {
"year": year,
"month": month,
"timezone": timezone_name,
},
"events": events,
}
def action_moon_star_occultations_for_month(args: list[str]) -> dict:
if len(args) != 7:
fail(
@@ -2364,7 +2510,7 @@ def action_satellite_passes(args: list[str]) -> dict:
def main() -> None:
if len(sys.argv) < 2:
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "outer_planet_events_for_month", "moon_star_occultations_for_month"]})
fail("Es wurde keine Aktion uebergeben.", extra={"available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "moon_star_occultations_for_month"]})
action = sys.argv[1]
args = sys.argv[2:]
@@ -2444,12 +2590,17 @@ def main() -> None:
print(json.dumps(result, ensure_ascii=False))
return
if action == "outer_planet_stations_for_month":
result = action_outer_planet_stations_for_month(args)
print(json.dumps(result, ensure_ascii=False))
return
if action == "moon_star_occultations_for_month":
result = action_moon_star_occultations_for_month(args)
print(json.dumps(result, ensure_ascii=False))
return
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "outer_planet_events_for_month", "moon_star_occultations_for_month"]})
fail("Unbekannte Aktion.", extra={"action": action, "available_actions": ["sun_moon_rise_set", "moon_star_occultations", "moon_phase_details", "satellite_passes", "planet_rise_set", "month_sky_context", "moon_phases_for_month", "season_changes_for_month", "moon_planet_approaches", "planet_conjunctions_for_month", "eclipses_for_month", "moon_apsides_for_month", "sun_apsides_for_month", "inner_planet_elongations_for_month", "outer_planet_events_for_month", "outer_planet_stations_for_month", "moon_star_occultations_for_month"]})
if __name__ == "__main__":