Lägga till ett heat map-lager (Android SDK)

Värmekartor, även kallade punktdensitetskartor, är en typ av datavisualisering. De används för att representera densiteten för data med hjälp av olika färger och visa data "hot spots" på en karta. Heat Maps är ett bra sätt att återge datauppsättningar med ett stort antal punkter.

Återgivning av tiotusentals punkter som symboler kan täcka de flesta av kartområdet. I det här fallet överlappar förmodligen många symboler. Gör det svårt att få en bättre förståelse av data. Men om du visualiserar samma datauppsättning som en heat map är det enkelt att se densiteten och den relativa densiteten för varje datapunkt.

Du kan använda värmekartor i många olika scenarier, inklusive:

  • Temperaturdata: Ger approximeringar för vad temperaturen är mellan två datapunkter.
  • Data för brussensorer: Visar inte bara brusintensiteten där sensorn är, utan kan även ge insikter om avledning över ett avstånd. Brusnivån på en plats kanske inte är hög. Om brustäckningsområdet från flera sensorer överlappar är det möjligt att det här överlappande området kan uppleva högre brusnivåer. Därför skulle det överlappade området vara synligt på den värmekartan.
  • GPS-spårning: Innehåller hastigheten som en viktad höjdkarta, där intensiteten för varje datapunkt baseras på hastigheten. Den här funktionen ger till exempel ett sätt att se var ett fordon kördes.

Tips

Skikt på en värmekarta återger som standard koordinaterna för alla geometrier i en datakälla. Om du vill begränsa skiktet så att det endast återger punktgeometrifunktioner anger filter du alternativet för skiktet till eq(geometryType(), "Point") . Om du även vill inkludera MultiPoint-funktioner anger du filter alternativet för skiktet till any(eq(geometryType(), "Point"), eq(geometryType(), "MultiPoint")) .


Förutsättningar

Se till att slutföra stegen i dokumentet Snabbstart: Skapa en Android-app. Kodblock i den här artikeln kan infogas i onReady händelsehanteraren maps.

Lägga till ett heatmapskikt

Om du vill rendera en datakälla med punkter som en heat map skickar du datakällan till en instans av klassen HeatMapLayer och lägger till den på kartan.

Följande kodexempel läser in ett GeoJSON-flöde med jordbävningar från den senaste veckan och återger dem som en värmekarta. Varje datapunkt renderas med en radie på 10 bildpunkter på alla zoomnivåer. För att säkerställa en bättre användarupplevelse ligger den värmekartan under etikettskiktet så att etiketterna syns tydligt. Data i det här exemplet kommer från USGS Earthquake Earthquake Earthquake Program. Det här exemplet läser in GeoJSON-data från webben med hjälp av kodblocket för dataimportverktyget i dokumentet Skapa en datakälla.

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

Följande skärmbild visar en karta som läser in en heat map med koden ovan.

Karta med det heat map-lager för de senaste jordbävningarna

Anpassa det värmekartskiktet

