Работа с высотой и экструзией

В контексте WebGL-визуализаций библиотека Deck.gl рассматривает высоту как один из ключевых параметров перехода от плоской карты к объёмной сцене. Высота в слоях данных не является геометрическим свойством в классическом смысле — она вычисляется процедурно на основе атрибутов данных и затем преобразуется в 3D-геометрию через механизм экструзии (extrusion).

Экструзия в Deck.gl представляет собой процесс «вытягивания» 2D-геометрии вдоль оси Z, где значение высоты определяется функцией данных getElevation или аналогичными мапперами атрибутов. Это позволяет преобразовывать полигоны, точки и гексагоны в объёмные объекты.


Базовая модель высоты в слоях Deck.gl

Практически все 3D-слои в Deck.gl используют единый подход:

  • данные содержат числовое поле (например, population, height, value)
  • слой интерпретирует это поле как высоту
  • применяется масштабирование через elevationScale
  • результат передаётся в вершинный шейдер WebGL

Ключевая концепция: высота не хранится в геометрии напрямую, а вычисляется на этапе рендеринга.

new ColumnLayer({
  id: 'columns',
  data,
  getPosition: d => [d.lng, d.lat],
  getElevation: d => d.value,
  elevationScale: 10,
  radius: 50
});

Здесь getElevation возвращает «сырое» значение, а elevationScale преобразует его в визуальную высоту.


Масштабирование высоты и нормализация данных

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

Основные подходы:

Линейное масштабирование

elevationScale: 0.1

Логарифмическая трансформация

getElevation: d => Math.log(d.value + 1)

Кастомная нормализация

getElevation: d => (d.value - min) / (max - min)

Выбор метода зависит от распределения данных и цели визуализации.


ColumnLayer как базовый инструмент экструзии

Deck.gl предоставляет ColumnLayer как один из наиболее прямолинейных способов работы с высотой.

import {ColumnLayer} from '@deck.gl/layers';

const layer = new ColumnLayer({
  id: 'column-layer',
  data: points,
  diskResolution: 12,
  radius: 200,
  extruded: true,
  pickable: true,

  getPosition: d => [d.longitude, d.latitude],
  getFillColor: d => [255, 140, 0],
  getElevation: d => d.height
});

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

  • каждая точка превращается в цилиндр
  • высота определяется индивидуально
  • поддерживает интерактивность (hover, click)
  • оптимизирован для больших наборов данных

PolygonLayer и экструзия геометрии

PolygonLayer позволяет экструзировать произвольные полигоны, превращая их в 3D-призмы.

import {PolygonLayer} from '@deck.gl/layers';

const layer = new PolygonLayer({
  id: 'polygons',
  data,
  extruded: true,
  wireframe: false,

  getPolygon: d => d.coordinates,
  getElevation: d => d.population,
  getFillColor: d => [0, 128, 255],
  elevationScale: 5
});

Геометрическая интерпретация:

  • основание — географический полигон
  • высота — значение из данных
  • боковые грани генерируются автоматически
  • верхняя грань закрывается для создания объёма

GeoJsonLayer и 3D-объекты

GeoJsonLayer объединяет точки, линии и полигоны в единую модель и поддерживает экструзию на уровне Feature.

import {GeoJsonLayer} from '@deck.gl/layers';

const layer = new GeoJsonLayer({
  id: 'geojson',
  data: geojson,

  extruded: true,
  stroked: false,
  filled: true,

  getElevation: f => f.properties.height,
  elevationScale: 20,
  getFillColor: [200, 200, 200]
});

Этот слой особенно полезен при работе с административными границами и тематическими картами.


HexagonLayer и агрегация высоты

HexagonLayer агрегирует точки в шестиугольные ячейки и вычисляет высоту на основе статистической функции.

import {HexagonLayer} from '@deck.gl/aggregation-layers';

const layer = new HexagonLayer({
  id: 'hex',
  data,
  radius: 1000,
  extruded: true,

  getPosition: d => [d.lng, d.lat],
  getElevationWeight: d => d.value,
  elevationScale: 50
});

Методы агрегации:

  • sum (сумма)
  • mean (среднее)
  • max (максимум)
  • count (количество точек)

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


Вершинные шейдеры и преобразование высоты

На уровне WebGL высота преобразуется в смещение по оси Z в вершинном шейдере.

Упрощённая логика:

float elevation = getElevation(attribute);
float scaledElevation = elevation * u_elevationScale;

position.z += scaledElevation;

Также учитываются:

  • проекционные матрицы
  • координатная система (Web Mercator)
  • глобальные масштабы сцены

Координатные системы и влияние на высоту

Высота в Deck.gl зависит от системы координат. В географических слоях используется Web Mercator, где единицы измерения не равны метрам.

В связке с Mapbox GL JS часто применяется синхронизация систем координат:

  • COORDINATE_SYSTEM.LNGLAT
  • COORDINATE_SYSTEM.METER_OFFSETS
  • COORDINATE_SYSTEM.CARTESIAN

Ошибки выбора системы приводят к:

  • искажению высот
  • несоответствию масштаба
  • «плавающим» объектам

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

3D-экструзия без освещения теряет читаемость. Deck.gl использует модель направленного света:

  • ambient light (фон)
  • directional light (направленный источник)
  • specular highlights (блики)
import {AmbientLight, DirectionalLight} from '@deck.gl/core';

const lightingEffect = new LightingEffect({
  ambientLight: new AmbientLight({intensity: 0.4}),
  directionalLight: new DirectionalLight({
    color: [255, 255, 255],
    intensity: 1.0,
    direction: [-1, -1, -1]
  })
});

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


Динамическое изменение высоты

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

setInterval(() => {
  layer.setProps({
    getElevation: d => d.value * Math.random()
  });
}, 1000);

Также поддерживаются плавные переходы:

transitions: {
  getElevation: 1000
}

Это создаёт эффект анимации роста или изменения рельефа.


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

Тематические карты плотности

Высота отражает интенсивность явления:

  • население
  • загрязнение воздуха
  • трафик

Финансовые визуализации

  • объёмы транзакций
  • капитализация
  • торговая активность

Географические модели

  • рельеф
  • застройка
  • инфраструктурные объекты

Ошибки при работе с экструзией

Несбалансированный масштаб

Слишком большие значения elevationScale приводят к:

  • перекрытию объектов
  • потере глубины сцены

Неправильные данные

  • строки вместо чисел
  • отрицательные значения без обработки

Игнорирование проекции

Несоответствие координатных систем приводит к визуальному «разъезду» геометрии.


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

Высота сама по себе не влияет на FPS напрямую, но влияет на:

  • сложность геометрии (больше граней при высоких призмах)
  • количество отрисовываемых пикселей
  • нагрузку на фрагментный шейдер

Оптимизации:

  • уменьшение diskResolution
  • батчинг данных
  • использование GPU aggregation
  • упрощение материалов

Многослойная экструзия и композиция сцен

Deck.gl позволяет комбинировать слои:

  • базовый TerrainLayer
  • поверх ColumnLayer
  • затем ScatterplotLayer

Это создаёт сложные 3D-сцены, где высота становится частью многослойной визуальной модели, а не отдельным параметром.