Работа с координатами векторных объектов

Векторные объекты в OpenLayers представляют пространственные сущности, описываемые набором координат. Независимо от того, является ли объект точкой, линией или полигоном, его геометрия строится на основе координатных данных.

Каждая геометрия хранит координаты в определённой структуре:

  • Point — одна координатная пара;
  • LineString — массив координат;
  • Polygon — массив массивов координат;
  • MultiPoint — набор точек;
  • MultiLineString — набор линий;
  • MultiPolygon — набор полигонов.

Простейший пример создания точки:

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

const point = new Point([37.6176, 55.7558]);

В данном случае массив содержит две величины:

[долгота, широта]

Однако корректность интерпретации этих значений зависит от используемой проекции.


Координатные системы и проекции

Одной из наиболее важных особенностей OpenLayers является работа с различными проекциями.

Наиболее распространены две системы:

Проекция Код Назначение
WGS84 EPSG:4326 Географические координаты
Web Mercator EPSG:3857 Отображение карт

Координаты Москвы в WGS84:

[37.6176, 55.7558]

После преобразования в Web Mercator значения становятся совершенно другими:

[4187538.678, 7509955.143]

Большинство современных картографических сервисов используют именно EPSG:3857.


Получение координат объекта

Каждая геометрия предоставляет метод getCoordinates().

Пример для точки:

const coordinates = point.getCoordinates();

console.log(coordinates);

Результат:

[37.6176, 55.7558]

Для линии:

const line = new LineString([
    [37.6, 55.7],
    [37.7, 55.8]
]);

console.log(line.getCoordinates());

Результат:

[
    [37.6, 55.7],
    [37.7, 55.8]
]

Для полигона:

[
    [
        [37.6, 55.7],
        [37.8, 55.7],
        [37.8, 55.9],
        [37.6, 55.9],
        [37.6, 55.7]
    ]
]

Структура вложенности напрямую зависит от типа геометрии.


Изменение координат объекта

Метод setCoordinates() позволяет полностью заменить координаты геометрии.

Пример перемещения точки:

point.setCoordinates([38.0, 56.0]);

После выполнения:

console.log(point.getCoordinates());

Получаем:

[38.0, 56.0]

Изменение линии:

line.setCoordinates([
    [37.5, 55.5],
    [37.9, 55.9]
]);

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


Координаты объекта Feature

Геометрия обычно хранится внутри объекта Feature.

Создание объекта:

import Feature from 'ol/Feature.js';
import Point from 'ol/geom/Point.js';

const feature = new Feature({
    geometry: new Point([37.6176, 55.7558])
});

Получение координат:

const geometry = feature.getGeometry();

const coordinates = geometry.getCoordinates();

Более компактный вариант:

const coordinates =
    feature.getGeometry().getCoordinates();

Изменение положения:

feature
    .getGeometry()
    .setCoordinates([38.0, 56.0]);

Получение центра геометрии

Для вычисления центральной точки объекта часто используется экстент.

Получение границ:

const extent =
    feature.getGeometry().getExtent();

Вычисление центра:

import {getCenter} from 'ol/extent.js';

const center = getCenter(extent);

Результат:

[x, y]

Этот подход работает для любых типов геометрий.


Работа с координатами точки

Точка является самым простым видом геометрии.

Создание:

const point = new Point([30, 60]);

Получение X и Y:

const [x, y] =
    point.getCoordinates();

console.log(x);
console.log(y);

Изменение отдельных значений:

let coordinates =
    point.getCoordinates();

coordinates[0] += 100;

point.setCoordinates(coordinates);

Таким способом можно реализовывать программное перемещение объектов.


Работа с координатами линий

Линия состоит из последовательности вершин.

Создание:

const line = new LineString([
    [10, 10],
    [20, 20],
    [30, 40]
]);

Получение всех вершин:

const points =
    line.getCoordinates();

Обращение к первой вершине:

const firstPoint = points[0];

Добавление новой вершины:

points.push([50, 70]);

line.setCoordinates(points);

Удаление вершины:

points.splice(1, 1);

line.setCoordinates(points);

Изменение конкретной вершины:

points[2] = [40, 60];

line.setCoordinates(points);

Работа с координатами полигонов

Полигон хранит один или несколько контуров.

Пример:

const polygon = new Polygon([
    [
        [0, 0],
        [100, 0],
        [100, 100],
        [0, 100],
        [0, 0]
    ]
]);

Получение внешнего контура:

const ring =
    polygon.getCoordinates()[0];

Первая вершина:

const vertex = ring[0];

Изменение вершины:

ring[1] = [150, 0];

polygon.setCoordinates([ring]);

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


Работа с внутренними контурами

Полигон может содержать отверстия.

