Aggiungere un livello mappa termica (Android SDK)
Nota
Ritiro di Android SDK di Mappe di Azure
Azure Maps Native SDK per Android è ora deprecato e verrà ritirato il 3/31/25. Per evitare interruzioni del servizio, eseguire la migrazione al Web SDK di Mappe di Azure entro il 31/3/25. Per altre informazioni, vedere La guida alla migrazione di Android SDK di Mappe di Azure.
Le mappe termiche, note anche come mappe di densità dei punti, sono un tipo di visualizzazione dei dati. Vengono usate per rappresentare la densità dei dati mediante una gamma di colori e mostrano gli "hot spot" dei dati su una mappa. Le mappe termiche sono un ottimo modo per eseguire il rendering dei set di dati con un numero elevato di punti.
Il rendering di decine di migliaia di punti come simboli può coprire la maggior parte dell'area della mappa. In questo caso è probabile che molti simboli si sovrappongano. In questo modo risulta più difficile comprendere meglio i dati. Tuttavia, la visualizzazione dello stesso set di dati di una mappa termica semplifica la visualizzazione della densità, inclusa quella relativa di ogni punto dati.
È possibile usare mappe termiche in molti scenari diversi, tra cui:
- Dati di temperatura: fornisce approssimazioni per la temperatura compresa tra due punti dati.
- Dati per i sensori di rumore: mostra non solo l'intensità del rumore in cui si trova il sensore, ma può anche fornire informazioni dettagliate sulla dissipazione lungo la distanza. Il livello di rumore in un sito potrebbe non essere elevato. Se l'area di copertura del rumore di più sensori si sovrappone, è possibile che questa area sovrapposta possa riscontrare livelli di rumore più elevati. Di conseguenza, l'area sovrapposta sarebbe visibile nella mappa termica.
- Traccia GPS: include la velocità come mappa dell'altezza ponderata, in cui l'intensità di ogni punto dati si basa sulla velocità. Ad esempio, questa funzionalità offre un modo per vedere dove un veicolo era in eccesso di velocità.
Suggerimento
Per impostazione predefinita, i livelli della mappa termica eseguiranno il rendering delle coordinate di tutte le geometrie in un'origine dati. Per limitare il livello in modo che esegua solo il rendering delle funzionalità geometriche dei punti, impostare l’opzione filter
del livello su eq(geometryType(), "Point")
. Per includere anche le funzionalità MultiPoint, impostare l’opzione filter
del livello su any(eq(geometryType(), "Point"), eq(geometryType(), "MultiPoint"))
.
Prerequisiti
Assicurarsi di completare la procedura descritta nel documento Guida introduttiva: creare un’app Android. È possibile inserire i blocchi di codice indicati in questo articolo nel gestore eventi onReady
delle mappe.
Aggiungere un livello mappa termica
Per eseguire il rendering di un'origine dati di punti come una mappa termica, è sufficiente trasferire l'origine dati in un'istanza della classe HeatMapLayer
e aggiungerla alla mappa.
L'esempio di codice seguente carica un feed GeoJSON dei terremoti della settimana precedente e lo esegue come mappa termica. Viene eseguito il rendering di ogni punto dati con un raggio di 10 pixel a tutti i livelli di zoom. Per garantire un'esperienza utente migliore, la mappa termica è al di sotto del livello etichetta, in modo che le etichette rimangano chiaramente visibili. I dati in questo esempio provengono dall'USGS Earthquake Hazards Program. Questo esempio carica i dati GeoJSON dal Web usando il blocco di codice dell'utilità di importazione dati fornito nel documento Creare un'origine dati.
//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")
Lo screenshot seguente mostra una mappa che carica una mappa termica usando il codice precedente.
Personalizzare il livello per le mappe termiche
Nell'esempio precedente viene personalizzata la mappa termica impostando le opzioni di radius e opacità. Il livello per le mappe termiche offre diverse opzioni per la personalizzazione, tra cui:
heatmapRadius
: definisce un raggio di pixel in cui eseguire il rendering di ogni punto dati. È possibile impostare il raggio come numero fisso o come espressione. Mediante l'uso di un'espressione è possibile ridimensionare il raggio in base al livello di zoom tramite la rappresentazione di un'area spaziale coerente sulla mappa (ad esempio, un raggio di 8 km circa).heatmapColor
: specifica come viene colorata la mappa termica. Una sfumatura di colore è una caratteristica comune delle mappe termiche. È possibile ottenere l'effetto con un'espressioneinterpolate
. È anche possibile usare un'espressionestep
per colorare la mappa termica, suddividendo visivamente la densità in intervalli simili a una mappa dello stile di contorno o radar. Queste tavolozze di colori definiscono i colori dal valore di densità minima a quello massimo.Specificare i valori di colore per le mappe termiche come espressione nel valore
heatmapDensity
. Il colore dell'area in cui non sono presenti dati è definito in corrispondenza dell'indice 0 dell'espressione "Interpolazione" o come il colore predefinito di un'espressione "Con rientri". È possibile usare questo valore per definire un colore di sfondo. Spesso, questo valore è impostato su trasparente o su un nero semitrasparente.Ecco alcuni esempi di espressioni di colore:
Espressione colore interpolazione Espressione colore graduale 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
: specifica quanto opaco o trasparente è il livello della mappa termica.heatmapIntensity
Applica un moltiplicatore al peso di ciascun punto dati per aumentare l'intensità complessiva della mappa termica. Causa una differenza nel peso dei punti dati, semplificando la visualizzazione.heatmapWeight
: per impostazione predefinita, tutti i punti dati hanno un peso pari a 1 e vengono ponderati equamente. L'opzione peso funge da moltiplicatore e può essere impostata come numero o espressione. Se un numero è impostato come peso, l'operazione equivale a posizionare ogni punto dati sulla mappa due volte. Ad esempio, se il peso è2
, la densità raddoppia. Impostando l'opzione peso su un numero, la mappa termica viene renderizzata in modo simile all'utilizzo dell'opzione intensità.Tuttavia, se viene usata un'espressione, il peso di ogni punto dati può basarsi sulle proprietà di ogni punto dati. Si supponga, ad esempio, che ogni punto dati rappresenti un terremoto. Il valore di grandezza è una metrica importante per ogni punto dati del terremoto. I terremoti si verificano continuamente, ma la maggior parte di essi hanno una bassa magnitudo e non vengono nemmeno percepiti. Usare il valore di grandezza in un'espressione per assegnare il peso a ogni punto dati. Usando il valore di grandezza per assegnare il peso, si ottiene una rappresentazione migliore della rilevanza dei terremoti all'interno della mappa termica.
minZoom
emaxZoom
: intervallo del livello di zoom in cui deve essere visualizzato il livello.filter
: espressione di filtro usata per limitare l'oggetto recuperato dall'origine e sottoposto a rendering nel livello.sourceLayer
: se l'origine dati connessa al livello è un'origine riquadro vettoriale, è necessario specificare un livello di origine all'interno dei riquadri vettoriali.visible
: nasconde o mostra il livello.
Il frammento di codice seguente è un esempio di mappa termica in cui viene usata un'espressione di interpolazione liner per creare una sfumatura di colore uniforme. La proprietà mag
definita nei dati viene usata con un'interpolazione esponenziale per impostare il peso o la pertinenza di ogni punto dati.
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)
)
)
)
Lo screenshot seguente mostra il livello mappa termica personalizzata con gli stessi dati dell'esempio di mappa termica precedente.
Mappa termica ridimensionabile coerente
Per impostazione predefinita, i raggi dei punti dati di cui viene eseguito il rendering nel livello mappa termica hanno un raggio di pixel fisso per tutti i livelli di zoom. Quando si esegue lo zoom della mappa, i dati vengono aggregati insieme e il livello mappa termica ha un aspetto diverso. Il video seguente mostra il comportamento predefinito della mappa termica in cui si mantiene un raggio di pixel durante lo zoom della mappa.
Usare un'espressione zoom
per ridimensionare il raggio per ogni livello di zoom, in modo che ogni punto dati copra la stessa area fisica della mappa. Questa espressione rende il livello mappa termica più statico e coerente. Ogni livello di zoom della mappa ha il doppio dei pixel verticali e orizzontali del livello di zoom precedente.
Ridimensionare il raggio in modo che raddoppi con ogni livello di zoom e che crei una mappa termica che abbia un aspetto coerente su tutti i livelli di zoom. Per applicare questa scalabilità, usare zoom
con un'espressione base 2 exponential interpolation
, con il raggio del pixel impostato per il livello di zoom minimo e un raggio scalato per il livello di zoom massimo calcolato come 2 * Math.pow(2, minZoom - maxZoom)
, come illustrato nell'esempio seguente. Ingrandire la mappa per verificare la scalabilità della mappa termica con il livello di zoom.
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)
)
Il video seguente mostra una mappa che esegue il codice precedente, che ridimensiona il raggio mentre viene ridotta al fine di creare un rendering coerente della mappa termica tra i livelli di zoom.
L'espressione zoom
può essere usata solo nelle espressioni step
e interpolate
. L'espressione seguente può essere usata per approssimare un raggio in metri. Questa espressione usa un segnaposto radiusMeters
, che deve essere sostituito con il raggio desiderato. Questa espressione calcola il raggio di pixel approssimativo per un livello di zoom all'equatore per i livelli di zoom 0 e 24 e usa un'espressione exponential interpolation
per scalare tra questi valori con lo stesso funzionamento del sistema di associazione nella mappa.
interpolate(
exponential(2),
zoom(),
stop(1, product(radiusMeters, 0.000012776039596366526)),
stop(24, product(radiusMeters, 214.34637593279402))
)
Suggerimento
Abilitando il clustering sull'origine dati, i punti che sono vicini l'uno all'altro sono raggruppati insieme come punto in cluster. È possibile usare il numero di punti di ogni cluster come espressione di peso per la mappa termica. Ciò può ridurre significativamente il numero di punti di cui eseguire il rendering. Il conteggio dei punti di un cluster viene archiviato in una proprietà point_count
della funzionalità punto:
HeatMapLayer layer = new HeatMapLayer(dataSource,
heatmapWeight(get("point_count"))
);
Se il raggio del clustering è di pochi pixel, il rendering presenta una piccola differenza visiva. Un raggio più grande raggruppa più punti in ogni cluster e migliora le prestazioni della mappa termica.
interpolate(
exponential(2),
zoom(),
stop(1, product(radiusMeters, 0.000012776039596366526)),
stop(24, product(radiusMeters, 214.34637593279402))
)
Suggerimento
Abilitando il clustering sull'origine dati, i punti che sono vicini l'uno all'altro sono raggruppati insieme come punto in cluster. È possibile usare il numero di punti di ogni cluster come espressione di peso per la mappa termica. Ciò può ridurre significativamente il numero di punti di cui eseguire il rendering. Il conteggio dei punti di un cluster viene archiviato in una proprietà point_count
della funzionalità punto:
var layer = new HeatMapLayer(dataSource,
heatmapWeight(get("point_count"))
)
Se il raggio del clustering è di pochi pixel, il rendering presenta una piccola differenza visiva. Un raggio più grande raggruppa più punti in ogni cluster e migliora le prestazioni della mappa termica.
Passaggi successivi
Per altri esempi di codice da aggiungere alle mappe, vedere gli articoli seguenti: