Skip to content

About

Sonnenfinsternis Prüfung

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SoFiChecker

Kleine PHP-Web-App zur Prüfung von Beobachtungsstandorten für Sonnen- und Mondfinsternisse.

SoFiChecker nimmt einen Ort, eine Adresse oder Koordinaten entgegen, berechnet lokale Finsterniszeiten, prüft Blickrichtung und Höhe von Sonne oder Mond und bewertet, ob Gelände oder kartierte Hindernisse die Beobachtung wahrscheinlich stören.

Projektstruktur und Deployment

Damit der Projektordner übersichtlich bleibt, sind Laufzeitdateien und Hilfsskripte jetzt getrennt:

  • Web-App-Laufzeit im Projektwurzelverzeichnis: index.php, app.js, styles.css, translations.js, templates/, assets/
  • lokale Hindernisdaten und Share-Daten: data/
  • Hindernis-Buildskripte: scripts/obstacles/
  • Log-Auswertung: scripts/logs/
  • lokale Entwicklungs- und Prüfhilfen: scripts/dev/
  • Testdaten und Import-Beispiele: tests/

Für einen schlanken Linux-Deploy brauchst du im Normalfall nicht jede Hilfsdatei aus der Entwicklung mitzunehmen. Für den eigentlichen Betrieb der App sind vor allem diese Bereiche relevant:

  • index.php
  • templates/
  • assets/
  • app.js
  • styles.css
  • app-config.js
  • eclipse-events.js
  • translations.js
  • announcement-translations.js
  • site.webmanifest
  • image_og.png
  • image_og.jpg
  • image_og.svg
  • DATA-LICENSE.md
  • THIRD-PARTY-LICENSES.md
  • data/obstacles/europe/

Nur wenn du direkt auf dem Server Daten nachladen oder prüfen willst, brauchst du zusätzlich:

  • scripts/obstacles/
  • scripts/dev/check-php-requirements.php

Was die App macht

Die App hilft dir bei einer sehr konkreten Frage: Ist ein bestimmter Standort für die Beobachtung einer Sonnen- oder Mondfinsternis geeignet?

Dafür beantwortet SoFiChecker unter anderem diese Punkte:

  • Wann beginnen dort die relevanten Finsternisphasen?
  • Wann liegt das Maximum?
  • Wann geht die Sonne unter oder wie hoch steht der Mond während der Phasen?
  • In welche Richtung musst du zu den wichtigen Zeitpunkten schauen?
  • Wie hoch stehen Sonne oder Mond dann noch über dem Horizont?
  • Gibt es Hinweise, dass Gelände, Gebäude, Industrieanlagen oder Vegetation die Sicht behindern könnten?
  • Gibt es in der Nähe einen etwas höheren Ausweichpunkt?

Zusätzlich erzeugt die App eine fertige .kml-Datei für Google Earth.

In vier Schritten zum Ergebnis

1. Finsternis auswählen

Du wählst das Ereignis aus, das du prüfen willst. Die App zeigt dazu Datum, Ereignistyp und eine kurze Einordnung der Sichtbarkeit.

2. Ort angeben

Du gibst eine Adresse, einen Ortsnamen oder Koordinaten ein oder klickst direkt in die Karte. Optional kannst du eine zusätzliche Beobachtungshöhe angeben, zum Beispiel für einen Aussichtspunkt, einen Turm oder eine Dachterrasse.

3. Sicht prüfen

Per Knopfdruck startet die Analyse. Dabei werden nacheinander Standort, Zeitzone, astronomische Phasen, Geländehöhen, kartierte Hindernisse und Sichtlinien verarbeitet. Der laufende Status wird bewusst sichtbar protokolliert.

4. Ergebnis anzeigen und weiterverwenden

Am Ende zeigt die App das Ergebnis in einfacher Sprache an, ergänzt um Karte, Sichtprüfung, Beobachtungsphasen und Profilansichten.

Was du mit dem Ergebnis machen kannst

Nach der Analyse kannst du das Ergebnis direkt weiter nutzen:

  • die wichtigsten Beobachtungszeitpunkte lesen
  • Blickrichtung und Höhe von Sonne oder Mond verstehen
  • Kartenlinien und Hindernishinweise prüfen
  • Horizont- und Seitenprofile vergleichen
  • eine .kml-Datei herunterladen
  • die Datei in Google Earth öffnen
  • das Ergebnis lokal speichern
  • einen Share-Link erzeugen und an andere weitergeben

Wichtige Grenzen der App

  • Die App ist eine vorsichtige Sichtprüfung, keine amtliche Freigabe.
  • OSM-Daten können unvollständig, veraltet oder lokal lückenhaft sein.
  • Nicht jedes einzelne Gebäude, jeder Baum und jede temporäre Struktur ist kartiert.
  • Baumhöhen und Gebäudehöhen sind teils explizit, teils heuristisch geschätzt.
  • Lokale Zugänglichkeit eines vorgeschlagenen Ausweichpunkts wird nicht rechtlich geprüft.
  • Wetter, Bewölkung, Baustellen, saisonales Blattwerk und mobile Hindernisse werden nicht erfasst.

Datenlizenz und Attribution

Die App verwendet für lokale Hindernisdaten aufbereitete OpenStreetMap-Daten aus Geofabrik-Extrakten.

Wichtig dafür:

  • Datenquelle und Attribution: OpenStreetMap
  • Quelldownloads unter anderem über Geofabrik
  • Lizenz der OSM-basierten Daten: ODbL 1.0

