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

Любая географическая информация на карте представляется в виде координат. Однако поверхность Земли имеет форму, близкую к эллипсоиду, тогда как экран компьютера является плоским. Для отображения пространственных данных необходимо преобразовать координаты из одной системы представления в другую. Именно эту задачу решают системы координат и картографические проекции.

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


Основные понятия

Система координат

Система координат определяет способ задания положения точки в пространстве.

В геоинформационных системах наиболее распространены:

  • географические координаты;
  • проецированные координаты;
  • локальные системы координат.

Пример географических координат:

Долгота: 37.6176
Широта: 55.7558

Это координаты Москвы в градусах.

Проекция

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

При проецировании неизбежно возникают искажения:

  • расстояний;
  • площадей;
  • углов;
  • форм объектов.

Разные проекции минимизируют различные виды искажений в зависимости от поставленной задачи.


Идентификаторы EPSG

Для обозначения систем координат используются коды EPSG.

Наиболее распространённые:

Код Название Единицы
EPSG:4326 WGS84 градусы
EPSG:3857 Web Mercator метры
EPSG:3395 World Mercator метры
EPSG:32637 UTM Zone 37N метры

В OpenLayers проекция обычно задаётся именно через EPSG-код.

Пример:

'EPSG:4326'

или

'EPSG:3857'

Географическая система координат WGS84

EPSG:4326

Практически все GPS-приёмники и навигационные системы используют систему WGS84.

Координаты представлены в виде:

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

Например:

[37.6176, 55.7558]

Особенности:

  • единица измерения — градусы;
  • используется спутниковой навигацией;
  • является мировым стандартом;
  • подходит для хранения координат.

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

import Map from 'ol/Map.js';
import View from 'ol/View.js';

const map = new Map({
    target: 'map',
    view: new View({
        projection: 'EPSG:4326',
        center: [37.6176, 55.7558],
        zoom: 5
    })
});

Проекция Web Mercator

EPSG:3857

Самая распространённая проекция в интернете.

Используется сервисами:

  • Google Maps;
  • OpenStreetMap;
  • Bing Maps;
  • большинство веб-картографических платформ.

Особенности:

  • координаты измеряются в метрах;
  • удобна для отображения тайлов;
  • хорошо подходит для интерактивных карт;
  • сильно искажает площади возле полюсов.

Пример координат Москвы в Web Mercator:

[4187538.68, 7509955.14]

Те же координаты в WGS84:

[37.6176, 55.7558]

Проекция по умолчанию в OpenLayers

Если явно не указано иное, OpenLayers использует:

EPSG:3857

Поэтому большинство карт автоматически работают в Web Mercator.

Пример:

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

Фактически используется:

projection: 'EPSG:3857'

Представление координат в OpenLayers

Координата всегда хранится в массиве:

[x, y]

Для разных проекций значения имеют различный смысл.

Для EPSG:4326:

[37.6176, 55.7558]

где:

  • x — долгота;
  • y — широта.

Для EPSG:3857:

[4187538.68, 7509955.14]

где:

  • x — смещение по оси X в метрах;
  • y — смещение по оси Y в метрах.

Получение текущей проекции карты

Объект View хранит информацию о проекции.

Пример:

const projection = map
    .getView()
    .getProjection();

console.log(projection.getCode());

Результат:

EPSG:3857

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

Функция fromLonLat()

Наиболее часто используемая функция.

Преобразует координаты из WGS84 в Web Mercator.

import { fromLonLat } from 'ol/proj';

const coord = fromLonLat([
    37.6176,
    55.7558
]);

Результат:

[4187538.68, 7509955.14]

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

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

Такой подход считается стандартным.


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

Функция toLonLat()

Преобразует координаты из Web Mercator в WGS84.

import { toLonLat } from 'ol/proj';

const lonLat = toLonLat([
    4187538.68,
    7509955.14
]);

Результат:

[37.6176, 55.7558]

Универсальное преобразование координат

Функция transform()

Позволяет выполнять преобразование между любыми поддерживаемыми проекциями.

Синтаксис:

transform(
    coordinate,
    sourceProjection,
    destinationProjection
);

Пример:

import { transform } from 'ol/proj';

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

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

const result = transform(
    [4187538.68, 7509955.14],
    'EPSG:3857',
    'EPSG:4326'
);

