Настройка exaggeration

Параметр exaggeration в MapLibre GL JS используется для вертикального масштабирования рельефа, отображаемого на основе цифровой модели высот (DEM — Digital Elevation Model). Он позволяет визуально усиливать или ослаблять перепады высот без изменения исходных данных.

При использовании трёхмерного рельефа карта может выглядеть слишком плоской, особенно на территориях с небольшими перепадами высот. Увеличение значения exaggeration делает горы выше, долины глубже и общий рельеф более выразительным.

Настройка выполняется через источник типа raster-dem и объект terrain.

Базовая конфигурация выглядит следующим образом:

map.addSource('dem', {
    type: 'raster-dem',
    url: 'https://example.com/dem.json',
    tileSize: 512
});

map.setTerrain({
    source: 'dem',
    exaggeration: 1
});

Значение 1 означает отображение рельефа без изменений.


Принцип работы

MapLibre GL JS получает данные высот из DEM-тайлов. Для каждой точки известна абсолютная высота над уровнем моря. Перед визуализацией движок умножает каждое значение высоты на коэффициент exaggeration.

Условно процесс выглядит следующим образом:

Итоговая высота = Исходная высота × exaggeration

Если исходная вершина имеет высоту 1500 метров:

Exaggeration Отображаемая высота
0.5 750 м
1 1500 м
2 3000 м
3 4500 м

Физические координаты объектов не изменяются. Изменяется только визуальное представление поверхности.


Стандартное значение

Наиболее распространённым считается значение:

exaggeration: 1

Такой режим обеспечивает максимально реалистичное отображение рельефа.

Пример:

map.setTerrain({
    source: 'dem',
    exaggeration: 1
});

Подходит для:

  • географических приложений;
  • картографических сервисов;
  • навигационных систем;
  • научной визуализации;
  • кадастровых решений.

Уменьшение рельефа

Коэффициент может быть меньше единицы.

Пример:

map.setTerrain({
    source: 'dem',
    exaggeration: 0.5
});

Результат:

  • горы становятся ниже;
  • склоны выглядят более пологими;
  • рельеф визуально сглаживается.

Такой подход полезен, если:

  • данные высот слишком шумные;
  • необходимо сделать акцент на объектах карты;
  • рельеф отвлекает от основной информации.

Иногда используются ещё меньшие значения:

exaggeration: 0.25

или

exaggeration: 0.1

Карта приобретает почти плоский вид.


Полное отключение рельефа

Значение 0 фактически обнуляет все высоты.

map.setTerrain({
    source: 'dem',
    exaggeration: 0
});

В этом режиме:

  • DEM продолжает быть подключён;
  • расчёты рельефа остаются доступными;
  • поверхность отображается как плоскость.

Для полного отключения terrain обычно используется:

map.setTerrain(null);

Однако значение 0 удобно применять для плавной анимации включения рельефа.


Усиление рельефа

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

Пример:

map.setTerrain({
    source: 'dem',
    exaggeration: 2
});

Высоты визуально удваиваются.

Эффект особенно заметен:

  • в горных районах;
  • на каньонах;
  • в долинах;
  • на вулканических территориях.

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


Сильное увеличение

Допускаются и большие значения.

map.setTerrain({
    source: 'dem',
    exaggeration: 5
});

или

map.setTerrain({
    source: 'dem',
    exaggeration: 10
});

Подобные коэффициенты используются преимущественно для:

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

При больших значениях карта становится менее реалистичной.

Например:

exaggeration: 20

может превратить умеренные холмы в практически вертикальные стены.


Влияние на 3D-визуализацию

Exaggeration воздействует на все элементы, зависящие от поверхности terrain.

При увеличении коэффициента изменяются:

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

Пример:

map.setTerrain({
    source: 'dem',
    exaggeration: 3
});

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


Влияние на перспективу камеры

Эффект exaggeration особенно заметен при наклоне карты.

Небольшой наклон:

map.easeTo({
    pitch: 20
});

Средний наклон:

map.easeTo({
    pitch: 45
});

Максимально выраженный эффект:

map.easeTo({
    pitch: 70
});

Чем больше угол обзора, тем сильнее воспринимается увеличение рельефа.

Комбинация:

pitch: 70
exaggeration: 2

обычно выглядит значительно эффектнее, чем:

pitch: 0
exaggeration: 2

Динамическое изменение exaggeration

Коэффициент может изменяться во время работы приложения.

Пример:

map.setTerrain({
    source: 'dem',
    exaggeration: 1
});

button.addEventListener('click', () => {
    map.setTerrain({
        source: 'dem',
        exaggeration: 2
    });
});