Kurzform für die sichtbare Attribution in App, Webseite oder Begleittexten:

Kartendaten / Hindernisdaten: OpenStreetMap, ODbL 1.0

Empfohlene Links:

Ausführliche Hinweise für dieses Projekt stehen in:

  • DATA-LICENSE.md
  • THIRD-PARTY-LICENSES.md

Dabei gilt:

  • DATA-LICENSE.md dokumentiert Datenquellen, Datenlizenzen und Attribution rund um OpenStreetMap, Geofabrik und lokale Hindernisdaten.
  • THIRD-PARTY-LICENSES.md dokumentiert lokal mitgelieferte Software-Bibliotheken wie astronomy-engine, tz-lookup und MapLibre GL JS.

Lokaler Start

  1. Terminal im Projektordner öffnen.
  2. Vorschau starten:
.\start-server.ps1
  1. Im Browser öffnen:
http://127.0.0.1:4173

Apache-Log nach häufigsten Koordinaten auswerten

Für Apache-Access-Logs gibt es jetzt das Skript scripts/logs/analyze-location-log.py.

Es sucht in Request-URLs wie /?lat=50.76380&lon=6.07527 nach Koordinaten, gruppiert sie und erzeugt eine Top-Liste der meistgenutzten Standorte.

Optional versucht es zusätzlich, per Nominatim einen sprechenden Ortsnamen zu ergänzen und legt dafür einen lokalen Cache an.

Beispiel: Top-100 mit Ortsnamen

python3 ./scripts/logs/analyze-location-log.py \
  /var/log/apache2/sofichecker/access.log \
  /var/log/apache2/sofichecker/access.log.1 \
  /var/log/apache2/sofichecker/access.log.2.gz

Beispiel: nur Koordinaten ohne Reverse Geocoding

python3 ./scripts/logs/analyze-location-log.py --no-reverse \
  /var/log/apache2/sofichecker/access.log \
  /var/log/apache2/sofichecker/access.log.1

Beispiel: zusätzlich JSON-Datei schreiben

python3 ./scripts/logs/analyze-location-log.py \
  --output-json ./data/log-analysis/top-locations.json \
  /var/log/apache2/sofichecker/access.log

Beispiel: direkt KML für Google Earth schreiben

python3 ./scripts/logs/analyze-location-log.py \
  --output-kml ./data/log-analysis/top-locations.kml \
  /var/log/apache2/sofichecker/access.log

Wichtige Optionen

  • --top 100 begrenzt die Zahl der Ausgabeeinträge
  • --precision 5 gruppiert nahe Koordinaten auf fünf Nachkommastellen
  • --no-reverse unterdrückt Ortsnamen und arbeitet nur mit Koordinaten
  • --cache-file ... setzt einen eigenen Cache-Pfad für Reverse Geocoding
  • --nominatim-email ... hängt eine Kontaktadresse an Nominatim-Anfragen an
  • --request-delay 1.1 setzt die Pause zwischen uncached Reverse-Geocoding-Anfragen
  • --output-kml ... schreibt die Top-Liste als KML-Datei für Google Earth

Ausgabeformat

Die Standardausgabe ist tab-getrennt und enthält:

  • Rang
  • Trefferzahl
  • Breite
  • Länge
  • Ortsbezeichnung oder Koordinaten-Fallback

Lokale Hindernisdaten auf dem Linux-Server nachladen

Die Hindernisprüfung kann mit lokalen Geofabrik-Daten befüllt werden. Dafür ist kein Overpass mehr nötig.

Voraussetzungen auf dem Server

  • Linux-Server mit bash
  • python3
  • genug freier Speicherplatz für Downloads, temporäre Dateien und erzeugte Tiles
  • Schreibrechte im Projektordner

Schnelltest:

python3 --version
bash --version

Builder-Dateien

Im Projekt liegen dafür jetzt diese Dateien:

  • scripts/obstacles/build-obstacle-dataset.py
  • scripts/obstacles/build-obstacle-dataset.sh

Der Shell-Wrapper startet einfach den Python-Builder mit python3.

Erstes sinnvolles Vorgehen

Nicht ganz Europa auf einmal laden, sondern in regionalen Paketen arbeiten.

Empfohlener Start:

  • luxembourg
  • germany/berlin
  • germany/hamburg
  • germany/nordrhein-westfalen/koeln-regbez

Das deckt schon viele deiner bisherigen Testfälle ab, ohne sofort riesige Datenmengen zu erzeugen.

Beispiel: Daten für diese Regionen bauen

Im Projektordner:

chmod +x ./scripts/obstacles/build-obstacle-dataset.sh
./scripts/obstacles/build-obstacle-dataset.sh --clean --regions \
  luxembourg \
  germany/berlin \
  germany/hamburg \
  germany/nordrhein-westfalen/koeln-regbez

Was dabei passiert:

  • Geofabrik-GeoPackages werden in data/obstacles/cache/ geladen
  • relevante OSM-Hindernisse werden extrahiert
  • JSON-Tiles werden unter data/obstacles/europe/tiles/ erzeugt
  • das Manifest wird nach data/obstacles/europe/manifest.json geschrieben

Beispiel: nur aus lokalem Cache neu bauen

Wenn die Zip-Dateien schon im Cache liegen und nichts neu geladen werden soll:

