Добавление слоя тепловой карты (пакет SDK для Android)

Примечание.

Прекращение использования пакета SDK для Android для Azure Карты

Пакет SDK для машинного кода Azure для Android Карты теперь устарел и будет прекращен 3.31.25. Чтобы избежать сбоев в работе служб, перейдите в веб-пакет SDK для Azure Карты на 3.31.25. Дополнительные сведения см. в руководстве по миграции пакета SDK для Android Карты Azure.

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

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

Тепловые карты подходят для разных сценариев использования. Ниже приведены некоторые из них.

  • Данные о температуре. Вы сможете получить приблизительные значения данных между двумя точками.
  • Сведения от датчиков шума. У вас будет возможность не только оценить уровень шума в точке установки датчика, но и получить представление о снижении шума на расстоянии. Уровень шума на одном из участков может быть невысоким. Но если несколько датчиков фиксируют воздействие на одну зону, в этой области могут наблюдаться более высокие уровни шума. Такая область перекрытия будет видна на тепловой карте.
  • GPS-данные. Вам будет доступна информация в виде взвешенной карты высот, где интенсивность каждой точки данных зависит от скорости. Например, эта функция позволит узнать, на каких участках транспортное средство двигалось с превышение скорости.

Совет

Слои тепловой карты по умолчанию преобразовывают координаты всех геометрических объектов в источнике данных. Чтобы отображать в слое только геометрические объекты, присвойте параметру filter для этого слоя значение eq(geometryType(), "Point"). Если вам также нужно включить компоненты MultiPoint, присвойте параметру filter для этого слоя значение any(eq(geometryType(), "Point"), eq(geometryType(), "MultiPoint")).


Необходимые компоненты

Обязательно выполните действия, описанные в кратком руководстве по созданию приложения Android. Блоки кода, приведенные в этой статье, можно поместить в обработчик событий onReady для карт.

Добавление слоя тепловой карты

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

В следующем примере кода загружается веб-канал GeoJSON по землетрясениям за прошлую неделю и преобразуется для просмотра в виде тепловой карты. Каждая точка данных преобразуется для просмотра с радиусом 10 пикселей на всех уровнях масштабирования. Для удобства пользователей тепловая карта находится под слоем меток, чтобы сохранить четкую видимость меток. Данные в этом примере содержат информацию об опасности землетрясений от Геологической службы США. В этом примере данные GeoJSON загружаются из Интернета с использованием блока кода служебной программы импорта данных, приведенного в документе Создание источника данных.

//Create a data source and add it to the map.
DataSource source = new DataSource();

//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson");

//Add data source to the map.
map.sources.add(source);

//Create a heat map layer.
HeatMapLayer layer = new HeatMapLayer(source,
  heatmapRadius(10f),
  heatmapOpacity(0.8f)
);

//Add the layer to the map, below the labels.
map.layers.add(layer, "labels");
//Create a data source and add it to the map.
val source = DataSource()

//Import the geojson data and add it to the data source.
source.importDataFromUrl("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")

//Add data source to the map.
map.sources.add(source)

//Create a heat map layer.
val layer = HeatMapLayer(
    source,
    heatmapRadius(10f),
    heatmapOpacity(0.8f)
)

//Add the layer to the map, below the labels.
map.layers.add(layer, "labels")

На следующем снимке экрана показана схема загрузки тепловой карты с помощью приведенного выше кода.

Схема с уровнем тепловой карты для недавних землетрясений

