Centroid и center

В архитектуре Mapbox GL JS центральное понятие — камера карты, определяющая, какой участок мира отображается в текущий момент. Камера описывается набором параметров: center, zoom, bearing, pitch. Среди них center задаёт географическую точку, которая проецируется в центр canvas.

const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/streets-v12',
  center: [69.2401, 53.2145],
  zoom: 9
});

Значение center — это не геометрический центр объектов, а точка фокуса камеры, вокруг которой строится визуализация сцены.

Основные операции с центром камеры

map.setCenter([69.2401, 53.2145]);
const currentCenter = map.getCenter();

setCenter изменяет положение камеры, сохраняя остальные параметры. getCenter возвращает текущее положение камеры в координатах [lng, lat].

Важно понимать: центр камеры всегда связан с экранной геометрией — это точка, которая проецируется в пиксель центра canvas (width/2, height/2), независимо от распределения объектов на карте.


Геометрический центроид (centroid) геообъектов

Центроид — это геометрический центр фигуры, вычисляемый на основе координат её вершин. В контексте GeoJSON это характеристика конкретной геометрии: Point, Polygon, MultiPolygon.

Для полигона центроид — это точка, которая минимизирует среднеквадратичное расстояние до всех точек фигуры или, в упрощённом виде, является “балансной точкой” площади.

Пример GeoJSON объекта:

const polygon = {
  type: "Feature",
  geometry: {
    type: "Polygon",
    coordinates: [[
      [69.2, 53.2],
      [69.4, 53.2],
      [69.4, 53.3],
      [69.2, 53.3],
      [69.2, 53.2]
    ]]
  }
};

Особенности центроида

  • зависит от формы объекта, а не от камеры
  • может находиться вне полигона (для вогнутых фигур)
  • чувствителен к плотности и распределению вершин
  • для MultiPolygon требует взвешивания по площади

Разница между camera center и centroid

Несмотря на схожесть терминов, это принципиально разные концепции.

Параметр center (камера) centroid (геометрия)
Природа визуальная математическая
Зависит от положения карты формы объекта
Меняется при pan/zoom да нет
Привязан к экрану да нет
Может быть вне объекта да да

Ключевая разница

  • center отвечает за то, что видно
  • centroid отвечает за структуру объекта

Практическое применение различий

Размещение маркера

Если требуется поставить маркер “в центре объекта”, использование map.getCenter() некорректно. Камера может быть смещена пользователем.

Корректный подход — вычисление центроида:

import centroid from '@turf/centroid';

const centerPoint = centroid(polygon);

Далее:

new mapboxgl.Marker()
  .setLngLat(centerPoint.geometry.coordinates)
  .addTo(map);

Центрирование карты по объекту

Если требуется наоборот — переместить камеру так, чтобы объект оказался по центру экрана:

map.flyTo({
  center: centerPoint.geometry.coordinates,
  zoom: 12
});

Здесь происходит обратное преобразование: геометрический центроид становится центром камеры.


Центроид и сложные геометрии

MultiPolygon

Для составных объектов простое усреднение координат даёт искажения. Корректный центроид должен учитывать площади частей.

Пример проблемы:

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

Правильный центроид:

  • вычисляется как сумма центроидов частей, взвешенных по площади

Bounding box center (центр ограничивающего прямоугольника)

Альтернативный способ получить “центр объекта” — использовать bounding box:

[minLng, minLat, maxLng, maxLat]

Центр вычисляется как:

const center = [
  (minLng + maxLng) / 2,
  (minLat + maxLat) / 2
];

В экосистеме Mapbox GL JS часто используется метод:

map.fitBounds(bounds);

Он автоматически вычисляет центр bounding box и подстраивает камеру.


Визуальный центр и искажения проекции

Mapbox GL JS использует Web Mercator projection, в которой:

  • масштабы искажаются к полюсам
  • площади объектов визуально неравномерны
  • геометрический центроид не всегда совпадает с “визуальным центром”

Пример искажения

Один и тот же полигон:

  • на экваторе выглядит равномерно
  • в северных широтах растягивается

Это приводит к тому, что:

  • centroid остаётся стабильным
  • визуальный центр смещается

Центроид через screen-space координаты

Иногда требуется найти центр не в географических координатах, а в пикселях:

const centerPixel = map.project([lng, lat]);

И обратное преобразование:

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

Это важно при работе с UI-слоями, tooltip, overlay и кастомными контролами.


Центрирование по набору точек

Если есть набор точек (например, результаты queryRenderedFeatures):

const features = map.queryRenderedFeatures({ layers: ['points'] });

Можно вычислить средний центр:

let lngSum = 0;
let latSum = 0;

features.forEach(f => {
  lngSum += f.geometry.coordinates[0];
  latSum += f.geometry.coordinates[1];
});

const center = [
  lngSum / features.length,
  latSum / features.length
];

Однако такой подход игнорирует плотность и площадь влияния объектов.


Центроид и визуальные слои

В слоях типа symbol, circle, heatmap центроид часто используется как:

  • anchor для подписи
  • точка размещения интерактивного popup
  • позиция кластерного маркера

Пример label placement

map.addLayer({
  id: 'labels',
  type: 'symbol',
  source: 'areas',
  layout: {
    'text-field': ['get', 'name'],
    'text-anchor': 'center'
  }
});

Здесь Mapbox автоматически использует центроид полигона для позиционирования текста.


Смещение центра при интерактивности

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

  • drag → изменение center
  • zoom → изменение scale вокруг center
  • rotate → изменение bearing относительно center

При этом геометрический центроид остаётся неизменным.

Это приводит к важному разделению:

  • camera center — динамический
  • geometry centroid — статический

Fit bounds и скрытая централизация

map.fitBounds([
  [69.1, 53.1],
  [69.5, 53.5]
]);

Внутри этого метода:

  • вычисляется bounding box center
  • определяется оптимальный zoom
  • центр камеры устанавливается автоматически

Таким образом, fitBounds фактически работает через центр bbox, а не через centroid геометрий.


Центроид в аналитике и агрегации

В геоаналитике centroid используется для:

  • кластеризации регионов
  • агрегации административных зон
  • построения heatmap-центров
  • вычисления географических “представителей” объектов

В Mapbox GL JS это часто комбинируется с GeoJSON sources:

map.addSource('regions', {
  type: 'geojson',
  data: geojsonData
});

Далее слой может использовать вычисленные центроиды как отдельный dataset.


Итоговая логика различий в архитектуре Mapbox GL JS

  • center — параметр камеры, определяющий отображение сцены
  • centroid — свойство геометрии, определяющее её математическую структуру
  • bounding box center — компромиссный способ централизации
  • screen center — экранная проекция точки камеры

Эти понятия формируют разные уровни одной системы:

  • геометрия данных
  • визуальная камера
  • экранная проекция