Udostępnij za pośrednictwem


Dodawanie warstwy mapy cieplnej (android SDK)

Uwaga

Wycofanie zestawu SDK systemu Android w usłudze Azure Maps

Zestaw SDK natywny usługi Azure Maps dla systemu Android jest teraz przestarzały i zostanie wycofany w dniu 3/31/25. Aby uniknąć przerw w działaniu usługi, przeprowadź migrację do zestawu Web SDK usługi Azure Maps przez 3/31/25. Aby uzyskać więcej informacji, zobacz Przewodnik migracji zestawu SDK systemu Android usługi Azure Maps.

Mapy cieplne, nazywane również mapami gęstości punktów, są typem wizualizacji danych. Są one używane do reprezentowania gęstości danych przy użyciu różnych kolorów i pokazywania danych "gorących punktów" na mapie. Mapy cieplne to doskonały sposób renderowania zestawów danych z dużą liczbą punktów.

Renderowanie dziesiątek tysięcy punktów jako symboli może obejmować większość obszaru mapy. Ten przypadek prawdopodobnie powoduje nakładanie się wielu symboli. Utrudnianie lepszego zrozumienia danych. Jednak wizualizowanie tego samego zestawu danych co mapa cieplna ułatwia sprawdzenie gęstości i względnej gęstości każdego punktu danych.

Mapy cieplne można używać w wielu różnych scenariuszach, w tym:

  • Dane dotyczące temperatury: zapewnia przybliżenia temperatury między dwoma punktami danych.
  • Dane dotyczące czujników szumu: pokazuje nie tylko intensywność szumu, w którym znajduje się czujnik, ale może również zapewnić wgląd w rozproszenie na odległość. Poziom szumu w każdej lokacji może nie być wysoki. Jeśli obszar pokrycia szumu z wielu czujników nakłada się na siebie, możliwe, że ten nakładający się obszar może doświadczać wyższego poziomu szumu. W związku z tym nakładany obszar będzie widoczny na mapie cieplnej.
  • Ślad GPS: zawiera szybkość jako mapę ważonej wysokości, gdzie intensywność każdego punktu danych jest oparta na szybkości. Na przykład ta funkcja umożliwia sprawdzenie, gdzie pojazd pędzył.

Napiwek

Warstwy mapy cieplnej domyślnie renderują współrzędne wszystkich geometrii w źródle danych. Aby ograniczyć warstwę tak, aby renderowana była tylko cechy geometrii punktów, ustaw filter opcję warstwy na eq(geometryType(), "Point"). Jeśli chcesz również uwzględnić funkcje MultiPoint, ustaw filter opcję warstwy na any(eq(geometryType(), "Point"), eq(geometryType(), "MultiPoint")).


Wymagania wstępne

Pamiętaj, aby wykonać kroki opisane w przewodniku Szybki start: tworzenie dokumentu aplikacji dla systemu Android. Bloki kodu w tym artykule można wstawić do programu obsługi zdarzeń map onReady .

Dodawanie warstwy mapy cieplnej

Aby renderować źródło danych punktów jako mapę cieplną, przekaż źródło danych do wystąpienia HeatMapLayer klasy i dodaj je do mapy.

Poniższy przykładowy kod ładuje źródło danych GeoJSON trzęsień ziemi z ostatniego tygodnia i renderuje je jako mapę cieplną. Każdy punkt danych jest renderowany z promieniem 10 pikseli na wszystkich poziomach powiększenia. Aby zapewnić lepsze środowisko użytkownika, mapa cieplna znajduje się poniżej warstwy etykiety, dzięki czemu etykiety pozostają wyraźnie widoczne. Dane w tym przykładzie pochodzą z USGS Earthquake Hazards Program. W tym przykładzie dane GeoJSON są ładowane z Internetu przy użyciu bloku kodu narzędzia importu danych podanego w dokumencie Tworzenie źródła danych.

//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")

Poniższy zrzut ekranu przedstawia mapę ładowania mapy cieplnej przy użyciu powyższego kodu.

Mapa z warstwą mapy cieplnej ostatnich trzęsień ziemi

Dostosowywanie warstwy mapy cieplnej

