📐 Przewodnik Matematyczny i Dowód

Jak Działają Losowe Współrzędne: Prawda Sferyczna

Dlaczego większość generatorów w sieci jest matematycznie błędna i jak rzut wiernościenny daje prawdziwie jednolite punkty.

📐 Ścisłość Matematyczna

Wiernościenny Rozkład Sferyczny vs. Błąd Biegunowy

Większość darmowych narzędzi traktuje Ziemię jak płaski prostokąt. Zobacz, jak nasza matematyka zapewnia całkowitą poprawność.

❌ Naiwna Siatka Płaska (Błąd Konkurencji)

Błędne
// ❌ Flat 2D Rectangular Bug:
const lat = (Math.random() * 180) - 90;
const lng = (Math.random() * 360) - 180;

Istota Problemu: Pas 1° na równiku ma 40 075 km, a na 80°N zaledwie 6 950 km. Jednostajny wybór szerokości zawyża bieguny o 400%.

✅ Wiernościenna Metoda Marsaglii (Nasz Algorytm)

Zweryfikowane i Dokładne
// ✅ Marsaglia Equal-Area Sphere Math:
const u = Math.random();
const lat = Math.asin(2 * u - 1) * (180 / Math.PI);
const lng = -180 + Math.random() * 360;

Rozwiązanie: Jednostajne losowanie sinusa szerokości sin(θ) całkowicie kompensuje kurczenie cos(lat). Każdy km² ma równe szanse.

1. Fundamentalny Błąd Założenia Prostokątnego

Na płaskiej mapie 2D (jak rzut Mercatora) Ziemia wygląda jak prostokąt o szerokości od -90° do +90° i długości od -180° do +180°.

Wiele poradników niesłusznie sugeruje generowanie współrzędnych w ten sposób:

// ❌ Naive algorithm (Suffers from polar bias bug)
const latitude = (Math.random() * 180) - 90;
const longitude = (Math.random() * 360) - 180;

Choć ten kod daje poprawne liczby, zakłada, że wszystkie pasy szerokości mają taką samą powierzchnię. Na kuli obwód równoleżnika zmniejsza się z cosinusem szerokości:

Circumference(θ) = 2πR · cos(θ)

Na równiku (0°) obwód wynosi 40 075 km, a na 80°N zaledwie 6 950 km. Płaski algorytm generuje na biegunach 5,7 razy większą gęstość punktów niż na równiku!

2. Wiernościenna Sferyczna Transformacja Marsaglii

Aby punkty rozkładały się równomiernie na kuli, gęstość prawdopodobieństwa musi być ściśle proporcjonalna do elementu powierzchni:

dA = R² · cos(θ) dθ dφ = R² · d(sin θ) dφ

Ponieważ element powierzchni jest proporcjonalny do d(sin θ), losujemy sin(θ) jednostajnie w przedziale [-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 };
}

Ta elegancka transformacja matematyczna gwarantuje, że każdy kilometr kwadratowy na Ziemi ma dokładnie taką samą szansę na wylosowanie.

3. Próbkowanie z Odrzuceniem na Lądzie i PRNG

Około 71% Ziemi to oceany. Gdy użytkownik wybierze tylko ląd, stosujemy próbkowanie z odrzuceniem:

  1. Wygeneruj wiernościenny punkt sferyczny.
  2. Sprawdź przynależność do wektorowych wielokątów kontynentów.
  3. Jeśli punkt trafi w ocean, odrzuć go i ponów próbę (do 250 razy).

Dla powtarzalności nasz silnik łączy 53-bitowy hash cyrb53 z 32-bitowym generatorem mulberry32, gwarantując w 100% deterministyczne wyniki.