Бесплатно, всего с десятью дополнительными строками кода

Что, если бы я сказал вам, что вы можете сделать свою веб-карту такой:

Выглядите так:

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

Большинство приложений для веб-карт являются 2D, но с выпуском MapLibre v2 (а также Mapbox) 3D стало очень доступным. Больше не требуется сложное кодирование в ThreeJS для загрузки модели высот. Это просто вопрос добавления источника с URL-адресом, указывающим на набор данных о высоте.

Последняя часть. Набор данных о высоте за последний год был чем-то вроде остановки шоу. Поскольку наборы данных о высоте обычно бывают двух видов:

1 Как веб-сервис, но платный.

2 Бесплатно, но поставляется в виде загружаемых файлов (более тысячи файлов).

Однако, к счастью, набор данных НАСА о высотах с разрешением 30 м теперь бесплатно размещен в виде веб-сервиса на Ellipsis Drive! Этот набор данных предоставляет высококачественный набор данных по всему миру, который вы можете использовать в своих приложениях бесплатно!

Итак, как это делается?

В примере я использую mapLibre, но если вы используете Mapbox, все происходит почти так же (просто поменяйте в коде слово maplibregl на mapboxgl).

Чтобы отобразить карту с открытой картой улиц в качестве базового слоя и рельефа, набора данных НАСА о высоте 30 м, размещенного на Ellipsis Drive, мы можем использовать следующий фрагмент кода:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>3D Terrain</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://unpkg.com/[email protected]/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/[email protected]/dist/maplibre-gl.css" rel="stylesheet" />
<style>
 body { margin: 0; padding: 0; }
 #map { position: absolute; top: 0; bottom: 0; width: 100%; }
</style>
</head>
<body>
<div id="map"></div>
<script>
var map = (window.map = new maplibregl.Map({
container: 'map',
zoom: 12,
center: [11.39085, 47.27574],
pitch: 52,
hash: true,
style: {
version: 8,
sources: {
osm: {
type: 'raster',
tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],
tileSize: 256,
attribution: '&copy; OpenStreetMap Contributors',
maxzoom: 19
},
terrainSource: {
type: 'raster-dem',
tiles: ['https://api.ellipsis-drive.com/v3/path/085f5e10-63b6-4e8f-a4c6-dce9689100d3/raster/timestamp/3179fa80-60ad-41c7-ae67-cdd5eeeca693/tile/{z}/{x}/{y}?style={"method":"terrainRgb", "parameters":{"alpha":1, "bandNumber":1} }],
tileSize: 256
},
},
layers: [
{
id: 'osm',
type: 'raster',
source: 'osm'
},
],
terrain: {
source: 'terrainSource',
exaggeration: 1
}
},
maxZoom: 18,
maxPitch: 85
}));
 
map.addControl(
new maplibregl.NavigationControl({
visualizePitch: true,
showZoom: true,
showCompass: true
})
);
 
map.addControl(
new maplibregl.TerrainControl({
source: 'terrainSource',
exaggeration: 1
})
);
</script>
 
</body>

Как видите, это обычный способ отображения карты с помощью mapLibre. Единственная разница в том, что мы добавили источник ландшафта и слой. URL-адрес источника ландшафта следующий:

'https://api.ellipsis-drive.com/v3/path/085f5e10-63b6-4e8f-a4c6-dce9689100d3/raster/timestamp/3179fa80-60ad-41c7-ae67-cdd5eeeca693/tile/{z}/{x}/{y}?style={"method":"terrainRgb", "parameters":{"alpha":1, "bandNumber":1} }

Это указывает на этот слой в Ellipsis Drive с id 085f5e10–63b6–4e8f-a4c6-dce9689100d3.

И на самом деле это уже все… Добавление этого дополнительного источника и слоя — это все, что нам нужно, чтобы оснастить наше приложение высококачественной глобальной высотой.

Немного предыстории RGB-территории

Как видно из исходного URL-адреса, мы используем стили ландшафта RGB для извлечения данных из слоя высот. Рельеф RGB — это способ получить необработанные данные о высоте в формате PNG. Это может показаться странным, так как это не то, что собирается делать PNG… PNG — это изображение, а мы хотим получить точные значения высоты для местоположений.

Однако PNG предлагает гораздо более эффективный способ отправки данных о высоте, чем если бы мы просто поместили их в JSON. Это сжатие без потерь, и это очень хорошо поддерживаемый формат. Все веские причины, по которым «захват» PNG для этой цели вполне допустим.

Итак, как данные о высоте закодированы в этих PNG? Простой.

elevation = -10000 + ((Red * 256 * 256 + Green * 256 + Blue) * 0.1)

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

Таким образом, этот PNG:

Кодирует для этой высоты:

Использование собственных наборов данных о высотах

А что, если у вас есть собственная модель высот, которую вы хотели бы использовать?

Что ж, это всего лишь вопрос загрузки растров, содержащих вашу высоту, на Ellipsis Drive. После загрузки вы сможете использовать их точно так же.

Вам необходимо создать исходный URL-адрес следующим образом:

'https://api.ellipsis-drive.com/v3/path/<id of your layer>/raster/timestamp/<id of a timestamp in the layer>/tile/{z}/{x}/{y}?style={"method":"terrainRgb", "parameters":{"alpha":1, "bandNumber":1} }

Используя идентификатор слоя и идентификатор временной метки, которые вы можете найти здесь, на панели сведений о слое:

Раздел URL указывает стиль, который вы сохраняете, когда хотите передавать свои данные в виде TerrainRgb.

style={"method":"terrainRgb", "parameters":{"alpha":1, "bandNumber":1}

Здесь, например, я использую высокодетализированную модель высот 0,5 м, которую размещаю у себя:

Заключительные мысли

С выпуском mapLibre v2 (а также mapbox v2) использование моделей местности в приложении стало проще простого. Трудность, однако. Раньше считалось, что создать веб-службу ландшафта RGB из ваших данных или получить в свои руки бесплатный веб-сервис, предоставляющий ландшафт RGB, не так уж и просто. Однако с помощью Ellipsis Drive теперь вы можете передавать данные NASA о высотах по всему миру и даже свои собственные данные о высотах в виде ландшафта RGB без трения.

mapLibre + Ellipsis Drive = веб-карты с трехмерной высотой!