Добавление точек с использованием географических координат

Исходные GPS-данные обычно приходят в WGS84.

Например:

const gps = [
    37.6176,
    55.7558
];

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

import Point from 'ol/geom/Point';
import { fromLonLat } from 'ol/proj';

const point = new Point(
    fromLonLat(gps)
);

Работа с Feature

import Feature from 'ol/Feature';

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

Без преобразования объект окажется в неверной позиции.


Координаты события клика

При клике по карте координаты возвращаются в проекции текущего представления.

map.on('click', function(event) {
    console.log(event.coordinate);
});

Для EPSG:3857 вывод может выглядеть так:

[4187538.68, 7509955.14]

Получение географических координат при клике

Обычно требуется долгота и широта.

import { toLonLat } from 'ol/proj';

map.on('click', function(event) {

    const lonLat = toLonLat(
        event.coordinate
    );

    console.log(lonLat);

});

Результат:

[37.6176, 55.7558]

Работа с extent

Extent представляет прямоугольную область:

[
    minX,
    minY,
    maxX,
    maxY
]

Пример:

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

Для преобразования используется:

import { transformExtent } from 'ol/proj';

const projectedExtent =
    transformExtent(
        extent,
        'EPSG:4326',
        'EPSG:3857'
    );

Использование пользовательской проекции

OpenLayers поддерживает регистрацию дополнительных систем координат.

Для этого применяется библиотека proj4.

Установка:

npm install proj4

Импорт:

import proj4 from 'proj4';
import { register } from 'ol/proj/proj4';

Регистрация проекции:

proj4.defs(
    'EPSG:12345',
    '+proj=tmerc +lat_0=0 ...'
);

register(proj4);

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

projection: 'EPSG:12345'

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

import { get } from 'ol/proj';

const projection =
    get('EPSG:3857');

Доступны различные свойства.

Например:

projection.getCode();

или

projection.getUnits();

Единицы измерения проекции

Проверка единиц:

const units =
    projection.getUnits();

console.log(units);

Результат:

m

или

degrees

Это особенно важно при вычислении расстояний.


Почему нельзя измерять расстояния напрямую в EPSG:4326

Неверный подход:

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

В системе WGS84 координаты выражены в градусах.

Разница в один градус:

  • на экваторе соответствует примерно 111 км;
  • возле полюсов значительно меньше.

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


Ограничения Web Mercator

Несмотря на популярность, EPSG:3857 имеет недостатки.

Основные проблемы:

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

Например, территория Гренландии визуально выглядит сопоставимой с Африкой, хотя фактически значительно меньше.


Географические координаты пользователя

Если браузер предоставляет данные геолокации:

navigator.geolocation
    .getCurrentPosition(
        function(position) {

            const lon =
                position.coords.longitude;

            const lat =
                position.coords.latitude;

        }
    );

Полученные значения находятся в системе:

EPSG:4326

Для отображения на карте OpenLayers обычно требуется преобразование:

const center =
    fromLonLat([
        lon,
        lat
    ]);

Типичные ошибки при работе с проекциями

Отсутствие преобразования координат

Неправильно:

new Point([
    37.6176,
    55.7558
]);

Правильно:

new Point(
    fromLonLat([
        37.6176,
        55.7558
    ])
);

Перепутаны широта и долгота

Неправильно:

[
    latitude,
    longitude
]

Правильно:

[
    longitude,
    latitude
]

В OpenLayers порядок всегда следующий:

[x, y]

Несовпадение проекций слоёв

Если один слой использует:

EPSG:4326

а карта отображается в:

EPSG:3857

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


Неправильная интерпретация координат клика

Координаты события:

event.coordinate

не являются автоматически долготой и широтой.

Они находятся в проекции карты.

Перед использованием в географических расчётах необходимо выполнить преобразование через:

toLonLat()

Практические рекомендации

Для хранения данных предпочтительно использовать:

EPSG:4326

Для отображения веб-карт предпочтительно использовать:

EPSG:3857

Для GPS-координат всегда предполагать:

EPSG:4326

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

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

Понимание различий между системами координат, корректное преобразование данных и осознанный выбор проекций являются необходимой основой для разработки надёжных картографических приложений на OpenLayers.