Ограничение домов

В MapLibre GL JS отображение домов (зданий) почти всегда опирается на данные векторных тайлов, где объекты имеют свойства building, height, min_height, name и другие атрибуты. Основной способ ограничить отображение домов — применение фильтров слоя.

Типичная конфигурация слоя зданий:

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

Ключевой механизм ограничения — выражение filter. Оно определяет, какие здания попадут в визуализацию.

Примеры фильтрации:

// Только здания с заданной высотой
filter: ['>', ['get', 'height'], 10]

// Только жилые здания
filter: ['==', ['get', 'building'], 'residential']

// Исключение небольших построек
filter: ['>=', ['get', 'area'], 200]

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


Ограничение отображения зданий по масштабу

Один из наиболее эффективных способов управления «плотностью» домов — контроль через minzoom и maxzoom.

layout: {
  visibility: 'visible'
},
minzoom: 15,
maxzoom: 18

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

Практика показывает:

  • до zoom 13 здания обычно скрываются полностью;
  • 14–15 отображаются упрощённые формы;
  • 16+ включается 3D extrusion.

Ограничение зданий по географическому диапазону

Иногда требуется ограничить отображение домов конкретной областью. В MapLibre GL JS это достигается через фильтр координат с использованием выражений within или логических условий.

Простейший подход — фильтрация по атрибутам или заранее размеченным полям:

filter: [
  'all',
  ['>=', ['get', 'x_index'], 100],
  ['<=', ['get', 'x_index'], 200],
  ['>=', ['get', 'y_index'], 50],
  ['<=', ['get', 'y_index'], 120]
]

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


Управление визуальной плотностью зданий

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

Снижение визуальной нагрузки через opacity

paint: {
  'fill-extrusion-opacity': [
    'interpolate',
    ['linear'],
    ['zoom'],
    14, 0.3,
    16, 0.8
  ]
}

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


Отсечение мелких зданий

filter: [
  'all',
  ['>=', ['get', 'height'], 5],
  ['!=', ['get', 'type'], 'shed']
]

Удаление малых объектов уменьшает количество геометрии и ускоряет отрисовку.


Ограничение экструдированных зданий (3D)

fill-extrusion позволяет задавать высоту зданий. Ограничение часто вводится для предотвращения чрезмерных значений высоты или некорректных данных.

'fill-extrusion-height': [
  'min',
  ['get', 'height'],
  120
]

Или более строгая нормализация:

'fill-extrusion-height': [
  'case',
  ['>', ['get', 'height'], 200],
  200,
  ['get', 'height']
]

Дополнительно можно ограничивать базовую высоту:

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

Клиппинг зданий в пределах области просмотра

MapLibre GL JS поддерживает автоматическое отсечение геометрии по viewport, но при сложных сценах применяется дополнительное ограничение через маскирующие слои.

Пример использования слоя-маски:

map.addLayer({
  id: 'clip-mask',
  type: 'fill',
  source: {
    type: 'geojson',
    data: polygon
  },
  paint: {
    'fill-color': '#000',
    'fill-opacity': 0
  }
});

Далее здания могут фильтроваться через логические выражения, привязанные к геометрии источника.


Ограничение зданий по типу объекта

Векторные тайлы часто содержат смешанные объекты: жилые дома, коммерческие здания, гаражи, склады.

filter: [
  'match',
  ['get', 'building'],
  ['house', 'apartments', 'residential'],
  true,
  false
]

Более строгая классификация:

filter: [
  'in',
  ['get', 'type'],
  'residential',
  'commercial'
]

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


Динамическое ограничение зданий через setFilter

MapLibre GL JS позволяет менять фильтры во время выполнения:

map.setFilter('buildings', [
  '>=',
  ['get', 'height'],
  20
]);

Это используется для интерактивных сценариев:

  • переключение режимов «только высотные здания»;
  • выделение исторической застройки;
  • анализ плотности.

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


Ограничение зданий по уровню детализации данных

Векторные тайлы часто содержат разные уровни детализации (LOD). Ограничение можно реализовать через выбор source-layer.

source-layer: 'building_low'

или

source-layer: 'building_high'

Принцип:

  • low — упрощённые контуры;
  • high — детализированные полигоны с высотой.

Переключение между слоями позволяет контролировать нагрузку и качество визуализации.


Геометрическое отсечение зданий по границам

При необходимости ограничить здания конкретным административным контуром применяется spatial clipping на уровне данных или через выражения:

filter: ['within', regionPolygon]

Если within недоступен в конкретной конфигурации, применяется предобработка GeoJSON и генерация тайлов с обрезкой по границе региона.


Контроль высотных аномалий зданий

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

'fill-extrusion-height': [
  'step',
  ['get', 'height'],
  0,
  2, 2,
  10, 10,
  50, 50,
  150, 150
]

Или ограничение диапазона:

[
  'clamp',
  ['get', 'height'],
  0,
  100
]

Оптимизация рендеринга при большом количестве зданий

При плотной застройке критически важны механизмы ограничения нагрузки:

1. Упрощение геометрии на источнике

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

2. Ограничение через zoom

minzoom: 15

3. Снижение количества атрибутов

Удаление неиспользуемых свойств уменьшает размер тайлов.

4. Группировка зданий

Некоторые источники объединяют мелкие здания в кластеры:

filter: ['>=', ['get', 'cluster_size'], 3]

Управление видимостью зданий через expression visibility

layout: {
  visibility: [
    'case',
    ['>', ['zoom'], 14],
    'visible',
    'none'
  ]
}

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


Ограничение зданий через комбинированные условия

Реальные сценарии часто требуют комплексных фильтров:

filter: [
  'all',
  ['==', ['get', 'extrude'], 'true'],
  ['>=', ['get', 'height'], 10],
  ['<=', ['get', 'height'], 120],
  ['!=', ['get', 'building'], 'shed']
]

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