1. De Fundamentele Fout van de Rechthoek-Aanname
Op een 2D-kaart (zoals Mercator) lijkt de aarde een platte rechthoek met breedtegraad van -90° tot +90° en lengtegraad van -180° tot +180°.
Veel programmeerhandleidingen raden ten onrechte aan coördinaten zo te berekenen:
// ❌ Naive algorithm (Suffers from polar bias bug) const latitude = (Math.random() * 180) - 90; const longitude = (Math.random() * 360) - 180;
Hoewel dit geldige getallen oplevert, behandelt het alle breedtegraadbanden alsof ze dezelfde oppervlakte hebben. Op een bol krimpt de omtrek met de cosinus van de breedte:
Bij de evenaar (0°) is de omtrek 40.075 km. Op 80° Noord is dat nog slechts 6.950 km. Het platte algoritme maakt de puntdichtheid aan de polen 5,7 keer hoger dan aan de evenaar!
2. De Vlakgetrouwe Marsaglia-Boltransformatie
Om punten uniform over een boloppervlak te verdelen, moet de kansdichtheid strikt evenredig zijn met het differentiële oppervlakte-element:
Omdat het oppervlakte-element evenredig is met d(sin θ), kiezen we sin(θ) uniform in het interval [-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 };
}Deze elegante transformatie garandeert dat elke vierkante kilometer op aarde exact dezelfde selectiekans heeft.
3. Land-Rejection-Sampling en PRNG-Reproduceerbaarheid
Ongeveer 71% van de aarde bestaat uit water. Wanneer de gebruiker alleen land kiest, gebruiken we rejection sampling:
- Genereer een vlakgetrouw bolpunt.
- Controleer tegen continentale polygoongrenzen en vectoren.
- Als het punt in open oceaan valt, verwerp het en genereer opnieuw (maximaal 250 pogingen).
Voor reproduceerbaarheid combineert onze motor een 53-bits cyrb53-hash met een 32-bits mulberry32 PRNG, wat 100% deterministische uitkomsten garandeert.