1. L’Errore Fondamentale del Modello Rettangolare
Su una mappa 2D (come Mercatore), la Terra appare come un rettangolo piatto con latitudine da -90° a +90° e longitudine da -180° a +180°.
Molti tutorial consigliano di generare coordinate con formule piane:
// ❌ Naive algorithm (Suffers from polar bias bug) const latitude = (Math.random() * 180) - 90; const longitude = (Math.random() * 360) - 180;
Anche se questo codice produce numeri validi, presuppone che tutte le fasce di latitudine abbiano la stessa area. Su una sfera reale, la circonferenza si riduce con il coseno della latitudine:
All’equatore (0°), la circonferenza è di 40.075 km. A 80° Nord, si riduce a soli 6.950 km. L’algoritmo piatto concentra 5,7 volte più punti ai poli che all’equatore!
2. La Trasformazione Sferica Equivalente di Marsaglia
Per distribuire uniformemente i punti sulla sfera, la densità di probabilità deve essere proporzionale all’elemento differenziale di superficie:
Poiché l’elemento di area è proporzionale a d(sin θ), campioniamo sin(θ) uniformemente nell’intervallo [-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 };
}Questa elegante trasformazione assicura che ogni chilometro quadrato sulla Terra abbia esattamente la stessa probabilità di essere selezionato.
3. Campionamento per Rifiuto su Terraferma e PRNG Deterministico
Circa il 71% della Terra è oceano. Quando l’utente sceglie solo terraferma, usiamo il campionamento per rifiuto:
- Generare un punto sferico equivalente.
- Verificare la posizione rispetto ai poligoni continentali.
- Se cade in mare, scartare e rigenerare fino a un massimo di 250 tentativi.
Per garantire la riproducibilità, il motore combina un hash cyrb53 a 53 bit con il PRNG mulberry32 a 32 bit, assicurando risultati deterministici al 100%.