./scripts/obstacles/build-obstacle-dataset.sh --clean --skip-download --regions \
  luxembourg \
  germany/berlin \
  germany/hamburg \
  germany/nordrhein-westfalen/koeln-regbez

Regionen später einzeln ergänzen

Der Builder kann Regionen jetzt schrittweise hinzufügen.

Das bedeutet:

  • ohne --clean bleiben bestehende Tiles erhalten
  • neue Regionen werden zu den vorhandenen Tiles und zum Manifest hinzugefügt
  • du musst nicht jedes Mal erneut die komplette bisherige Regionsliste angeben

Beispiel:

./scripts/obstacles/build-obstacle-dataset.sh --regions germany/berlin

Wenn Berlin vorher noch nicht im Datensatz war, wird die Region jetzt zum bestehenden Bestand ergänzt.

Wichtig:

  • mit --clean wird weiterhin ein komplett neuer Datensatz aufgebaut
  • ohne --clean arbeitet der Builder additiv
  • bereits installierte Regionen werden dabei standardmäßig übersprungen
  • mit --rebuild-regions können vorhandene Regionen bewusst erneut verarbeitet werden

Bereits installierte Regionen anzeigen

./scripts/obstacles/build-obstacle-dataset.sh --list-installed

Das liest die Regionseinträge aus data/obstacles/europe/manifest.json.

Verfügbare Europa-Regionen anzeigen

./scripts/obstacles/build-obstacle-dataset.sh --list-available

Das lädt die aktuelle erste Europa-Ebene von Geofabrik und listet die dort verfügbaren Regions-Slugs auf.

Noch fehlende Regionen anzeigen

./scripts/obstacles/build-obstacle-dataset.sh --list-missing

Das vergleicht:

  • installierte Regionen aus dem aktuellen Manifest
  • verfügbare erste Europa-Ebene von Geofabrik

und gibt die noch nicht installierten Regionen aus.

Verfügbare Unterregionen unterhalb einer Region anzeigen

Wenn du tiefer in eine Region hineinschauen willst, etwa unter germany, geht das jetzt direkt:

./scripts/obstacles/build-obstacle-dataset.sh --list-available-subregions germany

Beispiele:

./scripts/obstacles/build-obstacle-dataset.sh --list-available-subregions germany
./scripts/obstacles/build-obstacle-dataset.sh --list-available-subregions germany/nordrhein-westfalen

Das listet jeweils die direkten Unterregionen der angegebenen Elternregion.

Wichtig:

  • nicht jede Elternregion bietet selbst ein latest-free.gpkg.zip
  • Beispiel: germany/nordrhein-westfalen verweist für GeoPackage auf die Regierungsbezirke darunter
  • in solchen Fällen musst du eine passende Unterregion wie germany/nordrhein-westfalen/koeln-regbez wählen

Noch fehlende Unterregionen unterhalb einer Region anzeigen

./scripts/obstacles/build-obstacle-dataset.sh --list-missing-subregions germany

Beispiele:

./scripts/obstacles/build-obstacle-dataset.sh --list-missing-subregions germany
./scripts/obstacles/build-obstacle-dataset.sh --list-missing-subregions germany/nordrhein-westfalen

Das vergleicht:

  • die direkt verfügbaren Unterregionen von Geofabrik
  • mit den bereits installierten Regions-Slugs im Manifest

und gibt die direkten Unterregionen aus, die dir noch fehlen.

Cache und temporäre Daten

Wichtige Ordner:

  • data/obstacles/cache/ enthält heruntergeladene Geofabrik-Zips
  • data/obstacles/tmp/ enthält nur temporäre Build-Dateien
  • data/obstacles/europe/tiles/ enthält die produktiven Tile-Dateien

Wenn ein Lauf abgebrochen wurde, kannst du temporäre Daten gefahrlos löschen:

