diff --git a/config/rechtesystem.json b/config/rechtesystem.json index 8165f9e..cf111e2 100644 --- a/config/rechtesystem.json +++ b/config/rechtesystem.json @@ -76,6 +76,10 @@ "label": "Sternenhimmel", "menu_group": "Himmel & Planeten" }, + "drehbare_sternkarte.php": { + "label": "Drehbare Sternkarte", + "menu_group": "Himmel & Planeten" + }, "meteorshowers.php": { "label": "Meteorstroeme", "menu_group": "Himmel & Planeten" @@ -132,6 +136,7 @@ "jupitersystem.php", "tagbogen.php", "sternenhimmel.php", + "drehbare_sternkarte.php", "meteorshowers.php", "geocron/index.php", "geocron3d.php" diff --git a/public/auth_helpers.php b/public/auth_helpers.php index d83328a..15c706c 100644 --- a/public/auth_helpers.php +++ b/public/auth_helpers.php @@ -123,6 +123,7 @@ function manageablePublicPages(): array 'jupitersystem.php' => 'Jupitersystem', 'tagbogen.php' => 'Tagbogen', 'sternenhimmel.php' => 'Sternenhimmel', + 'drehbare_sternkarte.php' => 'Drehbare Sternkarte', 'meteorshowers.php' => 'Meteorströme', 'geocron/index.php' => 'Geocron', 'geocron3d.php' => 'Geocron 3D', diff --git a/public/drehbare_sternkarte.php b/public/drehbare_sternkarte.php new file mode 100644 index 0000000..33bd5d6 --- /dev/null +++ b/public/drehbare_sternkarte.php @@ -0,0 +1,1251 @@ + []]; +$constellationDataError = null; +$messierData = []; +$messierDataError = null; +$availableLocations = []; +$starDbMagLimit = 7.4; +$pdo = null; + +try { + $dbConfig = require __DIR__ . '/../config/database.php'; + $dsn = sprintf( + 'mysql:host=%s;dbname=%s;charset=%s', + $dbConfig['host'], + $dbConfig['dbname'], + $dbConfig['charset'] ?? 'utf8mb4' + ); + $pdo = new PDO($dsn, $dbConfig['user'], $dbConfig['pass'], [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + ]); + + $constellations = []; + $ensureConstellation = static function (string $id) use (&$constellations): void { + if (!isset($constellations[$id])) { + $constellations[$id] = [ + 'id' => $id, + 'lines' => [], + 'label_positions' => [], + 'common_name' => [ + 'german' => null, + 'native' => null, + 'byname' => null, + ], + ]; + } + }; + + $nameStmt = $pdo->query( + "SELECT constellation_id, german_name, native_name, byname + FROM constellation_names + ORDER BY constellation_id" + ); + foreach ($nameStmt as $row) { + $id = (string) $row['constellation_id']; + $ensureConstellation($id); + $constellations[$id]['common_name'] = [ + 'german' => $row['german_name'] !== null ? (string) $row['german_name'] : null, + 'native' => $row['native_name'] !== null ? (string) $row['native_name'] : null, + 'byname' => $row['byname'] !== null ? (string) $row['byname'] : null, + ]; + } + + $labelStmt = $pdo->query( + "SELECT constellation_id, position_index, ra_hours, dec_degrees + FROM constellation_label_positions + ORDER BY constellation_id, position_index" + ); + foreach ($labelStmt as $row) { + $id = (string) $row['constellation_id']; + $ensureConstellation($id); + $constellations[$id]['label_positions'][] = [ + (float) $row['ra_hours'], + (float) $row['dec_degrees'], + ]; + } + + $lineStmt = $pdo->query( + "SELECT cl.constellation_id, cl.line_index, clp.point_index, clp.hip_number + FROM constellation_lines cl + INNER JOIN constellation_line_points clp ON clp.line_id = cl.id + ORDER BY cl.constellation_id, cl.line_index, clp.point_index" + ); + foreach ($lineStmt as $row) { + $id = (string) $row['constellation_id']; + $lineIndex = (int) $row['line_index']; + $ensureConstellation($id); + $constellations[$id]['lines'][$lineIndex] ??= []; + $constellations[$id]['lines'][$lineIndex][] = (int) $row['hip_number']; + } + + foreach ($constellations as &$constellation) { + if ($constellation['lines']) { + ksort($constellation['lines']); + $constellation['lines'] = array_values($constellation['lines']); + } + } + unset($constellation); + + uasort( + $constellations, + static fn(array $a, array $b): int => strcmp($a['id'], $b['id']) + ); + + if ($starsApiRequested) { + $stars = []; + $starStmt = $pdo->query( + "SELECT hip, proper, bayer, con, spect, mag, ci, rarad, decrad + FROM star_hipparcos + WHERE mag IS NOT NULL + AND rarad IS NOT NULL + AND decrad IS NOT NULL + AND mag <= " . (float) $starDbMagLimit . " + ORDER BY mag ASC" + ); + while ($row = $starStmt->fetch()) { + $stars[] = [ + 'hip' => $row['hip'] !== null ? (int) $row['hip'] : null, + 'proper' => trim((string) ($row['proper'] ?? '')), + 'bayer' => trim((string) ($row['bayer'] ?? '')), + 'con' => trim((string) ($row['con'] ?? '')), + 'spect' => trim((string) ($row['spect'] ?? '')), + 'ra' => (float) $row['rarad'], + 'dec' => (float) $row['decrad'], + 'mag' => (float) $row['mag'], + 'ci' => $row['ci'] !== null ? (float) $row['ci'] : null, + ]; + } + + header('Content-Type: application/json; charset=utf-8'); + echo json_encode([ + 'ok' => true, + 'stars' => $stars, + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + exit; + } + + $constellationData['constellations'] = array_values($constellations); + + $messierStmt = $pdo->query( + "SELECT messier, name, object_type_abrev, ra_deg, dec_deg, v_mag, major_axis + FROM dso_objects + WHERE messier IS NOT NULL + AND messier <> '' + AND ra_deg IS NOT NULL + AND dec_deg IS NOT NULL + ORDER BY CAST(REGEXP_REPLACE(messier, '[^0-9]', '') AS UNSIGNED)" + ); + while ($row = $messierStmt->fetch()) { + if (!preg_match('/(\d+)/', (string) $row['messier'], $m)) { + continue; + } + $messierData[] = [ + 'm' => (int) $m[1], + 'name' => trim((string) ($row['name'] ?? '')), + 'type' => trim((string) ($row['object_type_abrev'] ?? 'As')), + 'ra' => ((float) $row['ra_deg']) / 15.0, + 'dec' => (float) $row['dec_deg'], + 'mag' => $row['v_mag'] !== null ? (float) $row['v_mag'] : 99.0, + 'size' => $row['major_axis'] !== null ? (float) $row['major_axis'] : 8.0, + ]; + } + + if ($loggedIn && isset($_SESSION['user_id'])) { + $locationStmt = $pdo->prepare( + "SELECT id, name, latitude, longitude, elevation, timezone, is_default + FROM app_user_locations + WHERE user_id = ? + ORDER BY is_default DESC, name ASC, id ASC" + ); + $locationStmt->execute([(int) $_SESSION['user_id']]); + while ($row = $locationStmt->fetch()) { + if ($row['latitude'] === null || $row['longitude'] === null) { + continue; + } + $availableLocations[] = [ + 'id' => $row['id'] !== null ? (int) $row['id'] : null, + 'name' => trim((string) ($row['name'] ?? 'Standort')), + 'latitude' => (float) $row['latitude'], + 'longitude' => (float) $row['longitude'], + 'elevation' => $row['elevation'] !== null ? (float) $row['elevation'] : 0.0, + 'timezone' => trim((string) ($row['timezone'] ?? 'Europe/Berlin')), + 'is_default' => !empty($row['is_default']), + ]; + } + } +} catch (Throwable $e) { + if ($starsApiRequested) { + header('Content-Type: application/json; charset=utf-8'); + http_response_code(500); + echo json_encode([ + 'ok' => false, + 'error' => $e->getMessage(), + ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + exit; + } + $constellationDataError = $e->getMessage(); + $messierDataError = $e->getMessage(); +} + +$constellationDataJson = json_encode($constellationData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +$constellationDataErrorJson = json_encode($constellationDataError, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +$messierDataJson = json_encode($messierData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); +$messierDataErrorJson = json_encode($messierDataError, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); + +require __DIR__ . '/header.php'; + +$chartLocation = [ + 'id' => null, + 'name' => 'Sternwarte Sonneberg', + 'latitude' => 50.3547, + 'longitude' => 11.1900, + 'elevation' => 640.0, + 'timezone' => 'Europe/Berlin', +]; + +if (!empty($currentLocation) && is_array($currentLocation)) { + $chartLocation = [ + 'id' => isset($currentLocation['id']) ? (int) $currentLocation['id'] : null, + 'name' => (string) ($currentLocation['name'] ?? 'Standard-Standort'), + 'latitude' => isset($currentLocation['latitude']) ? (float) $currentLocation['latitude'] : 50.3547, + 'longitude' => isset($currentLocation['longitude']) ? (float) $currentLocation['longitude'] : 11.1900, + 'elevation' => isset($currentLocation['elevation']) && $currentLocation['elevation'] !== null ? (float) $currentLocation['elevation'] : 0.0, + 'timezone' => trim((string) ($currentLocation['timezone'] ?? 'Europe/Berlin')), + ]; +} + +if (!$availableLocations) { + $availableLocations[] = [ + 'id' => $chartLocation['id'], + 'name' => $chartLocation['name'], + 'latitude' => $chartLocation['latitude'], + 'longitude' => $chartLocation['longitude'], + 'elevation' => $chartLocation['elevation'], + 'timezone' => $chartLocation['timezone'], + 'is_default' => true, + ]; +} +?> + + + + + + + + + Sternscheibe wird geladen… + Ziehen zum Drehen + + + + + + + + diff --git a/public/header.php b/public/header.php index e4966a1..7a84208 100644 --- a/public/header.php +++ b/public/header.php @@ -152,6 +152,7 @@ $menuGroups = [ ['href' => 'jupitersystem.php', 'label' => 'Jupitersystem'], ['href' => 'tagbogen.php', 'label' => 'Tagbogen'], ['href' => 'sternenhimmel.php', 'label' => 'Sternenhimmel'], + ['href' => 'drehbare_sternkarte.php', 'label' => 'Drehbare Sternkarte'], ['href' => 'satellitenhimmel.php', 'label' => 'Satellitenhimmel'], ['href' => 'meteorshowers.php', 'label' => 'Meteorströme'], ['href' => 'asteroid_temp.php', 'label' => 'Asteroid-Temperatur'],