После вызова setTerrain() карта автоматически перестроит поверхность.


Создание пользовательского переключателя

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

const levels = {
    flat: 0,
    normal: 1,
    enhanced: 2,
    dramatic: 4
};

function setRelief(level) {
    map.setTerrain({
        source: 'dem',
        exaggeration: levels[level]
    });
}

Использование:

setRelief('normal');
setRelief('enhanced');
setRelief('dramatic');

Такой подход распространён в туристических и геоинформационных системах.


Анимация изменения рельефа

MapLibre GL JS позволяет создавать плавные визуальные эффекты путём последовательного изменения коэффициента.

Простейший пример:

let exaggeration = 0;

const interval = setInterval(() => {
    exaggeration += 0.1;

    map.setTerrain({
        source: 'dem',
        exaggeration
    });

    if (exaggeration >= 2) {
        clearInterval(interval);
    }
}, 50);

Результат:

  • карта начинается с плоской поверхности;
  • рельеф постепенно поднимается;
  • горы становятся всё более выраженными.

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


Изменение значения через ползунок

Интерактивное управление обычно реализуется через элемент range.

HTML:

<input
    id="terrain-slider"
    type="range"
    min="0"
    max="5"
    step="0.1"
    value="1">

Jav * aScript:

const slider = document.getElementById('terrain-slider');

slider.addEventListener('input', (event) => {
    map.setTerrain({
        source: 'dem',
        exaggeration: Number(event.target.value)
    });
});

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


Использование разных значений для разных масштабов

Иногда требуется усиливать рельеф только при определённом приближении.

Пример:

map.on('zoom', () => {
    const zoom = map.getZoom();

    let exaggeration = 1;

    if (zoom > 10) {
        exaggeration = 2;
    }

    map.setTerrain({
        source: 'dem',
        exaggeration
    });
});

Логика может быть более сложной:

if (zoom < 6) {
    exaggeration = 0.5;
}
else if (zoom < 10) {
    exaggeration = 1;
}
else if (zoom < 14) {
    exaggeration = 2;
}
else {
    exaggeration = 3;
}

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


Подбор оптимальных значений

Практика показывает следующие диапазоны:

Значение Назначение
0 Полностью плоская поверхность
0.25–0.75 Слабый рельеф
1 Реалистичное отображение
1.5–2 Умеренное усиление
2–4 Ярко выраженный рельеф
5+ Демонстрационный режим

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

exaggeration: 1.2

или

exaggeration: 1.5

Они делают карту более выразительной без существенной потери реалистичности.


Производительность

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

Основная нагрузка связана с:

  • загрузкой DEM-тайлов;
  • построением terrain-сетки;
  • рендерингом трёхмерной сцены;
  • вычислением освещения.

Следующие варианты имеют близкую стоимость:

exaggeration: 1
exaggeration: 2
exaggeration: 5

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


Типичные ошибки

Чрезмерное увеличение

exaggeration: 15

или

exaggeration: 20

Часто приводит к неестественному отображению поверхности.


Отсутствие источника DEM

Некорректный код:

map.setTerrain({
    source: 'dem',
    exaggeration: 2
});

если источник ещё не зарегистрирован.

Правильный порядок:

map.addSource('dem', {
    type: 'raster-dem',
    url: 'https://example.com/dem.json'
});

map.setTerrain({
    source: 'dem',
    exaggeration: 2
});

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

Некорректный пример:

exaggeration: -1

Отрицательные коэффициенты не имеют практического смысла и могут привести к непредсказуемому поведению визуализации.


Частые вызовы setTerrain()

Неэффективный подход:

map.on('mousemove', () => {
    map.setTerrain({
        source: 'dem',
        exaggeration: Math.random()
    });
});

Постоянная перестройка рельефа способна создавать лишнюю нагрузку на систему.

Предпочтительно использовать:

  • debounce;
  • throttle;
  • обновление по событиям интерфейса;
  • анимации с контролируемой частотой кадров.

Практический пример

const map = new maplibregl.Map({
    container: 'map',
    style: 'https://demotiles.maplibre.org/style.json',
    center: [7.5, 46.5],
    zoom: 10,
    pitch: 60
});

map.on('load', () => {
    map.addSource('dem', {
        type: 'raster-dem',
        url: 'https://example.com/dem.json',
        tileSize: 512
    });

    map.setTerrain({
        source: 'dem',
        exaggeration: 1.8
    });

    map.easeTo({
        pitch: 70,
        duration: 3000
    });
});

В результате формируется выразительная трёхмерная сцена с усиленным рельефом, хорошо демонстрирующая возможности цифровой модели высот и механизма terrain в MapLibre GL JS.