Пример структуры:

const polygon = new Polygon([
    [
        [0, 0],
        [100, 0],
        [100, 100],
        [0, 100],
        [0, 0]
    ],
    [
        [25, 25],
        [75, 25],
        [75, 75],
        [25, 75],
        [25, 25]
    ]
]);

Здесь:

  • первый массив — внешний контур;
  • второй массив — отверстие.

Получение отверстия:

const hole =
    polygon.getCoordinates()[1];

Изменение его формы:

hole[1] = [80, 25];

polygon.setCoordinates([
    polygon.getCoordinates()[0],
    hole
]);

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

Модуль ol/proj содержит функции преобразования координат.

Импорт:

import {transform} from 'ol/proj.js';

Преобразование из WGS84 в Web Mercator:

const coordinate =
    transform(
        [37.6176, 55.7558],
        'EPSG:4326',
        'EPSG:3857'
    );

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

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

Этот механизм используется практически во всех картографических приложениях.


Использование функции fromLonLat

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

Импорт:

import {fromLonLat} from 'ol/proj.js';

Создание точки:

const point = new Point(
    fromLonLat([37.6176, 55.7558])
);

Создание центра карты:

const view = new View({
    center: fromLonLat([37.6176, 55.7558]),
    zoom: 10
});

Функция автоматически выполняет преобразование в EPSG:3857.


Использование функции toLonLat

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

Импорт:

import {toLonLat} from 'ol/proj.js';

Преобразование:

const geographicCoordinate =
    toLonLat(
        point.getCoordinates()
    );

Результат:

[долгота, широта]

Это особенно полезно при сохранении данных в базе данных или отправке на сервер.


Координаты курсора мыши

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

Пример:

map.on('pointermove', (event) => {

    const coordinate =
        event.coordinate;

    console.log(coordinate);

});

Координаты возвращаются в проекции карты.

Преобразование в географический формат:

import {toLonLat} from 'ol/proj.js';

map.on('pointermove', (event) => {

    const coordinate =
        toLonLat(event.coordinate);

    console.log(coordinate);

});

Получение координат при клике

Часто требуется определить место щелчка пользователя.

Пример:

map.on('click', (event) => {

    console.log(event.coordinate);

});

Получение долготы и широты:

map.on('click', (event) => {

    const lonLat =
        toLonLat(event.coordinate);

    console.log(lonLat);

});

Подобный механизм применяется при создании меток, измерениях и редактировании объектов.


Координаты вершин при редактировании

Во время редактирования геометрии координаты изменяются динамически.

Подключение взаимодействия:

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

Создание:

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

map.addInteraction(modify);

Отслеживание завершения изменения:

modify.on('modifyend', (event) => {

    event.features.forEach((feature) => {

        const coordinates =
            feature
                .getGeometry()
                .getCoordinates();

        console.log(coordinates);

    });

});

Таким образом можно сохранять обновлённую геометрию на сервере сразу после редактирования.


Вычисление расстояния между координатами

Для двух точек можно вычислить расстояние средствами геометрии.

Пример:

const point1 = [0, 0];
const point2 = [100, 200];

const dx = point2[0] - point1[0];
const dy = point2[1] - point1[1];

const distance =
    Math.sqrt(dx * dx + dy * dy);

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


Проверка координат объекта

Перед сохранением данных часто выполняется валидация координат.

Проверка точки:

const [lon, lat] =
    geographicCoordinate;

const valid =
    lon >= -180 &&
    lon <= 180 &&
    lat >= -90 &&
    lat <= 90;

Проверка массива координат:

const coordinates =
    line.getCoordinates();

const valid =
    coordinates.every(
        ([x, y]) =>
            Number.isFinite(x) &&
            Number.isFinite(y)
    );

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


Клонирование геометрии с координатами

Создание копии объекта необходимо при реализации отмены изменений и временного редактирования.

Пример:

const geometry =
    feature.getGeometry();

const clone =
    geometry.clone();

Получение координат копии:

const coordinates =
    clone.getCoordinates();

Изменение копии:

clone.setCoordinates([
    [10, 10],
    [20, 20]
]);

Исходная геометрия останется без изменений.


Экспорт координат в GeoJSON

При экспорте координаты автоматически включаются в структуру GeoJSON.

Пример:

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

const geojson =
    new GeoJSON();

const json =
    geojson.writeFeature(feature);

Фрагмент результата:

{
  "type": "Feature",
  "geometry": {
    "type": "Point",
    "coordinates": [
      37.6176,
      55.7558
    ]
  }
}

Координаты становятся частью стандартного геопространственного формата, совместимого с большинством ГИС-систем, серверов пространственных данных и веб-картографических платформ.