I föregående exempel anpassades den värmekartan genom att ange alternativen för radie och opacitet. Det värmekartskiktet innehåller flera anpassningsalternativ, bland annat:

  • heatmapRadius: Definierar en pixelradie där varje datapunkt ska återges. Du kan ange radien som ett fast tal eller som ett uttryck. Genom att använda ett uttryck kan du skala radien baserat på zoomningsnivån och representera ett konsekvent rumsligt område på kartan (till exempel en radie på 5 km).

  • heatmapColor: Anger hur den värmekartan färgiseras. En färgtoning är en vanlig funktion i värmekartor. Du kan uppnå effekten med ett interpolate uttryck. Du kan också använda ett uttryck för att färglägga den värmekartan, och dela upp densiteten visuellt i intervall som liknar en karta step i radarstil. Dessa färgpaletter definierar färgerna från lägsta till högsta densitet.

    Du anger färgvärden för värmekartor som ett uttryck för heatmapDensity värdet. Färgen på området där det inte finns några data definieras vid index 0 i uttrycket "Interpolation" eller standardfärgen för ett "stegvist" uttryck. Du kan använda det här värdet för att definiera en bakgrundsfärg. Det här värdet är ofta inställt på transparent eller halvtransparent svart.

    Här följer exempel på färguttryck:

    Interpolationsfärguttryck Stegvist färguttryck
    interpolate(
        linear(),
        heatmapDensity(),
        stop(0, color(Color.TRANSPARENT)),
        stop(0.01, color(Color.HOSTINGTA)),
        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: Anger hur täckande eller transparent det heat map-skiktet är.

  • heatmapIntensity: Tillämpar en multiplikator på vikten för varje datapunkt för att öka den övergripande intensiteten för den heatmap. Det orsakar en skillnad i vikten av datapunkter, vilket gör det enklare att visualisera.

  • heatmapWeight: Som standard har alla datapunkter en vikt på 1 och viktas lika. Viktalternativet fungerar som en multiplikator och du kan ange det som ett tal eller ett uttryck. Om ett tal anges som vikt är det likvärdigt att placera varje datapunkt på kartan två gånger. Om vikten till exempel är 2 fördubblas densiteten. Om du anger viktalternativet till ett tal återges den värmekartan på ett liknande sätt som med hjälp av alternativet för intensitet.

    Men om du använder ett uttryck kan vikten för varje datapunkt baseras på egenskaperna för varje datapunkt. Anta till exempel att varje datapunkt representerar en jordbävning. Storleksvärdet har varit ett viktigt mått för varje jordbävningsdatapunkt. Jordbävningar sker hela tiden, men de flesta har en låg omfattning och märks inte. Använd storleksvärdet i ett uttryck för att tilldela vikten till varje datapunkt. Genom att använda storleksvärdet för att tilldela vikten får du en bättre representation av jordbävningens betydelse inom den värmekartan.

  • minZoom och maxZoom : Intervallet för zoomningsnivån där skiktet ska visas.

  • filter: Ett filteruttryck som används för att begränsa det som hämtas från källan och återges i lagret.

  • sourceLayer: Om datakällan som är ansluten till lagret är en vektorpanelkälla måste ett källskikt i vektorpanelerna anges.

  • visible: Döljer eller visar lagret.

Följande är ett exempel på en heat map där ett interpolationsuttryck används för att skapa en jämn färgtoning. Egenskapen mag som definieras i data används med en exponentiell interpolering för att ange vikt eller relevans för varje datapunkt.

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

Följande skärmbild visar det anpassade heat map-lagret ovan med samma data från föregående exempel på en heat map.

Karta med anpassat heat map-lager för de senaste jordbävningarna

Konsekvent zoombar heat map

Som standard har radialen av datapunkter som återges i det heat map-skiktet en fast pixelradie för alla zoomningsnivåer. När du zoomar kartan aggregeras data och det heat map-skiktet ser annorlunda ut. Följande video visar standardbeteendet för den värmekarta där den har en pixelradie när kartan zoomas.

Animering som visar en karta som zoomar med ett heat map-lager som visar en konsekvent bildpunktsstorlek

Använd ett zoom uttryck för att skala radien för varje zoomnivå, så att varje datapunkt täcker samma fysiska område på kartan. Det här uttrycket gör att det heat map-lagret ser mer statiskt och konsekvent ut. Varje zoomnivå på kartan har dubbelt så många bildpunkter lodrätt och vågrätt som den föregående zoomnivån.

Om du skalar radien så att den fördubblas med varje zoomnivå skapas en heat map som ser konsekvent ut på alla zoomnivåer. Om du vill använda den här skalningen använder du med ett base 2-uttryck, där pixelradien är inställd för den lägsta zoomningsnivån och en skalad radie för den maximala zoomningsnivån beräknad enligt följande zoom exponential interpolation 2 * Math.pow(2, minZoom - maxZoom) exempel. Zooma kartan för att se hur den värmekartan skalar med zoomningsnivån.

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

Följande video visar en karta som kör koden ovan, som skalar radien medan kartan zoomas för att skapa en konsekvent återgivning av den värmekartan över zoomningsnivåer.

Animering som visar en kart zoomning med ett heat map-lager som visar en konsekvent geospatial storlek

Uttrycket zoom kan bara användas i step uttrycken och interpolate . Följande uttryck kan användas för att göra en ungefärlig radie i meter. Det här uttrycket använder en radiusMeters platshållare som du bör ersätta med önskad radie. Det här uttrycket beräknar den ungefärliga pixelradien för en zoomningsnivå på ekvatorn för zoomningsnivå 0 och 24, och använder ett uttryck för att skala mellan dessa värden på samma sätt som exponential interpolation tilingsystemet på kartan fungerar.

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

Tips

När du aktiverar klustring på datakällan grupperas punkter som är nära varandra tillsammans som en klustrad punkt. Du kan använda punktantalet för varje kluster som viktuttryck för den värmekartan. Detta kan avsevärt minska antalet punkter som ska återges. Punktantalet för ett kluster lagras i point_count en egenskap för punktfunktionen:

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

Om klustringsradien bara är några få bildpunkter skulle det finnas en liten visuell skillnad i renderingen. En större radie grupperar fler punkter i varje kluster och förbättrar prestanda för den heatmap.

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

Tips

När du aktiverar klustring på datakällan grupperas punkter som är nära varandra tillsammans som en klustrad punkt. Du kan använda punktantalet för varje kluster som viktuttryck för den värmekartan. Detta kan avsevärt minska antalet punkter som ska återges. Punktantalet för ett kluster lagras i point_count en egenskap för punktfunktionen:

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

Om klustringsradien bara är några få bildpunkter skulle det finnas en liten visuell skillnad i renderingen. En större radie grupperar fler punkter i varje kluster och förbättrar prestanda för den heatmap.

Nästa steg

Fler kodexempel att lägga till i dina kartor finns i följande artiklar: