Работа с экстентами и границами

Работа с экстентами (extent) в OpenLayers является фундаментальной частью управления отображением карты, географическими ограничениями, фильтрацией данных и вычислением видимой области. Экстент представляет собой прямоугольную область в координатной системе карты, заданную четырьмя значениями: [minX, minY, maxX, maxY].

Экстент всегда интерпретируется в контексте конкретной проекции. В Web Mercator (EPSG:3857) значения выражаются в метрах, тогда как в географической системе (EPSG:4326) — в градусах долготы и широты.

Типичное представление экстента:

const extent = [minX, minY, maxX, maxY];

Например, экстент для области может выглядеть так:

const extent = [30.1, 59.8, 30.6, 60.0];

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


Базовые операции с экстентами

Модуль ol/extent предоставляет набор функций для работы с прямоугольными географическими областями.

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

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

import { intersects } from 'ol/extent';

const a = [0, 0, 10, 10];
const b = [5, 5, 15, 15];

const result = intersects(a, b);

Функция возвращает true, если области пересекаются хотя бы частично.


Полное включение (containment)

Проверка, содержится ли один экстент внутри другого:

import { containsExtent } from 'ol/extent';

const outer = [0, 0, 20, 20];
const inner = [5, 5, 10, 10];

const isInside = containsExtent(outer, inner);

Такая операция используется при фильтрации объектов, попадающих в текущую область видимости карты.


Расширение экстента

Объединение двух областей в один экстент:

import { extend } from 'ol/extent';

const target = [0, 0, 10, 10];
const source = [8, 8, 20, 20];

extend(target, source);

После выполнения target станет [0, 0, 20, 20].


Создание пустого экстента

Пустой экстент используется как начальное состояние для накопительных вычислений:

import { createEmpty, extend } from 'ol/extent';

const extent = createEmpty();

extend(extent, [10, 10, 20, 20]);
extend(extent, [0, 0, 5, 5]);

Преобразование экстентов между проекциями

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

import { transformExtent } from 'ol/proj';

const wgs84Extent = [30, 50, 40, 60];

const mercatorExtent = transformExtent(
  wgs84Extent,
  'EPSG:4326',
  'EPSG:3857'
);

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


Экстент видимой области карты

Текущий видимый экстент карты определяется через View:

const extent = map.getView().calculateExtent(map.getSize());

Этот экстент обновляется при каждом изменении масштаба или центра карты и используется для:

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

Ограничение перемещения карты

Экстенты применяются для ограничения области панорамирования.

import View from 'ol/View';

const view = new View({
  center: [0, 0],
  zoom: 2,
  extent: [-2000000, -2000000, 2000000, 2000000]
});

Параметр extent фиксирует границы, за которые пользователь не может переместить карту.


Функция fit и подгонка экстента

Метод fit позволяет автоматически подстроить вид карты под заданный экстент.

const extent = [10, 10, 20, 20];

map.getView().fit(extent, {
  padding: [50, 50, 50, 50],
  maxZoom: 10
});

Подгонка учитывает отступы и ограничения масштаба.


Работа с геометриями и экстентами

Экстент часто извлекается из геометрий:

const geometryExtent = geometry.getExtent();

Для сложных объектов (мультиполигоны, линии) экстент рассчитывается как минимальный ограничивающий прямоугольник.


Расширенные операции над экстентами

Смещение экстента

import { buffer } from 'ol/extent';

const expanded = buffer([0, 0, 10, 10], 5);

Экстент увеличивается во всех направлениях на заданное значение.


Пересечение экстентов

import { getIntersection } from 'ol/extent';

const result = getIntersection(
  [0, 0, 10, 10],
  [5, 5, 15, 15]
);

Результат — [5, 5, 10, 10] либо пустой экстент при отсутствии пересечения.


Проверка пустоты

import { isEmpty } from 'ol/extent';

const empty = isEmpty([0, 0, 0, 0]);

Используется для контроля валидности вычислений.


Экстенты слоёв

Слои могут иметь собственные ограничения отображения:

const layer = new TileLayer({
  extent: [0, 0, 1000000, 1000000],
  source: new OSM()
});

Такая настройка предотвращает рендеринг тайлов вне заданной области.


Оптимизация через экстенты

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

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

Фильтрация часто выполняется через проверку пересечения:

if (intersects(featureExtent, viewExtent)) {
  // объект попадает в область видимости
}

Преобразование координат экстента вручную

В некоторых случаях требуется ручное преобразование:

import { getTransform } from 'ol/proj';

const transform = getTransform('EPSG:4326', 'EPSG:3857');

const extent = [
  30, 50, 40, 60
];

const projectedExtent = [
  transform([extent[0], extent[1]]),
  transform([extent[2], extent[3]])
].flat();

Использование экстентов в векторных источниках

Векторные источники могут использовать экстент для ограничений выборки данных:

const source = new VectorSource({
  strategy: bboxStrategy
});

Стратегия bbox загружает данные только для текущего экстента карты.


Связь экстентов и событий карты

Изменение экстента связано с событиями:

  • moveend
  • change:view
  • rendercomplete

Пример получения актуального экстента после перемещения:

map.on('moveend', () => {
  const extent = map.getView().calculateExtent(map.getSize());
});

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

Экстент можно рассматривать как прямоугольник в декартовой системе координат. Он эквивалентен полигону с четырьмя вершинами:

  • (minX, minY)
  • (maxX, minY)
  • (maxX, maxY)
  • (minX, maxY)

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