rm -rf data/obstacles/tmp/*

Falls ein Download kaputt oder unvollständig im Cache liegt, lösche gezielt den betroffenen Regionsordner:

rm -rf data/obstacles/cache/germany/berlin

Danach kann die Region sauber neu geladen werden.

Was der Builder aktuell extrahiert

Der Builder beschränkt sich bewusst auf die Hindernisse, die die App wirklich auswertet:

  • Gebäude
  • Industrieflächen
  • Waldflächen
  • wood
  • Türme
  • Schornsteine

Nicht geladen werden unter anderem:

  • Straßen
  • allgemeine POIs
  • Wasserflächen
  • sonstige Landnutzung
  • ganz Europa in einem einzigen Schritt

Größenordnung und Empfehlung

Einzelne Regionen wie luxembourg oder germany/berlin sind gut beherrschbar. Größere Regionen wie germany/nordrhein-westfalen/koeln-regbez sind schon deutlich schwerer.

Empfehlung für den Serverbetrieb:

  • erst kleine Regionen testen
  • dann in sinnvollen Paketen ausbauen
  • nicht --all-europe benutzen, solange Speicherplatz und Laufzeit nicht bewusst dafür geplant sind

Nach dem Build prüfen

Prüfe mindestens:

ls -lh data/obstacles/europe/
ls -lh data/obstacles/europe/tiles | head

Das Manifest sollte danach echte Tile-Einträge enthalten und nicht mehr nur ein leeres tiles: [].

Deployment-Hinweis

Auf den Webserver gehören nur die erzeugten Produktivdaten:

  • data/obstacles/europe/manifest.json
  • data/obstacles/europe/tiles/

Die großen GeoPackage-Zips in data/obstacles/cache/ musst du nicht mit ausliefern, wenn der Build bereits auf dem Server selbst gelaufen ist.

Technische Architektur

Die Anwendung ist eine Single-Page-PHP-Seite:

  • index.php liefert HTML und stellt zugleich kleine Proxy-Endpunkte für externe Dienste bereit.
  • app.js enthält Eingabelogik, astronomische Berechnung, Sichtprüfung, Karten-Rendering und KML-Erzeugung.
  • translations.js enthält die UI-Texte in Deutsch, Englisch und Französisch.
  • styles.css enthält das Layout und das Design.
  • start-server.ps1 startet lokal den eingebauten PHP-Webserver.

Wichtig:

  • Die App ist nicht für reines GitHub Pages Hosting geeignet, weil sie PHP für die Proxy-Endpunkte benötigt.
  • Externe Dienste werden bewusst über dieselbe index.php aufgerufen, damit Browser-CORS-Probleme vermieden werden und zentrale Fehlerbehandlung möglich bleibt.

Eingaben

Unterstützte Standort-Eingaben

  • freie Adresse
  • Ortsname
  • bekannte Ortsbezeichnung
  • Dezimal-Koordinaten
  • Grad-Minuten-Sekunden-Notation
  • Grad-und-dezimale-Minuten-Notation

Beispiele:

  • Luxemburger Straße 170, 50939 Köln
  • Dom, Köln
  • 50.88748, 6.74429
  • 53,548699076930056, 9,978755385041094
  • 45°51'32.01"N 1°15'16.62"W
  • 40°42.768'N 74°00.360'W

URL-Parameter

Die App kann Koordinaten direkt aus der URL übernehmen.

Unterstützt werden:

  • lat
  • lon
  • observerHeight
  • h als Kurzform für observerHeight
  • lang für die UI-Sprache

Beispiel:

?lat=50.88748&lon=6.74429&observerHeight=2.5&lang=de

Sanity-Checks für URL-Parameter

Koordinaten aus der URL werden nur akzeptiert, wenn sie ein enges numerisches Format erfüllen.

Für lat und lon gilt:

  • nur Dezimalzahlen
  • optionales führendes Minuszeichen
  • maximal 24 Zeichen
  • Breite nur von -90 bis 90
  • Länge nur von -180 bis 180

Für observerHeight und h gilt:

  • nur nichtnegative Dezimalzahlen
  • maximal 16 Zeichen
  • höchstens zwei Nachkommastellen
  • Wertebereich 0 bis 500 Meter

Ungültige Werte werden verworfen und nicht in die Analyse übernommen.

Welche Zeiten und Blickrichtungen werden berechnet?

Die App berechnet für den Beobachtungsort diese Zeitpunkte:

  • Beginn der Finsternis
  • Maximum
  • 15 Minuten nach dem Maximum
  • 30 Minuten nach dem Maximum
  • Ende der Finsternis
  • zusätzlich kurz vor Sonnenuntergang, falls der Finsternisverlauf bis in diese Phase reicht

Für jeden dieser Zeitpunkte werden ermittelt:

  • lokale Uhrzeit
  • Sonnenazimut
  • menschenlesbare Blickrichtung wie Westnordwest
  • Sonnenhöhe über dem Horizont
  • anschauliche Zusatzbeschreibung wie Daumenbreite, Faust oder Elle

Wenn ein Zeitpunkt nach Sonnenuntergang liegt, wird er nicht mehr als Beobachtungszeitpunkt verwendet.

Welche Datenquellen und Dienste werden verwendet?

1. Nominatim für Geocoding und Reverse Geocoding

Verwendet für:

  • Umwandlung von Adresse oder Ortsname in Koordinaten
  • Ermittlung einer nahegelegenen Ortsbezeichnung für die Ausgabe

Aufrufe:

  • ?api=geocode&q=...
  • ?api=reverse&lat=...&lon=...

Externer Dienst:

  • OpenStreetMap Nominatim

Abgefragte Parameter:

  • q
  • lat
  • lon
  • intern zusätzlich format=jsonv2, limit=1, addressdetails=1, bei Reverse zoom=18

2. OpenTopoData für Geländehöhen

Verwendet für:

  • Geländehöhe des Beobachtungspunkts
  • Geländehöhen entlang aller Sichtlinien
  • Suche nach einem etwas höheren Ausweichpunkt in der Umgebung

Aufruf:

  • ?api=elevation&dataset=...&locations=...

Externer Dienst:

  • OpenTopoData

Abgefragte Parameter:

  • dataset
  • locations

Verwendete Datensätze:

  • eudem25m bevorzugt für Europa
  • mapzen als Fallback außerhalb dieses Bereichs

3. Lokale Europa-Dateien für kartierte Hindernisse

Verwendet für:

  • Gebäude
  • hohe Einzelbauwerke
  • Industrieflächen
  • Waldflächen
  • Baumreihen

Aufruf:

  • ?api=obstacles&south=...&west=...&north=...&east=...

Lokale Datenbasis:

  • data/obstacles/europe/manifest.json
  • darin referenzierte lokale Tile-Dateien

Wichtig:

  • Hindernisdaten werden nicht mehr live bei Overpass abgefragt.
  • Für die Sichtprüfung werden lokale Europa-Dateien serverseitig ausgelesen.
  • Außerhalb Europas meldet die App bewusst, dass für diese lokale Datenbasis derzeit keine Abdeckung vorliegt.
  • Wenn noch keine lokalen Datendateien installiert sind, wird das im Ergebnistext ausdrücklich genannt.

Das vermeidet Overpass-Limits, Timeouts und Abhängigkeiten von öffentlichen Drittinstanzen bei der Hindernisprüfung.

4. Astronomische Berechnung im Browser

Verwendete Bibliotheken:

  • astronomy-engine
  • tz-lookup

Verwendet für:

  • lokale Sonnenfinsternis am 12. August 2026
  • Sonnenuntergang
  • Sonnenposition zu jedem Beobachtungszeitpunkt
  • lokale IANA-Zeitzone des Standorts

Primärquellen der Berechnung

Für die eigentlichen Berechnungen stützt sich die App auf diese Primärquellen oder Primärdokumentationen:

1. Astronomy Engine

Verwendet für:

  • SearchLocalSolarEclipse
  • SearchLunarEclipse
  • SearchRiseSet
  • Equator
  • Horizon

Offizielle Quellen:

In der App eingesetzt für:

  • lokale Sonnenfinsternisse am Beobachtungsort
  • globale Mondfinsternis-Phasen
  • Sonnenuntergang
  • topozentrische Horizontal-Koordinaten von Sonne und Mond

2. Nominatim

Verwendet für:

  • freie Standortsuche per Text
  • Reverse Geocoding für nahe Ortsbezeichnungen

Offizielle Quellen:

3. OpenTopoData

Verwendet für:

  • Geländehöhen einzelner Punkte
  • Geländehöhen entlang von Sichtlinien

Offizielle Quellen:

4. OpenStreetMap / Geofabrik

Verwendet für:

  • lokale Hindernisdaten
  • Gebäudegrundrisse
  • Vegetation, Industrieflächen und ausgewählte man_made-Objekte

Offizielle Quellen:

5. Zeitzonen-Lookup

Verwendet für:

  • Zuordnung von Koordinaten zu einer IANA-Zeitzone
  • lokale Ausgabe mit Sommerzeit und korrekter Ortszeit

Offizielle Quellen:

Welche Formeln werden tatsächlich verwendet?

Dieser Abschnitt dokumentiert die mathematischen Formeln, die in app.js tatsächlich verwendet werden. Es geht dabei nicht um allgemeine Theorie, sondern um die konkret implementierten Rechenschritte.

Wichtig:

  • Eigene Geometrie-, Distanz- und Sichtlinienformeln der App werden hier vollständig dokumentiert.
  • Astronomische Kernrechnungen wie Finsternissuche, topozentrische Ephemeriden, Auf- und Untergänge stammen direkt aus astronomy-engine und werden deshalb nicht als Eigenformeln der App nachimplementiert.
  • Die App dokumentiert diese Bibliotheksaufrufe bewusst als Primärquelle und trennt sie von den eigenen Rechenschritten.

1. Großkreis-Zielpunkt aus Startpunkt, Peilung und Distanz

Verwendet in:

  • destinationPoint(...)

Zweck:

  • Endpunkte von Peillinien
  • Abtastpunkte entlang einer Sichtlinie
  • KML-Bodenlinien
  • KML-3D-Peilstrahlen

Formel:

angularDistance = distanceMeters / EARTH_RADIUS_METERS
bearingRad = degToRad(bearingDeg)
latRad = degToRad(lat)
lonRad = degToRad(lon)

destinationLat =
  asin(
    sin(latRad) * cos(angularDistance) +
    cos(latRad) * sin(angularDistance) * cos(bearingRad)
  )

destinationLon =
  lonRad +
  atan2(
    sin(bearingRad) * sin(angularDistance) * cos(latRad),
    cos(angularDistance) - sin(latRad) * sin(destinationLat)
  )

Danach wird die Länge wieder in den Bereich -180° bis +180° normalisiert.

2. Haversine-Distanz

Verwendet in:

  • haversineDistance(...)

Zweck:

  • Entfernung zwischen Beobachter und Hindernis
  • Distanzbewertung für Hindernis-Matching

Formel:

phi1 = degToRad(lat1)
phi2 = degToRad(lat2)
deltaPhi = degToRad(lat2 - lat1)
deltaLambda = degToRad(lon2 - lon1)

a =
  sin(deltaPhi / 2)^2 +
  cos(phi1) * cos(phi2) * sin(deltaLambda / 2)^2

c = 2 * atan2(sqrt(a), sqrt(1 - a))

distance = EARTH_RADIUS_METERS * c

3. Anfangspeilung zwischen zwei Punkten

Verwendet in:

  • computeBearing(...)

Zweck:

  • Richtung vom Beobachter zu kartierten Hindernissen
  • Vergleich zwischen Sonnen- oder Mondazimut und Hindernisrichtung

Formel:

phi1 = degToRad(lat1)
phi2 = degToRad(lat2)
lambda1 = degToRad(lon1)
lambda2 = degToRad(lon2)

y = sin(lambda2 - lambda1) * cos(phi2)
x =
  cos(phi1) * sin(phi2) -
  sin(phi1) * cos(phi2) * cos(lambda2 - lambda1)

bearing = normalizeBearing(radToDeg(atan2(y, x)))

4. Kleinste Winkeldifferenz zweier Richtungen

Verwendet in:

  • angularDifferenceDegrees(...)

Zweck:

  • Prüfung, ob ein Hindernis genügend nahe an der Blickrichtung liegt

Formel:

difference = abs(first - second)
if difference > 180 then difference = 360 - difference

5. Lokale Meterprojektion für Grundriss-Schnitte

Verwendet in:

  • convertGeoPointToLocalMeters(...)
  • convertLocalMetersToGeoPoint(...)
  • convertAzimuthToLocalVector(...)
  • intersectLineSegments(...)

Zweck:

  • Vereinfachte lokale 2D-Geometrie für Grundriss-Schnittberechnung

Formeln:

metersPerDegreeLongitude = 111320 * cos(degToRad(averageLatitude))
x = (point.lon - observer.lon) * metersPerDegreeLongitude
y = (point.lat - observer.lat) * 111320

Rückrichtung:

lat = observer.lat + (localY / 111320)
lon = observer.lon + (localX / metersPerDegreeLongitude)

Azimut-Vektor:

x = sin(azimuthRadians)
y = cos(azimuthRadians)

6. Scheinbarer Höhenwinkel eines Geländepunkts oder Hindernisses

Verwendet in:

  • computeApparentAngle(...)

Zweck:

  • maximalen Gelände- und Hinderniswinkel über dem lokalen Horizont bestimmen

Formel:

curvatureDrop = distanceMeters^2 / (2 * EARTH_RADIUS_METERS)
adjustedTargetElevation = targetGroundElevation + extraHeight - curvatureDrop
elevationDifference = adjustedTargetElevation - observerElevation
angleRad = atan2(elevationDifference, distanceMeters)
angleDeg = radToDeg(angleRad)

Wichtig:

  • Die App berücksichtigt hier eine einfache Erdkrümmungskorrektur.
  • Atmosphärische Refraktion wird in dieser eigenen Sichtlinienformel nicht zusätzlich modelliert.

7. 3D-KML-Höhenversatz einer Sonnen-Peillinie

Verwendet in:

  • calculateRayAltitudeOffset(...)

Zweck:

  • 3D-Sonnenlinie mit realistischer Steigung in Google Earth

Formel:

altitudeOffset = tan(degToRad(sunAltitude)) * horizontalDistance

8. Sonnen- und Mondposition im lokalen Horizontsystem

Verwendet in:

  • getSolarHorizontalCoordinates(...)
  • getMoonHorizontalCoordinates(...)

Zweck:

  • Azimut und Höhe von Sonne oder Mond zum jeweiligen Phasenzeitpunkt

Die App berechnet diese Werte nicht mit eigenen Tabellenformeln, sondern nutzt direkt:

  • Astronomy.Equator(...)
  • Astronomy.Horizon(...)

Damit stammen die eigentlichen topozentrischen Himmelskoordinaten vollständig aus Astronomy Engine.

9. Sonnenfinsternis-Sichtklassifikation

Verwendet in:

  • classifyVisibility(...)
  • classifyTerrainSegment(...)

Zweck:

  • Einordnung in good, warn oder bad

Feste Schwellwerte aus der App:

VISIBILITY_MARGIN_DEGREES = 0.35
CRITICAL_MARGIN_DEGREES = 0.8

Die Sichtlinie wird konservativ bewertet über:

  • Differenz zwischen Sonnenhöhe und stärkstem Geländewinkel
  • Differenz zwischen Sonnenhöhe und stärkstem Hinderniswinkel
  • Verfügbarkeit oder Fehlen der Hindernisdaten

Vereinfacht:

  • bad, wenn die Hindernisreserve <= 0.35° fällt
  • warn, wenn die Reserve klein ist oder Hindernisdaten fehlen
  • good, wenn ausreichend Reserve vorhanden ist

10. Mondfinsternis-Sichtklassifikation im aktuellen ersten Ausbau

Verwendet in:

  • classifyLunarAltitudeStatus(...)

Zweck:

  • schnelle erste Bewertung, ob der Mond während der Phasen überhaupt sinnvoll sichtbar ist

Schwellwerte:

bad  : moonAltitude <= 0°
warn : 0° < moonAltitude < 5°
good : moonAltitude >= 5°

Wichtig:

  • Diese erste Mondlogik bewertet aktuell nur die Horizonthöhe des Mondes.
  • Eine echte Hindernisprüfung für Mondfinsternisse ist im Codepfad noch nicht fertig.

Welche Parameter werden intern berechnet oder verwendet?

Standortbezogene Werte

  • geografische Breite
  • geografische Länge
  • zusätzliche Beobachtungshöhe über dem Gelände
  • Geländehöhe des Standorts
  • effektive Augenhöhe des Beobachters

Astronomische Werte

  • Beginn der partiellen Finsternis
  • Maximum
  • Ende der partiellen Finsternis
  • Sonnenuntergang
  • lokalisierte Uhrzeiten in der IANA-Zeitzone des Standorts
  • Azimut der Sonne
  • Höhe der Sonne

Geometrische Prüfwerte

  • Peillinienlänge: ungefähr 5 km
  • Abtastung des Geländes entlang der Linien
  • Winkel des Geländes über dem Horizont
  • Winkel kartierter Hindernisse über dem Horizont
  • Differenz zwischen Sonnenhöhe und größtem Hinderniswinkel

Was prüft die Sichtbarkeitsanalyse genau?

Die Analyse besteht aus mehreren Schritten.

1. Geländesicht

Für jede relevante Peillinie wird ein Höhenprofil über ungefähr 5 km berechnet.

Geprüft wird:

  • ob das Gelände in Blickrichtung ansteigt
  • wie groß der stärkste Geländewinkel über dem Horizont ist
  • wie viel Reserve zwischen Sonnenhöhe und Gelände bleibt

2. Kartierte Hindernisse

Zusätzlich werden lokal vorgehaltene OSM-Hindernisdaten entlang der Blickrichtung ausgewertet.

Berücksichtigt werden aktuell:

  • building
  • landuse=industrial
  • man_made=tower
  • man_made=chimney
  • landuse=forest
  • natural=wood
  • natural=tree_row

3. Vorsichtige Höhenannahmen

Wenn OSM keine explizite Höhe liefert, arbeitet die App mit vorsichtigen Heuristiken.

Beispiele:

  • Türme und Schornsteine: ungefähr 35 m
  • Industrieflächen: ungefähr 20 m
  • Baumreihen: ungefähr 18 m
  • Waldkanten: ungefähr 20 m
  • Gebäude: explizite OSM-Höhe oder Schätzung aus building:levels, roof:height und Gebäudetyp

Bei Gebäuden werden unter anderem ausgewertet:

  • height
  • building:height
  • roof:height
  • building:levels
  • building

4. Gebäudegrundrisse und Geometrien

Wenn die lokalen Datendateien Geometrien enthalten, werden diese genutzt, um:

  • Gebäudegrundrisse genauer auf die Sichtlinie zu schneiden
  • nahe Bauwerke realistischer zu bewerten
  • nicht nur den Schwerpunkt eines Objekts zu betrachten

5. Bewertung der Sicht

Die App klassifiziert jede Sichtlinie grob in:

  • voraussichtlich frei
  • teilweise gefährdet
  • wahrscheinlich verdeckt

Dabei fließen ein:

  • Sonnenhöhe
  • Geländewinkel
  • Winkel kartierter Hindernisse
  • verfügbare oder fehlende Datenabdeckung der Hindernisklassen

Wenn lokale Hindernisdaten nur teilweise oder gar nicht geladen werden konnten, wird das explizit im Ergebnistext erwähnt.

Welche Hindernisklassen werden im Ergebnis unterschieden?

Für die Lade- und Ausgabelogik werden die Hindernisse in drei Gruppen gegliedert:

  • Gebäude
  • weitere Bauwerke und Industrieflächen
  • Wald und Baumstrukturen

Das Ergebnis kann daher auch Teilinformationen ausgeben, zum Beispiel:

  • Gebäude wurden geprüft, Vegetation konnte nicht geladen werden
  • Gebäude und Bauwerke wurden geprüft, Walddaten fehlen

Karte und KML

Die App erzeugt:

  • Beobachtungspunkt
  • Peillinien für die relevanten Zeitpunkte
  • farbliche Bewertung der Linienabschnitte in der Karte
  • hervorgehobenes Maximum
  • markierte mögliche Hindernisse
  • gegebenenfalls einen grün markierten höheren Ausweichpunkt
  • eine fertige .kml-Datei zum Download

Die KML enthält unter anderem:

  • Beobachtungspunkt
  • Peillinien mit beschrifteten Ereignissen
  • Richtung und Sonnenhöhe
  • hervorgehobenes Maximum
  • optional den Ausweichpunkt

Kuratierte SoFi-Zonen für Karte und KML

Für die drei auswählbaren Sonnenfinsternisse enthält die App zusätzlich kuratierte Zonendaten für:

  • den Karten-Button direkt in der Ereignisauswahl
  • das OSM-Popup mit Zentralzone
  • den erklärenden KML-Zusatzlayer

Diese Daten liegen zentral im globalen Katalog window.SOFICHECKER_SOLAR_PATH_CATALOG in eclipse-events.js. Pro Sonnenfinsternis werden dort gepflegt:

  • northLimitStrings
  • southLimitStrings
  • centerLineStrings
  • viewport
  • sourceName
  • sourceUrl

Wichtige Einordnung:

  • Verwendet werden die Daten nur bei Sonnenfinsternissen mit gesetztem kmlPathKey.
  • Sie dienen dem erklärenden Karten- und KML-Overlay und nicht der eigentlichen Sichtprüfung am Standort.
  • Gezeigt wird jeweils ein bewusst kuratierter Ausschnitt, der zur Europa-Ausrichtung der App passt.

Format der Rohdaten:

  • jeder Eintrag ist eine Breite-Länge-Angabe mit Grad und Dezimalminuten
  • Beispiel: 71 59.5N 023 18.8W
  • zuerst Breite, dann Länge

Quelle:

  • kuratierte NASA-GSFC-Pfadkoordinaten aus den offiziellen Pfadtabellen der jeweiligen Sonnenfinsternis

Die Rohstrings werden in geografische Punkte umgerechnet und anschließend sowohl als Polygon für die Zone als auch als Linie für die Zentrallinie ausgegeben.

Ergebnistext

Die App erklärt die Analyse in alltagsnaher Sprache und beantwortet unter anderem:

  • wann man vor Ort sein sollte
  • in welche Richtung man schauen muss
  • wie hoch die Sonne beim Maximum steht
  • ob die Sicht wahrscheinlich frei ist
  • welche Hindernisse problematisch sein könnten
  • ob in der Nähe ein etwas höherer Ausweichpunkt vorgeschlagen wird

Fortschrittsanzeige während der Analyse

Die Statusanzeige beschreibt den Ablauf bewusst detailliert.

Typische Schritte sind:

  • Eingabe prüfen
  • Standort auflösen
  • Geländedaten laden
  • astronomische Zeiten berechnen
  • Geländeprofile vorbereiten
  • lokale Europa-Hindernisdaten laden
  • Hindernisgeometrien vorbereiten
  • einzelne Sichtlinien auswerten
  • Ergebnis und KML erzeugen

Für Geocoding und Geländehöhen weist die App weiterhin bewusst darauf hin, wenn Daten von externen Drittanbietern geladen werden.

Lokale API-Endpunkte in index.php

Die Seite stellt intern diese Endpunkte bereit:

  • ?api=geocode
  • ?api=reverse
  • ?api=elevation
  • ?api=obstacles
  • ?api=share-save
  • ?api=share-load

?api=obstacles ist dabei kein externer Proxy, sondern liest lokale Europa-Dateien anhand einer angeforderten Bounding Box aus.

Share-by-ID

Der Teilen-Button kann fertige Analyseergebnisse serverseitig speichern und daraus eine kurze URL mit ?share=... erzeugen.

Wichtig dabei:

  • Gespeichert wird nicht jede Analyse automatisch.
  • Ein serverseitiger SQLite-Eintrag entsteht nur nach aktivem Klick auf Teilen.
  • Die kurze Share-URL lädt das fertige Ergebnis später direkt wieder, ohne Neuberechnung.
  • Serverseitig wird der Share-Payload mit explizitem format und version gespeichert und beim Laden wieder geprüft.
  • Ältere bereits gespeicherte Share-Einträge ohne diese Hülle bleiben weiterhin lesbar und werden als Legacy-Format behandelt.
  • Lokal speichert der Browser erfolgreiche Analysen weiterhin zusätzlich in IndexedDB.
  • Jeder erfolgreiche Aufruf eines Share-Links erhöht serverseitig den Zugriffszähler und aktualisiert den letzten Aufrufzeitpunkt.

Für diese Funktion braucht der Server:

  • PDO
  • pdo_sqlite
  • Schreibrechte auf das Share-Verzeichnis des jeweiligen Systems:
  • Windows lokal: data/shared/
  • Linux-Server: /var/lib/sofichecker/

Admin-Seite für Share-Links

Für Kontrolle, Statistik, Verlängern, Sperren und Löschen gibt es eine separate Verwaltungsseite:

  • ?admin=shares

Die Seite ist per HTTP Basic Auth geschützt. Dafür müssen auf dem Server diese Umgebungsvariablen gesetzt sein:

  • SOFICHECKER_ADMIN_USER
  • SOFICHECKER_ADMIN_PASSWORD

Beispiel mit Apache-Umgebung oder Systemd-Umgebung:

SOFICHECKER_ADMIN_USER=adminname
SOFICHECKER_ADMIN_PASSWORD=sehr-langes-passwort

Die Admin-Seite zeigt unter anderem:

  • Anzahl aktiver, abgelaufener und gesperrter Share-Links
  • gesamte Aufrufzahl
  • letzter Aufruf pro Share-Link
  • Verlängerung des Ablaufdatums
  • Sperren, Reaktivieren und Löschen einzelner Einträge
  • Sammelaktion zum Löschen abgelaufener Links

Datenschutz und Drittanbieter

Bei Nutzung der App werden je nach Eingabe und Analyse Standortdaten an Drittanbieter übermittelt:

  • Nominatim für Geocoding und Reverse Geocoding
  • OpenTopoData für Geländehöhen

Übermittelt werden insbesondere:

  • Suchbegriffe oder Adressen
  • Koordinaten
  • Punktlisten für Höhenabfragen

Bounding Boxes für Hindernisabfragen bleiben bei der lokalen Europa-Datei-Prüfung auf dem eigenen Server.

Wenn ein Nutzer aktiv auf Teilen klickt, wird das serialisierte Analyseergebnis zusätzlich auf dem eigenen Server in SQLite gespeichert, damit eine kurze Share-ID daraus erzeugt werden kann.

Die App enthält keinen Nutzer-Account-Teil. Eine kleine SQLite-Datenbank wird nur für aktiv erzeugte Share-Links und deren Verwaltungsmetadaten verwendet.

Entwicklungshinweise

  • UI-Texte liegen zentral in translations.js.
  • Die Seite startet die Analyse nur nach Knopfdruck.
  • Koordinaten aus URL-Parametern werden streng validiert.
  • Die Hindernisprüfung liest lokale Europa-Dateien über ein Manifest in data/obstacles/europe/manifest.json.
  • Der Hindernis-Endpunkt akzeptiert nur streng validierte Bounding-Box-Parameter.
  • Wenn keine lokalen Europa-Dateien installiert sind, arbeitet die App weiter mit Gelände und Sonnenstand und kennzeichnet das Ergebnis vorsichtig.

Kurzfassung der externen Dienste

  • Nominatim: Adresse oder Ortsname zu Koordinaten und Ortsbezeichnung
  • OpenTopoData: Geländehöhen für Punkt und Sichtlinien
  • lokale Europa-Dateien: Gebäude, Industrie, Bauwerke, Wald und Baumstrukturen
  • Astronomy Engine: Finsternis, Sonnenposition, Sonnenuntergang
  • tz-lookup: lokale Zeitzone

About

Sonnenfinsternis Prüfung

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Used by

Contributors

Languages