Геометрические операции

Работа с геометрией в контексте веб-картографии строится вокруг преобразования, анализа и визуализации пространственных данных. В Mapbox GL JS геометрические операции реализуются через комбинацию встроенных методов API, GeoJSON-структур, математики проекций и внешних библиотек пространственного анализа.


Геометрическая модель Mapbox GL JS

Основой всех операций выступает GeoJSON. В Mapbox GL JS геометрии представлены четырьмя базовыми типами:

  • Point
  • LineString
  • Polygon
  • MultiGeometry (MultiPoint, MultiLineString, MultiPolygon)

Каждая операция в конечном счёте сводится к преобразованию массива координат в системе WGS84 (долгота, широта) и их проекции на экран через Web Mercator.

Ключевой момент: все вычисления пользовательской геометрии выполняются в географических координатах, а отрисовка — в пиксельных координатах.


Преобразование координат и система проекций

Mapbox GL JS использует Web Mercator (EPSG:3857). Это означает:

  • долгота и широта преобразуются в координаты плоскости
  • искажения возрастают к полюсам
  • прямые линии на карте не являются геодезическими

Основные методы преобразования:

  • map.project(lngLat) — перевод географических координат в пиксели
  • map.unproject(point) — обратное преобразование
  • map.getBounds() — получение текущих границ видимой области

Преобразования координат являются базой для всех геометрических вычислений на экране: измерений, столкновений, выделений и интерактивных операций.


Операции над точками

Расчёт расстояния

Расстояние между двумя точками чаще всего вычисляется через формулу гаверсинуса или библиотеку turf:

import * as turf from '@turf/turf';

const from = [37.6173, 55.7558];
const to = [30.3351, 59.9343];

const distance = turf.distance(from, to, { units: 'kilometers' });

Использование прямой евклидовой метрики недопустимо для глобальных координат, так как приводит к существенным искажениям.


Проверка принадлежности точки

Одна из базовых операций — определение, находится ли точка внутри полигона:

const point = turf.point([37.6, 55.7]);
const polygon = turf.polygon([[
  [37.0, 55.5],
  [38.0, 55.5],
  [38.0, 56.0],
  [37.0, 56.0],
  [37.0, 55.5]
]]);

const isInside = turf.booleanPointInPolygon(point, polygon);

Эта операция используется для:

  • фильтрации объектов
  • интерактивного выделения
  • анализа зон покрытия

Операции над линиями

Длина линии

Mapbox GL JS не вычисляет длину напрямую, но через Turf:

const line = turf.lineString([
  [37.6, 55.7],
  [38.6, 55.9]
]);

const length = turf.length(line, { units: 'kilometers' });

Интерполяция точек вдоль линии

Используется для анимации объектов или построения маршрутов:

const segment = turf.along(line, 10, { units: 'kilometers' });

Сглаживание линий

Геометрическая оптимизация формы линии:

const smooth = turf.bezierSpline(line);

Применяется для визуального улучшения маршрутов и контуров.


Операции над полигонами

Площадь

const area = turf.area(polygon);

Площадь вычисляется в квадратных метрах с учётом кривизны Земли.


Объединение и пересечение

Операции булевой геометрии:

const union = turf.union(poly1, poly2);
const intersect = turf.intersect(poly1, poly2);

Используются для:

  • агрегации зон
  • анализа пересечений территорий
  • построения сложных масок

Буферные зоны

Создание зон вокруг объектов:

const buffer = turf.buffer(point, 5, { units: 'kilometers' });

Буферизация применяется в задачах:

  • геозонирования
  • анализа доступности
  • визуализации влияния объектов

Геометрия в экранных координатах

Mapbox GL JS позволяет работать не только с географическими координатами, но и с пиксельной сеткой.

Преобразование в экранные координаты

const pixel = map.project([37.6173, 55.7558]);

Обратное преобразование

const lngLat = map.unproject([x, y]);

Эти операции критичны для:

  • drag-and-drop объектов
  • построения кастомных слоёв
  • обработки событий мыши

Геометрические запросы к рендеру

queryRenderedFeatures

Позволяет получать геометрические данные, попадающие в область:

const features = map.queryRenderedFeatures(
  [[0, 0], [300, 300]],
  { layers: ['buildings'] }
);

Используется для:

  • выделения объектов
  • анализа кликов
  • построения интерактивных инструментов

querySourceFeatures

Работает на уровне источника данных:

const features = map.querySourceFeatures('my-source');

Позволяет анализировать данные до рендеринга, включая скрытые или фильтрованные объекты.


Геометрические трансформации

Масштабирование

При изменении масштаба карты происходит:

  • пересчёт координат
  • перераспределение tile-геометрии
  • изменение плотности рендеринга

Поворот и наклон

Mapbox GL JS поддерживает:

  • bearing (поворот)
  • pitch (наклон)

Геометрически это означает применение матриц преобразования к сцене WebGL.


Геометрические ограничения и bounding box

Определение границ

const bounds = map.getBounds();

Bounding box используется для:

  • кластеризации данных
  • оптимизации загрузки
  • фильтрации видимых объектов

Проверка пересечения bbox

const bbox = turf.bbox(polygon);

Кластеризация как геометрическая операция

Хотя кластеризация воспринимается как визуальная функция, по сути это пространственное разбиение:

  • точки группируются по расстоянию
  • используется экранное или географическое расстояние
  • применяется grid-based или k-means логика

Mapbox GL JS поддерживает кластеризацию через источники:

map.addSource('points', {
  type: 'geojson',
  data: geojson,
  cluster: true,
  clusterRadius: 50
});

Геометрия событий мыши

События карты возвращают координаты:

map.on('click', (e) => {
  const coords = e.lngLat;
});

Дополнительно доступны:

  • e.point — пиксельные координаты
  • e.lngLat — географические координаты
  • e.features — геометрии под курсором

Эти данные используются для:

  • hit-testing
  • интерактивного редактирования геометрии
  • построения пользовательских инструментов рисования

Геометрия пользовательского рисования

При создании редакторов карт (drawing tools) применяются операции:

  • добавление вершин
  • удаление точек
  • пересчёт полигона в реальном времени
  • вычисление самопересечений

Типичная схема:

  1. пользователь добавляет точки
  2. формируется LineString
  3. при замыкании создаётся Polygon
  4. выполняется проверка валидности

Геометрические ошибки и топологическая валидность

Основные проблемы:

  • самопересекающиеся полигоны
  • дублирующиеся вершины
  • некорректный порядок обхода (clockwise / counterclockwise)
  • несоответствие MultiPolygon структуре

Для проверки используются:

turf.kinks(polygon);

или более сложные валидаторы топологии.


Производительность геометрических операций

Геометрические вычисления могут быть ресурсоёмкими, поэтому применяются оптимизации:

  • упрощение линий (Douglas-Peucker)
  • предрасчёт bbox
  • кэширование результатов
  • выполнение операций на Web Worker
const simplified = turf.simplify(geojson, { tolerance: 0.01 });

Взаимодействие с WebGL-слоем

В custom layers геометрия передаётся напрямую в WebGL:

  • координаты преобразуются в матрицы
  • геометрия разбивается на треугольники
  • выполняется рендеринг через буферы вершин

Это позволяет реализовывать:

  • 3D-объекты
  • кастомные визуализации
  • динамические поверхности