1. Der Grundlegende Fehler der Rechteck-Annahme
Auf einer 2D-Kartenprojektion (wie Mercator) erscheint die Erde als flaches Rechteck mit Breitengraden von -90° bis +90° und Längengraden von -180° bis +180°.
Viele Programmier-Tutorials empfehlen naive Zufallskoordinaten:
// ❌ Naive algorithm (Suffers from polar bias bug) const latitude = (Math.random() * 180) - 90; const longitude = (Math.random() * 360) - 180;
Obwohl dieser Code gültige Zahlen liefert, behandelt er alle Breitengradbänder als flächengleich. Auf einer Kugel schrumpft der Umfang mit dem Kosinus der Breite:
Am Äquator (0°) beträgt der Umfang 40.075 km. Bei 80° Nord schrumpft er auf 6.950 km. Der naive Algorithmus erzeugt an den Polen eine 5,7-fach höhere Punktdichte als am Äquator!
2. Die Flächentreue Marsaglia-Sphärentransformation
Um Punkte gleichmäßig auf der Kugeloberfläche zu verteilen, muss die Wahrscheinlichkeitsdichte proportional zum differentiellen Flächenelement sein:
Da das Flächenelement proportional zu d(sin θ) ist, wählen wir sin(θ) gleichmäßig im Intervall [-1, 1]:
// ✅ Correct Archimedes-Lambert-Marsaglia equal-area algorithm:
function getRandomSpherePoint() {
const u = Math.random(); // Uniform in [0, 1)
const v = Math.random(); // Uniform in [0, 1)
// Invert the cumulative distribution function:
const sinLat = 2 * u - 1; // Uniform in [-1, 1]
const latRad = Math.asin(sinLat); // In radians
const lat = latRad * (180 / Math.PI); // In degrees [-90, +90]
const lng = -180 + v * 360; // In degrees [-180, +180]
return { lat, lng };
}Diese elegante Transformation garantiert, dass jeder Quadratkilometer auf der Erde die exakt gleiche Auswahlwahrscheinlichkeit besitzt.
3. Land-Rejection-Sampling und PRNG-Reproduzierbarkeit
Etwa 71 % der Erdoberfläche sind von Ozeanen bedeckt. Für Landpunkte nutzen wir Rejection Sampling:
- Flächentreuen Kugelpunkt generieren.
- Gegen kontinentale Polygon-Grenzwerte und Vektordaten prüfen.
- Falls auf offenem Meer gelegen, verwerfen und mit maximal 250 Versuchen neu generieren.
Für Reproduzierbarkeit nutzt unsere Engine einen 53-Bit cyrb53 Hash kombiniert mit dem 32-Bit mulberry32 PRNG, was 100% deterministische Ergebnisse sichert.