Polygon

Геометрическая модель Polygon

Polygon в OpenLayers представляет собой замкнутую область на карте, задаваемую набором координат. Внутренняя модель построена вокруг концепции линий (rings):

  • первый набор координат — внешний контур (outer ring)
  • последующие наборы — отверстия (holes)

Формально структура Polygon:

Polygon = [ outerRing, hole1, hole2, ... ]

Каждый ring — это массив координат вида:

[x, y]

или в географических координатах:

[longitude, latitude]

Создание Polygon через ol/geom/Polygon

Базовый способ создания полигона:

import Polygon from 'ol/geom/Polygon.js';

const polygon = new Polygon([
  [
    [30.0, 50.0],
    [31.0, 50.0],
    [31.0, 51.0],
    [30.0, 51.0],
    [30.0, 50.0]
  ]
]);

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


Полигон с отверстиями (holes)

OpenLayers поддерживает вложенные области, которые вырезаются из основной геометрии:

const polygonWithHole = new Polygon([
  [
    [0, 0],
    [10, 0],
    [10, 10],
    [0, 10],
    [0, 0]
  ],
  [
    [3, 3],
    [7, 3],
    [7, 7],
    [3, 7],
    [3, 3]
  ]
]);

Внутренний ring интерпретируется как «дырка», не входящая в область полигона.


Работа с координатами и проекциями

OpenLayers не привязывает координаты к конкретной системе координат внутри Geometry. Однако стандартом считается:

  • EPSG:3857 — проекция карты
  • EPSG:4326 — географические координаты

При необходимости преобразование выполняется через ol/proj:

import { fromLonLat } from 'ol/proj';

const polygon = new Polygon([[
  fromLonLat([30, 50]),
  fromLonLat([31, 50]),
  fromLonLat([31, 51]),
  fromLonLat([30, 51]),
  fromLonLat([30, 50])
]]);

Методы Polygon

getCoordinates()

Возвращает текущую структуру координат:

const coords = polygon.getCoordinates();

Результат всегда соответствует формату:

[number[][][]]

setCoordinates()

Полностью заменяет геометрию:

polygon.setCoordinates([
  [
    [0, 0],
    [5, 0],
    [5, 5],
    [0, 5],
    [0, 0]
  ]
]);

appendCoordinate()

Добавляет точку в последний ring:

polygon.appendCoordinate([6, 6]);

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


Использование Polygon в слоях

Чтобы Polygon появился на карте, он должен быть частью Feature и VectorLayer.

import Feature from 'ol/Feature.js';
import VectorSource from 'ol/source/Vector.js';
import VectorLayer from 'ol/layer/Vector.js';

const feature = new Feature({
  geometry: polygon
});

const source = new VectorSource({
  features: [feature]
});

const layer = new VectorLayer({
  source: source
});

Стилизация Polygon

Стили определяются через ol/style:

import Style from 'ol/style/Style.js';
import Fill from 'ol/style/Fill.js';
import Stroke from 'ol/style/Stroke.js';

const style = new Style({
  fill: new Fill({
    color: 'rgba(0, 150, 255, 0.3)'
  }),
  stroke: new Stroke({
    color: '#3399CC',
    width: 2
  })
});

feature.setStyle(style);

Ключевые компоненты:

  • Fill — заливка области
  • Stroke — обводка границы

Рисование Polygon пользователем

Для интерактивного создания используется Draw interaction:

import Draw from 'ol/interaction/Draw.js';

const draw = new Draw({
  source: source,
  type: 'Polygon'
});

map.addInteraction(draw);

Особенности поведения:

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

Редактирование Polygon

Для изменения геометрии применяется Modify:

import Modify from 'ol/interaction/Modify.js';

const modify = new Modify({
  source: source
});

map.addInteraction(modify);

Поддерживаемые операции:

  • перемещение вершин
  • изменение формы
  • сохранение структуры rings

Проверка геометрии и самопересечения

OpenLayers не всегда автоматически валидирует полигоны. Самопересекающиеся формы могут:

  • отображаться некорректно
  • давать неожиданные результаты при вычислениях площади

Для вычислений используется:

import { getArea } from 'ol/sphere.js';

const area = getArea(polygon);

Polygon и GeoJSON

Polygon напрямую совместим с GeoJSON форматом:

import GeoJSON from 'ol/format/GeoJSON.js';

const geojson = new GeoJSON();

const json = geojson.writeFeature(feature);

Структура GeoJSON:

{
  "type": "Polygon",
  "coordinates": [
    [[30, 50], [31, 50], [31, 51], [30, 51], [30, 50]]
  ]
}

MultiPolygon vs Polygon

Polygon — одна область.

MultiPolygon — набор независимых областей:

import MultiPolygon from 'ol/geom/MultiPolygon.js';

const multi = new MultiPolygon([
  [
    [
      [0, 0],
      [5, 0],
      [5, 5],
      [0, 5],
      [0, 0]
    ]
  ],
  [
    [
      [10, 10],
      [15, 10],
      [15, 15],
      [10, 15],
      [10, 10]
    ]
  ]
]);

Используется при работе с разрозненными территориями одного объекта.


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

При большом количестве вершин критичны:

  • минимизация числа сегментов
  • упрощение геометрии (simplification)
  • использование векторных источников с кластеризацией при необходимости

Рекомендации:

  • избегать избыточных точек в rings
  • не пересоздавать Polygon без необходимости
  • использовать setCoordinates вместо создания новых Feature при обновлении

Практическая модель поведения Polygon в рендеринге

OpenLayers преобразует Polygon в набор экранных координат:

  1. географические координаты → проекция карты
  2. проекция → пиксели viewport
  3. triangulation (разбиение на треугольники)
  4. отрисовка через WebGL или Canvas renderer

Особенно важно:

  • сложные полигоны триангулируются
  • отверстия учитываются как вычитаемые области
  • самопересечения могут ломать triangulation pipeline