Настройка слоя тепловой карты

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

  • heatmapRadius — это радиус в пикселях для отрисовки каждой точки данных. Радиус определяется в виде фиксированного числа или выражения. С помощью выражения можно масштабировать радиус, в зависимости от уровня увеличения, чтобы демонстрировать согласованные пространственные области на карте (например, радиус 5 миль).

  • heatmapColor: — это цвета для тепловой карты. Цветовой градиент — это стандартный параметр тепловых карт. Нужного эффекта можно достичь с помощью выражения interpolate. Вы также можете использовать выражение step для выделения цветом элементов тепловой карты, чтобы визуально разбить плотность данных на диапазоны. Так карта будет напоминать топографическую или радиолокационную. Эти цветовые палитры определяют цвета в диапазоне от минимальной до максимальной плотности.

    Значения цветов для тепловых карт указываются в виде выражения для значения heatmapDensity. Цвет области, в которой отсутствуют данные, определяется индексом 0 в выражении для интерполяции или цветом по умолчанию в выражении для ступенчатой палитры. Это значение можно использовать для определения цвета фона. Часто применяется прозрачный или полупрозрачный черный цвет.

    Вот несколько примеров выражений для определения цвета.

    Выражение для интерполяции цвета Выражение для ступенчатой палитры
    interpolate(
        linear(),
        heatmapDensity(),
        stop(0, color(Color.TRANSPARENT)),
        stop(0.01, color(Color.MAGENTA)),
        stop(0.5, color(parseColor("#fb00fb"))),
        stop(1, color(parseColor("#00c3ff")))
    )'
    step(
        heatmapDensity(),
        color(Color.TRANSPARENT),
        stop(0.01, color(parseColor("#000080"))),
        stop(0.25, color(parseColor("#000080"))),
        stop(0.5, color(Color.GREEN)),
        stop(0.5, color(Color.YELLOW)),
        stop(1, color(Color.RED))
    )
  • heatmapOpacity — это степень прозрачности слоя тепловой карты.

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

  • heatmapWeight — это вес точки данных. По умолчанию для этого параметра установлено значение 1 для всех точек данных, то есть они имеют равный вес. Параметр weight используется в качестве множителя. Для него можно использовать фиксированное число или выражение. Если в качестве веса задано число, то это эквивалентно двукратному размещению каждой точки данных на карте. Например, если значение параметра weight равно 2, то плотность удваивается. Фиксированное число в качестве значения параметра weight изменяет тепловую карту точно так же, как изменение параметра intensity.

    Но если используется выражение, вес каждой точки данных может быть основан на ее свойствах. Например, предположим, что каждая точка данных представляет землетрясение. Важная метрика для каждой точки данных землетрясения — это значение магнитуды. Землетрясения происходят постоянно, но большинство из них имеют низкую магнитуду и не заметны. Используйте в выражении значение магнитуды, чтобы присвоить вес каждой точке данных. Это позволит получить наглядное представление о значительности землетрясений на тепловой карте.

  • minZoom и maxZoom: диапазон уровня масштабирования, в котором должен отображаться слой.

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

  • sourceLayer: если источник данных, подключенный к слою, является источником векторного фрагмента, необходимо указать исходный слой в векторных фрагментах.

  • visible: скрывает или отображает слой.

Следующий фрагмент кода является примером тепловой карты, в которой выражение интерполяции линии используется для создания градиента гладкого цвета. Свойство mag, определенное в данных, используется при экспоненциальной интерполяции для настройки веса или релевантности каждой точки данных.

HeatMapLayer layer = new HeatMapLayer(source,
    heatmapRadius(10f),

    //A linear interpolation is used to create a smooth color gradient based on the heat map density.
    heatmapColor(
        interpolate(
            linear(),
            heatmapDensity(),
            stop(0, color(Color.TRANSPARENT)),
            stop(0.01, color(Color.BLACK)),
            stop(0.25, color(Color.MAGENTA)),
            stop(0.5, color(Color.RED)),
            stop(0.75, color(Color.YELLOW)),
            stop(1, color(Color.WHITE))
        )
    ),

    //Using an exponential interpolation since earthquake magnitudes are on an exponential scale.
    heatmapWeight(
       interpolate(
            exponential(2),
            get("mag"),
            stop(0,0),

            //Any earthquake above a magnitude of 6 will have a weight of 1
            stop(6, 1)
       )
    )
);
val layer = HeatMapLayer(source,
    heatmapRadius(10f),

    //A linear interpolation is used to create a smooth color gradient based on the heat map density.
    heatmapColor(
        interpolate(
            linear(),
            heatmapDensity(),
            stop(0, color(Color.TRANSPARENT)),
            stop(0.01, color(Color.BLACK)),
            stop(0.25, color(Color.MAGENTA)),
            stop(0.5, color(Color.RED)),
            stop(0.75, color(Color.YELLOW)),
            stop(1, color(Color.WHITE))
        )
    ),

    //Using an exponential interpolation since earthquake magnitudes are on an exponential scale.
    heatmapWeight(
       interpolate(
            exponential(2),
            get("mag"),
            stop(0,0),

            //Any earthquake above a magnitude of 6 will have a weight of 1
            stop(6, 1)
       )
    )
)

