1. Фундаментальная Ошибка Прямоугольного Допущения
На плоской 2D-карте (например, в проекции Меркатора) Земля выглядит как прямоугольник с широтой от -90° до +90° и долготой от -180° до +180°.
Многие обучающие статьи советуют генерировать координаты по наивной формуле:
// ❌ Naive algorithm (Suffers from polar bias bug) const latitude = (Math.random() * 180) - 90; const longitude = (Math.random() * 360) - 180;
Хотя этот код выдает корректные числа, он считает площадь всех широт одинаковой. На реальной сфере длина параллели уменьшается как косинус широты:
На экваторе (0°) длина окружности составляет 40 075 км, а на 80° с.ш. — всего 6 950 км. Наивный алгоритм делает плотность точек на полюсах в 5,7 раза выше, чем на экваторе!
2. Равновеликое Сферическое Преобразование Марсальи
Чтобы точки распределялись по поверхности сферы абсолютно равномерно, плотность вероятности должна быть строго пропорциональна дифференциалу площади:
Поскольку дифференциал площади пропорционален d(sin θ), мы выбираем sin(θ) равномерно на отрезке [-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 };
}Это элегантное математическое решение гарантирует, что каждый квадратный километр на Земле имеет одинаковый шанс быть выбранным.
3. Выборка на Суше и Детерминированный PRNG
Около 71% поверхности Земли покрыто водой. Для генерации точек только на суше мы применяем метод отклонения:
- Генерация равновеликой сферической точки.
- Проверка принадлежности к векторным полигонам континентов.
- Если точка попала в океан, она отбрасывается и генерируется заново (до 250 попыток).
Для воспроизводимости наш движок объединяет 53-битный хеш cyrb53 с 32-битным генератором mulberry32, обеспечивая 100% детерминизм.