Polygon геометрия

Структура Polygon в GeoJSON

Полигональная геометрия в MapLibre GL JS основана на стандарте GeoJSON, где объект типа Polygon представляет замкнутую область на поверхности карты. Координаты задаются в порядке [долгота, широта], что критически важно для корректного отображения.

Базовая структура полигона:

{
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [30.31413, 59.93863],
        [30.32000, 59.93863],
        [30.32000, 59.94200],
        [30.31413, 59.94200],
        [30.31413, 59.93863]
      ]
    ]
  },
  "properties": {}
}

Первый элемент массива координат — внешний контур. Последняя точка должна совпадать с первой, формируя замкнутую область.

Внутренние кольца (holes)

Polygon может содержать отверстия, задаваемые внутренними кольцами. Они добавляются как дополнительные массивы координат внутри основного массива:

{
  "type": "Polygon",
  "coordinates": [
    [
      [30.30, 59.93],
      [30.33, 59.93],
      [30.33, 59.95],
      [30.30, 59.95],
      [30.30, 59.93]
    ],
    [
      [30.31, 59.935],
      [30.32, 59.935],
      [30.32, 59.945],
      [30.31, 59.945],
      [30.31, 59.935]
    ]
  ]
}

Первое кольцо — внешний контур, последующие — вырезы.

MultiPolygon

Для представления нескольких независимых областей используется тип MultiPolygon:

{
  "type": "MultiPolygon",
  "coordinates": [
    [
      [
        [30.1, 59.9],
        [30.2, 59.9],
        [30.2, 60.0],
        [30.1, 60.0],
        [30.1, 59.9]
      ]
    ],
    [
      [
        [30.3, 59.9],
        [30.4, 59.9],
        [30.4, 60.0],
        [30.3, 60.0],
        [30.3, 59.9]
      ]
    ]
  ]
}

Каждый полигон внутри массива полностью независим.


Подключение Polygon к MapLibre GL JS

Полигональная геометрия отображается через source типа geojson и слой fill.

const map = new maplibregl.Map({
  container: 'map',
  style: 'https://demotiles.maplibre.org/style.json',
  center: [30.31, 59.94],
  zoom: 12
});

map.on('load', () => {
  map.addSource('area', {
    type: 'geojson',
    data: {
      type: 'Feature',
      geometry: {
        type: 'Polygon',
        coordinates: [
          [
            [30.30, 59.93],
            [30.33, 59.93],
            [30.33, 59.95],
            [30.30, 59.95],
            [30.30, 59.93]
          ]
        ]
      }
    }
  });

  map.addLayer({
    id: 'area-fill',
    type: 'fill',
    source: 'area',
    paint: {
      'fill-color': '#3b82f6',
      'fill-opacity': 0.5
    }
  });
});

Ключевой слой для полигона — fill. Он отвечает за заливку области.


Обводка полигона

Для визуального выделения границ используется отдельный слой типа line.

map.addLayer({
  id: 'area-outline',
  type: 'line',
  source: 'area',
  paint: {
    'line-color': '#1e3a8a',
    'line-width': 2
  }
});

Разделение fill и line слоёв — стандартная практика, позволяющая независимо управлять заливкой и контуром.


Fill extrusion: объёмные полигоны

MapLibre GL JS поддерживает 3D-экструзию через слой fill-extrusion, где полигон «выдавливается» в пространство.

map.addLayer({
  id: 'area-3d',
  type: 'fill-extrusion',
  source: 'area',
  paint: {
    'fill-extrusion-color': '#10b981',
    'fill-extrusion-height': 200,
    'fill-extrusion-opacity': 0.7
  }
});

Высота может быть статической или вычисляться через выражения:

'fill-extrusion-height': ['get', 'height']

Правила ориентации координат (winding order)

Направление обхода координат влияет на интерпретацию внешних и внутренних колец.

  • Внешний контур обычно задаётся против часовой стрелки
  • Внутренние кольца — по часовой стрелке

Некорректный порядок может привести к:

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

MapLibre частично нормализует winding order, но полагаться на это не рекомендуется.


Обновление данных полигона

GeoJSON-источник можно динамически изменять через setData.

const source = map.getSource('area');

source.setData({
  type: 'Feature',
  geometry: {
    type: 'Polygon',
    coordinates: [
      [
        [30.31, 59.94],
        [30.34, 59.94],
        [30.34, 59.96],
        [30.31, 59.96],
        [30.31, 59.94]
      ]
    ]
  }
});

Это основной механизм интерактивного редактирования геометрии.


Стилизация через выражения

MapLibre GL JS поддерживает data-driven styling, позволяющий менять внешний вид полигона в зависимости от свойств.

'fill-color': [
  'case',
  ['>', ['get', 'population'], 1000],
  '#ef4444',
  '#3b82f6'
]

Возможные подходы:

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

Пример градиентной заливки:

'fill-color': [
  'interpolate',
  ['linear'],
  ['get', 'value'],
  0, '#dbeafe',
  100, '#60a5fa',
  200, '#1d4ed8'
]

Слои и порядок отрисовки

Полигоны чувствительны к порядку слоёв:

  • fill слой рисуется ниже line слоя
  • fill-extrusion может перекрывать другие слои
  • порядок определяется последовательностью добавления или параметром beforeId
map.addLayer(layer, 'road-label');

Это позволяет контролировать визуальную иерархию.


Взаимодействие с Polygon

Получение кликов по полигону

map.on('click', 'area-fill', (e) => {
  const features = map.queryRenderedFeatures(e.point, {
    layers: ['area-fill']
  });

  console.log(features[0].properties);
});

Hover-эффекты

map.on('mousemove', 'area-fill', () => {
  map.getCanvas().style.cursor = 'pointer';
});
map.on('mouseleave', 'area-fill', () => {
  map.getCanvas().style.cursor = '';
});

Фильтрация полигонов

Если источник содержит множество объектов, используется фильтрация на уровне слоя:

'filter': ['==', ['get', 'type'], 'active']

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


Производительность при работе с Polygon

Полигональные данные могут стать узким местом при высокой сложности геометрии.

Основные ограничения:

  • большое количество вершин
  • частые вызовы setData
  • сложные MultiPolygon структуры

Практические оптимизации:

Снижение детализации:

упрощение геометрии (Douglas-Peucker)

Разбиение на тайлы:

  • использование vector tiles вместо GeoJSON
  • переход к MVT (Mapbox Vector Tile)

Ограничение перерисовок:

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

Частые ошибки при работе с Polygon

1. Перепутанный порядок координат

[lat, lng] вместо [lng, lat]

Приводит к смещению объекта в неверную точку мира.


2. Незамкнутый контур

Последняя точка должна повторять первую.


3. Некорректные внутренние кольца

Внутренние полигоны должны находиться строго внутри внешнего.


4. Слишком сложная геометрия

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


Использование свойств Feature для логики отображения

Polygon часто хранит бизнес-данные:

"properties": {
  "name": "Industrial zone",
  "status": "active",
  "priority": 3
}

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

  • для фильтрации
  • для стилизации
  • для событий интерфейса

Комбинация Polygon с другими слоями

Polygon редко используется изолированно. Типичная связка:

  • fill — заливка территории
  • line — граница
  • symbol — подпись
  • circle — маркеры внутри области

Это позволяет строить многоуровневые карты территорий, зон и регионов.