На следующем снимке экрана показан пользовательский слой тепловой карты, использующий те же данные, что и в предыдущем примере тепловой карты.

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

Согласованная масштабируемая тепловая карта

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

Анимация, показывающая изменение размера карты с помощью слоя тепловой карты с соответствующим размером в пикселях

Используйте выражение zoom для изменения радиуса на всех уровнях масштабирования, чтобы каждая точка данных покрывала одну и ту же физическую область на карте. Это выражение делает слой тепловой карты более статичным и согласованным. Каждый уровень масштабирования карты имеет в два раза больше пикселей по вертикали и горизонтали, чем предыдущий.

Удваивание радиуса с каждым уровнем масштабирования позволяет создавать тепловые карты, которые выглядит согласованно на всех уровнях. Чтобы применить такое масштабирование, используйте выражение zoom с базовым значением 2 для exponential interpolation. Радиус пикселей должен быть задан для минимального уровня масштабирования, а масштабируемый радиус для максимального уровня — вычислен как 2 * Math.pow(2, minZoom - maxZoom), что показано в примере ниже. Измените масштаб, чтобы посмотреть, как меняется тепловая карта.

HeatMapLayer layer = new HeatMapLayer(source,
  heatmapRadius(
    interpolate(
      exponential(2),
      zoom(),

      //For zoom level 1 set the radius to 2 pixels.
      stop(1, 2f),

      //Between zoom level 1 and 19, exponentially scale the radius from 2 pixels to 2 * (maxZoom - minZoom)^2 pixels.
      stop(19, Math.pow(2, 19 - 1) * 2f)
    )
  ),
  heatmapOpacity(0.75f)
);
val layer = HeatMapLayer(source,
  heatmapRadius(
    interpolate(
      exponential(2),
      zoom(),

      //For zoom level 1 set the radius to 2 pixels.
      stop(1, 2f),

      //Between zoom level 1 and 19, exponentially scale the radius from 2 pixels to 2 * (maxZoom - minZoom)^2 pixels.
      stop(19, Math.pow(2.0, 19 - 1.0) * 2f)
    )
  ),
  heatmapOpacity(0.75f)
)

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

Анимация, показывающая изменение размера карты с помощью слоя тепловой карты с соответствующим геопространственным размером

Выражение zoom можно использовать только в выражениях step и interpolate. Следующее выражение можно использовать для приближения радиуса в метрах. Это выражение использует заполнитель radiusMeters, который следует заменить нужным радиусом. Это выражение вычисляет приблизительный радиус в пикселях для уровней масштабирования на экваторе 0 и 24, а также использует выражение exponential interpolation для масштабирования этих значений так же, как и в системе мозаичного заполнения на карте.

interpolate(
    exponential(2),
    zoom(),
    stop(1, product(radiusMeters, 0.000012776039596366526)),
    stop(24, product(radiusMeters, 214.34637593279402))
)

Совет

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

HeatMapLayer layer = new HeatMapLayer(dataSource,
   heatmapWeight(get("point_count"))
);

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

interpolate(
    exponential(2),
    zoom(),
    stop(1, product(radiusMeters, 0.000012776039596366526)),
    stop(24, product(radiusMeters, 214.34637593279402))
)

Совет

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

var layer = new HeatMapLayer(dataSource,
   heatmapWeight(get("point_count"))
)

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

Следующие шаги

Дополнительные примеры кода для добавления в карты см. в следующих статьях: