Heatmap-weight

В слое типа heatmap в Mapbox GL JS каждая точка исходных данных не влияет на итоговое изображение одинаково. Интенсивность влияния регулируется свойством heatmap-weight, которое определяет «вес» каждого географического объекта при расчёте плотности.

Mapbox GL JS использует heatmap-weight как динамическое выражение, позволяющее учитывать не только наличие точки, но и её значимость.


Принцип работы heatmap-weight

Тепловая карта формируется не как простое количество точек в области, а как взвешенная сумма значений.

Каждая точка источника данных имеет вклад:

вклад точки = heatmap-weight × (нормализованное значение точки)

Если heatmap-weight не задан, используется значение по умолчанию 1.

Таким образом:

  • значения > 1 усиливают влияние точки;
  • значения < 1 ослабляют влияние;
  • значения 0 полностью исключают точку из тепловой карты.

Базовая структура слоя heatmap

map.addLayer({
  id: 'heatmap-layer',
  type: 'heatmap',
  source: 'points',
  paint: {
    'heatmap-weight': 1
  }
});

В этом виде каждая точка равнозначна.


Динамическое вычисление веса через свойства данных

Одно из ключевых применений heatmap-weight — привязка к атрибутам GeoJSON.

'heatmap-weight': [
  'get',
  'intensity'
]

Если объект данных содержит:

{
  "type": "Feature",
  "properties": {
    "intensity": 3
  }
}

то его вклад будет втрое выше стандартного.


Нормализация значений

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

'heatmap-weight': [
  'interpolate',
  ['linear'],
  ['get', 'mag'],
  0, 0,
  6, 1
]

Поведение выражения:

  • значение mag = 0 → вес 0
  • значение mag = 6 → вес 1
  • промежуточные значения масштабируются линейно

Использование категориального веса

Иногда данные разделены по категориям, например:

  • тип события
  • уровень важности
  • источник данных

Пример:

'heatmap-weight': [
  'match',
  ['get', 'type'],
  'fire', 1,
  'smoke', 0.7,
  'alert', 1.5,
  0.3
]

Здесь:

  • «alert» усиливает тепловую карту
  • «smoke» частично влияет
  • неизвестные типы почти игнорируются

Связь heatmap-weight и heatmap-intensity

heatmap-weight работает на уровне отдельных точек, тогда как heatmap-intensity масштабирует уже агрегированный результат.

Формально:

  • heatmap-weight → вклад точки
  • heatmap-intensity → масштаб всей поверхности

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


Влияние zoom-уровня

Вес можно изменять в зависимости от масштаба карты:

'heatmap-weight': [
  'interpolate',
  ['linear'],
  ['zoom'],
  0, 0.5,
  10, 1,
  15, 2
]

Поведение:

  • на малом масштабе влияние точек снижено
  • при увеличении масштаба вклад усиливается

Это используется для:

  • предотвращения «перегрева» карты на глобальном уровне
  • детализации локальных зон при увеличении

Комбинация с плотностью данных

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

  1. Вес точки (heatmap-weight)
  2. Радиус влияния (heatmap-radius)
  3. Интенсивность слоя (heatmap-intensity)

Пример комплексной конфигурации:

paint: {
  'heatmap-weight': [
    'interpolate',
    ['linear'],
    ['get', 'value'],
    0, 0,
    100, 1
  ],
  'heatmap-intensity': [
    'interpolate',
    ['linear'],
    ['zoom'],
    0, 1,
    9, 3
  ],
  'heatmap-radius': [
    'interpolate',
    ['linear'],
    ['zoom'],
    0, 2,
    9, 20
  ]
}

Ошибки в использовании heatmap-weight

1. Отсутствие нормализации

Если значения из данных напрямую используются без приведения к диапазону 0–1, тепловая карта становится непропорциональной.

2. Слишком большие веса

Значения > 10 часто приводят к визуальному доминированию отдельных точек.

3. Игнорирование категорий

При смешанных данных без match или case теряется семантическая структура.


Использование в аналитических картах

heatmap-weight применяется в сценариях:

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

В таких случаях вес часто отражает:

  • количество событий
  • финансовую значимость
  • уровень риска

Связь с источниками данных GeoJSON

Источник:

map.addSource('points', {
  type: 'geojson',
  data: {
    type: 'FeatureCollection',
    features: []
  }
});

Каждый объект Feature может содержать свойства, которые напрямую участвуют в вычислении веса:

  • числовые показатели
  • категориальные метки
  • временные параметры (через предварительную агрегацию)

Оптимизация вычислений

При большом количестве точек важна минимизация сложности выражений:

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

Поведение при отсутствии данных

Если значение heatmap-weight вычисляется как null или undefined, точка:

  • либо игнорируется
  • либо получает вес 0 (в зависимости от контекста выражения)

Поэтому используется защита:

'heatmap-weight': [
  'coalesce',
  ['get', 'weight'],
  1
]

Взаимодействие с визуальными свойствами слоя

heatmap-weight влияет не на цвет напрямую, а на распределение плотности, которая затем преобразуется через:

  • heatmap-color
  • heatmap-opacity

Таким образом формируется двухступенчатая модель:

  1. расчёт плотности (включая веса)
  2. визуализация результата

Поведение при изменении данных в реальном времени

При динамическом обновлении GeoJSON:

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

Это особенно важно для потоковых данных (streaming data), где каждое событие имеет собственный вклад в итоговое распределение.