Получение тайлов карты (Open Street Map)
Данный материал частично основан на информации с источников:
Хорошая статья по ГИС;
Про системы координат;
И еще про проекции.
Картографические проекции и системы координат
Земля имеет форму, так называемого, геоида. Впервые фигуру геоида описал немецкий математик К. Ф. Гаусс, который определял её как «математическую фигуру Земли» — гладкую, но неправильную поверхность.
(Авторство: International Centre for Global Earth Models (ICGEM). http://icgem.gfz-potsdam.de/vis3d/longtime / Ince, E. S., Barthelmes, F., Reißland, S., Elger, K., Förste, C., Flechtner, F., Schuh, H. (2019): ICGEM – 15 years of successful collection and distribution of global gravitational models, associated services and future plans. - Earth System Science Data, 11, pp. 647-674,DOI: http://doi.org/10.5194/essd-11-647-2019., CC BY 4.0, https://commons.wikimedia.org/w/index.php?curid=81462823)
Форма геоида обусловлена неравномерным распределением масс внутри и на поверхности Земли. Геоид является поверхностью, относительно которой ведётся отсчёт высот над уровнем моря, в силу чего точное знание параметров геоида необходимо, в частности, в навигации — для определения высоты над уровнем моря на основе геодезической (эллипсоидальной) высоты, измеряемой GPS-приёмниками, а также в физической океанологии — для определения высот морской поверхности.
Проблема геоида в обычной жизни?
Работать с элипсоидом (аппроксиморованный геоид) напрямую неудобно. Если мы работаем с маленькими масштабами на бумаге, нам потребуется ОГРОМНЫХ размеров глобус. И наоборот, при работе с большими масштабами, сложно было бы с таким глобусом охватить взглядом разные материки, например. Для многих задач намного удобнее использовать плоскую проекцию.
НО, создать плоскую проекцию Земли без искажений невозможно и точка. Не получится преобразовать глобус в плоскость без разрывов (кроме экватора):
Разрывы при проекции сферы на плоскость. Источник: https://habr.com/ru/companies/bft/articles/773814/.
Для решений данной пробелемы существуют проекции сферы на плоскость, например, проекция Меркатора.
Проекция Меркатора
Проекция Меркатора является лишь одной из большого списка. Список некоторых проекций можно посмотреть здесь.
Это цилиндрическая проекция, которая сохраняет углы и формы объектов (равноугольная), но сильно искажает площади ближе к полюсам. Основные области использования — морская навигация, авиация, веб-карты (Google Maps, Яндекс.Карты, Open Street Map и др.) и крупномасштабные карты приэкваториальных областей.
Пример искажений в проекции Меркатора. Авторство: Jakub Nowosad. Собственная работа, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=73955926
Про стандарты:
EPSG:4326— географическая система координат, основанная на системе параметровWGS84((World Geodetic System 1984) традиционно использует порядок широта — долгота, аEPSG 4326— долгота — широта.). Единица измерения — градус;EPSG:3857— прямоугольная система координат, основанная на проекции Меркатора, построенной по системе параметровWGS84. Единица измерения – метр.
Что такое тайлы?
Тайлы - это изображения небольшого размера (одинакового), являющиеся фрагментами большого изображения. В рамках работы с картами - это квадратные (обычно 256х256 пикселей, могут быть и 512x512) изображения, формирующие карту мира.
Они используются в веб-картографии (Google Maps, Яндекс Карты, OpenStreetMap) для быстрой загрузки: браузер загружает только те тайлы, которые видны на экране, экономя трафик и память.
Например, если открыть в браузере карту [OpenStreetMap.org](www.openstreetmap.org), перейти в режим разработчика (CTRL + SHIFT + I) во вкладке Network, мы увидим следующую картину:
Как web-карта (Open Street Map) получает изображения (тайлы)
, где увидим, что были загружены несколько изображений *.png со странными названиями файлов.
Например, 20726:
Этот файл был получен при помощи запроса на сервер OpenStreetMap -
https://tile.openstreetmap.org/16/47867/20726.png.
OSM-карты (и не только они) присваивают каждому изображению свои наименования. Правила наименований описаны в статье:wiki.openstreetmap.org/wiki/Slippy_map_tilenames.
Правила наименований тайлов
Все тайлы имеют размер
256 × 256пикселей форматаPNG;Каждое значение масштаба карты (zoom level) является директорией, каждый столбец также является директорией, в которой находятся изображения;
Ссылка (
URL) на получения конкретного файла (*.png) формируется в формате:/zoom/x/y.png
Например, для масштаба карты 2 (zoom = 2) будут след. наименования:
Пример нумерации тайлов
Можно заметить, что:
Координата
Z- не меняется,Z = 2.Координаты
X- это столбцы матрицы,Y- строки матрицы.
Тайл серверы
С названиями координат изображений мы определились, но первая часть URL (например, tile.openstreetmap.org) отвечает за сервер, на который вы или ваше приложение будет отправлять запрос.
Name |
URL template |
zoomlevels |
|---|---|---|
OSM ‘standard’ style |
https://tile.openstreetmap.org/zoom/x/y.png |
0-19 |
OpenCycleMap |
http://[abc].tile.thunderforest.com/cycle/zoom/x/y.png |
0-22 |
Thunderforest Transport |
http://[abc].tile.thunderforest.com/transport/zoom/x/y.png |
0-22 |
MapTiles API Standard |
https://maptiles.p.rapidapi.com/local/osm/v1/zoom/x/y.png?rapidapi-key=YOUR-KEY |
0-19 globally |
MapTiles API English |
https://maptiles.p.rapidapi.com/en/map/v1/zoom/x/y.png?rapidapi-key=YOUR-KEY |
0-19 globally with English labels |
Масштаб (zoom levels)
Ниже приведена таблица по каждому уровню масштабирования (от 0 до 19). Более подробная таблица находится здесь.
zoom level |
tile coverage |
number of tiles |
tile size(*) in degrees |
|---|---|---|---|
0 |
1 tile covers whole world |
1 tile |
360° x 170.1022° |
1 |
2 × 2 tiles |
4 tiles |
180° x 85.0511° |
2 |
4 × 4 tiles |
16 tiles |
90° x [variable] |
n |
\(2^n × 2^n\) tiles |
\(2^{2n}\) tiles |
360/2<sup>n</sup> ° x [variable] |
12 |
4096 x 4096 tiles |
16 777 216 |
0.0879° x [variable] |
16 |
… |
\(2^{32}\) ≈ 4 295 million tiles |
… |
17 |
… |
17.2 billion tiles |
… |
18 |
… |
68.7 billion tiles |
… |
19 |
Maximum zoom for Mapnik layer |
274.9 billion tiles |
… |
Получение наименований тайлов
Вспомним про странные названия изображений, которые получает наш браузер: 20726.png.
Если посмотрим на полный путь до этого файла, то увидим: 16/47867/20726.png, где:
16- zoom;47867- это номер столбца (координатаX) во всей матрице тайлов для текущего масштаба;20726- это номер строки (или координатаY) в матрице.
Наша цель
Преобразовать GPS-координаты в позиции (X, Y) тайлов Меркатора.
Состоит из 4 этапов:
Преобразовать углы
Latitude,Longitudeв сферическую проекцию Меркатора (из EPSG:4326 в EPSG:3857) https://epsg.io/3857;Преобразовать значения
X,Yк отрезку[0 - 1], получая относительный квадрат;Получить количество всей тайлов для текущего масштаба (
zoom);Умножаем
XиYна количество тайлов - получаем “имена” тайлов в форматеzoom/x/y.
Математика
Преобразование в Web-проекцию Меркатора (из
Lat, LonвX, Y):
, где \(lon_{EPSG:4326}\) - longitude в системе EPSG:4326, \(X_{EPSG:3857}\) - X в системе Меркатора.
, где \(lat_{EPSG:4326}\) - latitude в системе EPSG:4326, \(Y_{EPSG:3857}\) - Y в системе Меркатора.
Нормируем к интервалу
(0, 1)
Считаем количество тайлов, которое есть на карте данного масштаба (см. Информация по тайлам для масштабов (0 - 19)):
, где \(N_{tiles}\) - количество тайлов, \(zoom\) - уровень масштабирования.
Получаем значения координат тайла (в матрице всех тайлов для \(2^{zoom}\))
Пример:
Возьмем координаты lat = 55.007969, lon = 82.944546 (широта, долгота), zoom = 16.
Этап |
Значения |
|---|---|
Web-Меркатор |
lat = 55.007969lon = 82.944546\(X_{EPSG:3857} = 82.944546\)
\(Y_{EPSG:3857} = 1.1544770655\)
|
Нормирование |
\(x = 0.73040151666\)
\(y = 0.31625926833\)
|
Масштаб |
\(2^{16} = 65536\) |
Точные индексы тайла по |
\(x_{tile} = 0.73040151666 * 65536 = 47867.5937958\)
\(y_{tile} = 0.31625926833 * 65536 = 20726.3674093\)
\(fractional_{x} =59.37958\) %
\(fractional_{y} =36.74093\) %;
|
Значения пикселей в картинке |
X - \(256 * 0.5937 = 151.9872\)
Y - \(256 * 0.3674 = 94.0544\)
|
С округлением вниз получаем: z = 16, x = 47867, y = 20726. Как мы можем заметить, это совпадает с запросом к тайл-серверу OpenStreetmap: https://tile.openstreetmap.org/16/47867/20726.png.