Экструзия зданий

Экструзия зданий — это механизм трёхмерного отображения объектов на карте, при котором полигоны зданий визуально «поднимаются» над поверхностью земли в соответствии с их высотой. В Mapbox GL JS данный эффект реализуется через слой типа fill-extrusion, который преобразует двухмерные геометрии в объёмные формы с управляемой высотой, цветом и поведением при масштабировании.


Источник данных для 3D-зданий

Основой для экструзии служат векторные тайлы, содержащие слой зданий. Чаще всего используется набор данных, основанный на OpenStreetMap, преобразованный в формат векторных тайлов.

Типичный слой содержит следующие атрибуты:

  • height — фактическая высота здания
  • min_height — базовый уровень (например, подиум или подземные этажи)
  • extrude — флаг, указывающий, можно ли визуализировать здание в 3D
  • name — идентификатор объекта (опционально)

При отсутствии height часто используется приближённое значение, основанное на количестве этажей или типе здания.


Базовая конфигурация слоя fill-extrusion

Экструзия реализуется через добавление слоя с типом fill-extrusion в стиль карты.

map.on('load', () => {
  map.addLayer({
    id: '3d-buildings',
    source: 'composite',
    'source-layer': 'building',
    filter: ['==', 'extrude', 'true'],
    type: 'fill-extrusion',
    minzoom: 15,
    paint: {
      'fill-extrusion-color': '#aaa',
      'fill-extrusion-height': ['get', 'height'],
      'fill-extrusion-base': ['get', 'min_height'],
      'fill-extrusion-opacity': 0.9
    }
  });
});

Ключевые элементы:

  • type: fill-extrusion — включает 3D-рендеринг
  • fill-extrusion-height — высота объекта
  • fill-extrusion-base — базовая отметка
  • minzoom — ограничение видимости слоя

Управление высотой зданий

Высота зданий может задаваться напрямую или через выражения интерполяции. Это позволяет создавать более плавное появление 3D-эффекта при увеличении масштаба.

'fill-extrusion-height': [
  'interpolate',
  ['linear'],
  ['zoom'],
  15, 0,
  15.05, ['get', 'height']
]

Такая конструкция делает здания «вырастающими» при приближении карты, что улучшает визуальную динамику сцены.


Базовый уровень экструзии

Свойство fill-extrusion-base определяет, с какой высоты начинается построение объёма. Это особенно важно для зданий с подземной частью или сложным рельефом.

'fill-extrusion-base': [
  'case',
  ['has', 'min_height'],
  ['get', 'min_height'],
  0
]

При отсутствии значения базовый уровень считается нулевым, и здание начинается от поверхности земли.


Цвет и визуальные свойства

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

'fill-extrusion-color': [
  'interpolate',
  ['linear'],
  ['get', 'height'],
  0, '#d9d9d9',
  100, '#b3b3b3',
  200, '#8c8c8c',
  500, '#666666'
]

Дополнительные параметры:

  • fill-extrusion-opacity — прозрачность слоя
  • fill-extrusion-vertical-gradient — вертикальное затемнение для объёма

Управление видимостью и фильтрация

Для корректного отображения трёхмерных зданий используется фильтрация объектов.

filter: [
  'all',
  ['==', 'extrude', 'true'],
  ['!=', 'height', null]
]

Также применяется ограничение по масштабу:

  • До zoom 14–15 здания обычно скрываются
  • После zoom 15 начинается постепенная экструзия
  • На zoom 16+ проявляется полная детализация

Освещение и восприятие глубины

Mapbox GL JS поддерживает глобальное освещение сцены через свойство light в стиле карты. Оно влияет на тени и восприятие объёма.

map.setLight({
  anchor: 'viewport',
  color: 'white',
  intensity: 0.5
});

Параметры освещения:

  • anchor — привязка источника света (карта или экран)
  • color — цвет освещения
  • intensity — интенсивность света

Корректная настройка света критична для различимости высот зданий и создания объёмного эффекта.


Комбинация с другими слоями

Экструзия зданий часто комбинируется с:

  • слоями дорог (line)
  • водными объектами (fill)
  • слоями POI (symbol)
  • тенями и декоративными слоями

Порядок слоёв влияет на восприятие сцены: здания должны находиться выше плоских слоёв, но ниже символических меток.


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

3D-экструзия требует значительных ресурсов GPU. Оптимизация включает:

  • ограничение minzoom
  • фильтрацию ненужных объектов
  • упрощение геометрии на стороне тайлов
  • избегание сложных выражений в paint при большом количестве объектов

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


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

Свойства экструзии могут изменяться в реальном времени без перезагрузки карты:

map.setPaintProperty('3d-buildings', 'fill-extrusion-opacity', 0.6);

или

map.setPaintProperty(
  '3d-buildings',
  'fill-extrusion-color',
  '#ffcc00'
);

Это позволяет адаптировать визуализацию под разные сценарии: ночной режим, тепловые карты, тематические слои.


Использование выражений для сложных эффектов

Mapbox GL JS поддерживает выражения, позволяющие создавать зависимость высоты и цвета от зума:

'fill-extrusion-height': [
  'interpolate',
  ['exponential', 1.5],
  ['zoom'],
  14, 0,
  16, ['get', 'height']
]

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


Особенности работы с реальными данными

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

  • отсутствующие значения высоты
  • некорректные единицы измерения
  • дублирующиеся полигоны
  • здания без extrude флага

Для повышения качества визуализации применяется предварительная обработка данных или fallback-логика:

'fill-extrusion-height': [
  'coalesce',
  ['get', 'height'],
  10
]

Геометрия экструзии и WebGL-пайплайн

Внутри Mapbox GL JS экструзия преобразует 2D-полигоны в набор треугольников, формирующих боковые грани и крышу. Процесс включает:

  • триангуляцию основания
  • генерацию боковых граней
  • расчёт нормалей для освещения
  • передачу данных в WebGL буферы

Этот процесс выполняется на GPU, что обеспечивает высокую производительность при большом количестве объектов.


Взаимодействие с камерой

Экструзия зданий тесно связана с параметрами камеры:

  • pitch — наклон карты (необходим для 3D-эффекта)
  • bearing — поворот сцены
  • zoom — масштабирование

Типичная конфигурация для 3D-сцены:

map.setPitch(60);
map.setBearing(-20);

Без наклона (pitch = 0) экструзия теряет объёмное восприятие и выглядит как плоское смещение.


Поведение на границах масштаба

При переходе между уровнями zoom экструзия проходит несколько стадий:

  • скрытие (до minzoom)
  • появление (частичная высота)
  • полная экструзия
  • детализация освещения и цвета

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


Типичные ошибки при настройке экструзии

  • отсутствие source-layer для зданий
  • использование 2D-слоёв вместо векторных тайлов
  • игнорирование minzoom
  • отсутствие fill-extrusion-base, приводящее к «плавающим» зданиям
  • перегрузка выражений в paint, ухудшающая производительность