W poprzednim przykładzie dostosowano mapę cieplną, ustawiając opcje promienia i nieprzezroczystości. Warstwa mapy cieplnej oferuje kilka opcji dostosowywania, w tym:

  • heatmapRadius: definiuje promień pikseli, w którym ma być renderowany każdy punkt danych. Promień można ustawić jako stałą liczbę lub jako wyrażenie. Za pomocą wyrażenia można skalować promień na podstawie poziomu powiększenia i reprezentować spójny obszar przestrzenny na mapie (na przykład 5-milowy promień).

  • heatmapColor: określa sposób kolorowania mapy cieplnej. Gradient kolorów jest wspólną cechą map cieplnych. Efekt można osiągnąć za pomocą interpolate wyrażenia. Możesz również użyć step wyrażenia do kolorowania mapy cieplnej, dzieląc gęstość wizualnie na zakresy przypominające mapę konturu lub radaru. Te palety kolorów definiują kolory od minimum do maksymalnej wartości gęstości.

    Wartości kolorów map cieplnych można określić jako wyrażenie wartości heatmapDensity . Kolor obszaru, w którym nie ma danych, jest zdefiniowany na indeksie 0 wyrażenia "Interpolacja" lub domyślny kolor wyrażenia "Schodkowego". Tej wartości można użyć do zdefiniowania koloru tła. Często ta wartość jest ustawiona na przezroczystą lub półprzezroczystą czarną.

    Oto przykłady wyrażeń kolorów:

    Wyrażenie koloru interpolacji Wyrażenie koloru schodkowego
    interpolacja(
        linear(),
        mapa cieplnaDensity(),
        stop(0, color(Color.TRANSPARENT)),
        stop(0.01, color(Color.MAGENTA)),
        stop(0.5, color(parseColor("#fb00fb"))),
        stop(1, color(parseColor("#00c3ff")))
    )`
    step(
        mapa cieplnaDensity(),
        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: określa, jak nieprzezroczysta lub przezroczysta jest warstwa mapy cieplnej.

  • heatmapIntensity: Stosuje mnożnik do wagi każdego punktu danych, aby zwiększyć ogólną intensywność mapy cieplnej. Powoduje to różnicę w wadze punktów danych, co ułatwia wizualizowanie.

  • heatmapWeight: Domyślnie wszystkie punkty danych mają wagę 1 i są ważone w równym stopniu. Opcja waga działa jako mnożnik i można ustawić ją jako liczbę lub wyrażenie. Jeśli liczba jest ustawiona jako waga, jest to równoważność umieszczania każdego punktu danych na mapie dwa razy. Jeśli na przykład waga to 2, gęstość podwoi się. Ustawienie opcji wagi na liczbę renderuje mapę cieplną w podobny sposób do użycia opcji intensywności.

    Jeśli jednak używasz wyrażenia, waga każdego punktu danych może być oparta na właściwościach każdego punktu danych. Załóżmy na przykład, że każdy punkt danych reprezentuje trzęsienie ziemi. Wartość wielkości była ważną metryą dla każdego punktu danych trzęsienia ziemi. Trzęsienia ziemi zdarzają się cały czas, ale większość ma niską wielkość i nie są zauważane. Użyj wartości wielkości w wyrażeniu, aby przypisać wagę do każdego punktu danych. Używając wartości wielkości do przypisania wagi, uzyskasz lepszą reprezentację znaczenia trzęsień ziemi w mapie cieplnej.

  • minZoom i maxZoom: Zakres poziomów powiększenia, w którym powinna być wyświetlana warstwa.

  • filter: wyrażenie filtru używane do ograniczania pobranego ze źródła i renderowanego w warstwie.

  • sourceLayer: Jeśli źródło danych połączone z warstwą jest źródłem kafelka wektorowego, należy określić warstwę źródłową w kafelkach wektorowych.

  • visible: ukrywa lub wyświetla warstwę.

Poniższy fragment kodu jest przykładem mapy cieplnej, w której wyrażenie interpolacji liniowej służy do tworzenia płynnego gradientu kolorów. Właściwość zdefiniowana mag w danych jest używana z interpolacją wykładniczą w celu ustawienia wagi lub istotności każdego punktu danych.

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)
       )
    )
)

Poniższy zrzut ekranu przedstawia powyższą niestandardową warstwę mapy cieplnej przy użyciu tych samych danych z poprzedniego przykładu mapy cieplnej.

Mapa z niestandardową warstwą mapy cieplnej ostatnich trzęsień ziemi

Spójna mapa cieplna z możliwością powiększania

Domyślnie promienie punktów danych renderowanych w warstwie mapy cieplnej mają stały promień pikseli dla wszystkich poziomów powiększenia. Podczas powiększania mapy dane agregują się razem, a warstwa mapy cieplnej wygląda inaczej. Poniższy film wideo przedstawia domyślne zachowanie mapy cieplnej, w której zachowuje promień pikseli podczas powiększania mapy.

Animacja przedstawiająca powiększenie mapy z warstwą mapy cieplnej pokazującą spójny rozmiar pikseli

zoom Użyj wyrażenia, aby skalować promień dla każdego poziomu powiększenia, tak aby każdy punkt danych obejmował ten sam fizyczny obszar mapy. To wyrażenie sprawia, że warstwa mapy cieplnej wygląda bardziej statycznie i spójnie. Każdy poziom powiększenia mapy ma dwa razy więcej pikseli w pionie i w poziomie, jak poprzedni poziom powiększenia.

Skalowanie promienia w taki sposób, aby podwoiło się z każdym poziomem powiększenia, tworzy mapę cieplną, która wygląda spójnie na wszystkich poziomach powiększenia. Aby zastosować to skalowanie, użyj zoom wyrażenia podstawowego 2 exponential interpolation z promieniem pikseli ustawionym dla minimalnego poziomu powiększenia i promieniem skalowanym dla maksymalnego poziomu powiększenia obliczonego, jak 2 * Math.pow(2, minZoom - maxZoom) pokazano w poniższym przykładzie. Powiększ mapę, aby zobaczyć, jak mapa cieplna skaluje się z poziomem powiększenia.

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)
)

Poniższy film wideo przedstawia mapę uruchamianą powyżej kodu, która skaluje promień, gdy mapa jest powiększana, aby utworzyć spójne renderowanie mapy cieplnej na różnych poziomach powiększenia.

Animacja przedstawiająca powiększenie mapy z warstwą mapy cieplnej przedstawiającą spójny rozmiar geoprzestrzenny

Wyrażenie zoom może być używane tylko w wyrażeniach step i interpolate . Poniższe wyrażenie może służyć do przybliżenia promienia w metrach. To wyrażenie używa symbolu zastępczego radiusMeters, który należy zastąpić żądanym promieniem. To wyrażenie oblicza przybliżony promień pikseli dla poziomu powiększenia na równiku poziomów powiększenia 0 i 24 i używa exponential interpolation wyrażenia do skalowania między tymi wartościami w taki sam sposób, jak działa system układania kafelków w mapie.

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

Napiwek

Po włączeniu klastrowania w źródle danych punkty, które znajdują się blisko siebie, są grupowane razem jako punkt klastrowany. Liczbę punktów każdego klastra można użyć jako wyrażenia wagi dla mapy cieplnej. Może to znacznie zmniejszyć liczbę punktów do renderowania. Liczba punktów klastra jest przechowywana we point_count właściwości funkcji punktu:

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

Jeśli promień klastrowania wynosi tylko kilka pikseli, w renderowaniu występuje niewielka różnica wizualna. Większy promień grupuje więcej punktów w każdym klastrze i poprawia wydajność mapy cieplnej.

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

Napiwek

Po włączeniu klastrowania w źródle danych punkty, które znajdują się blisko siebie, są grupowane razem jako punkt klastrowany. Liczbę punktów każdego klastra można użyć jako wyrażenia wagi dla mapy cieplnej. Może to znacznie zmniejszyć liczbę punktów do renderowania. Liczba punktów klastra jest przechowywana we point_count właściwości funkcji punktu:

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

Jeśli promień klastrowania wynosi tylko kilka pikseli, w renderowaniu występuje niewielka różnica wizualna. Większy promień grupuje więcej punktów w każdym klastrze i poprawia wydajność mapy cieplnej.

Następne kroki

Aby uzyskać więcej przykładów kodu do dodania do map, zobacz następujące artykuły: