Custom Heatmap Layer

This example shows how to Add a HeatMap layer to MapView

  • Create HeatMap source with GeoJson Source

  • Create HeatMap Layer with heatmap properties

  • Add HeatMap Layer to MapView

Custom Heatmap Layer

For all code examples, refer to Android Maps SDK Code Examples

activity_heatmaplayer.xml view source

1
<?xml version="1.0" encoding="utf-8"?>
2
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
android:layout_width="match_parent"
4
android:layout_height="match_parent"
5
android:orientation="vertical">
6
7
<ai.nextbillion.maps.core.MapView
8
android:id="@+id/mapView"
9
android:layout_width="match_parent"
10
android:layout_height="match_parent" />
11
12
</RelativeLayout>

HeatmapLayerActivity view source

1
package ai.nextbillion;
2
3
import android.os.Bundle;
4
5
import java.net.URI;
6
import java.net.URISyntaxException;
7
8
import ai.nextbillion.maps.core.MapView;
9
import ai.nextbillion.maps.core.NextbillionMap;
10
import ai.nextbillion.maps.core.Style;
11
import ai.nextbillion.maps.style.layers.CircleLayer;
12
import ai.nextbillion.maps.style.layers.HeatmapLayer;
13
import ai.nextbillion.maps.style.sources.GeoJsonSource;
14
import androidx.appcompat.app.AppCompatActivity;
15
16
import static ai.nextbillion.maps.style.expressions.Expression.get;
17
import static ai.nextbillion.maps.style.expressions.Expression.heatmapDensity;
18
import static ai.nextbillion.maps.style.expressions.Expression.interpolate;
19
import static ai.nextbillion.maps.style.expressions.Expression.linear;
20
import static ai.nextbillion.maps.style.expressions.Expression.literal;
21
import static ai.nextbillion.maps.style.expressions.Expression.rgb;
22
import static ai.nextbillion.maps.style.expressions.Expression.rgba;
23
import static ai.nextbillion.maps.style.expressions.Expression.stop;
24
import static ai.nextbillion.maps.style.expressions.Expression.zoom;
25
import static ai.nextbillion.maps.style.layers.PropertyFactory.circleColor;
26
import static ai.nextbillion.maps.style.layers.PropertyFactory.circleOpacity;
27
import static ai.nextbillion.maps.style.layers.PropertyFactory.circleRadius;
28
import static ai.nextbillion.maps.style.layers.PropertyFactory.circleStrokeColor;
29
import static ai.nextbillion.maps.style.layers.PropertyFactory.circleStrokeWidth;
30
import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapColor;
31
import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapIntensity;
32
import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapOpacity;
33
import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapRadius;
34
import static ai.nextbillion.maps.style.layers.PropertyFactory.heatmapWeight;
35
36
/**
37
* Test activity showcasing the heatmap layer api.
38
*/
39
public class HeatmapLayerActivity extends AppCompatActivity {
40
41
private static final String EARTHQUAKE_SOURCE_URL = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson";
42
private static final String EARTHQUAKE_SOURCE_ID = "earthquakes";
43
private static final String HEATMAP_LAYER_ID = "earthquakes-heat";
44
private static final String HEATMAP_LAYER_SOURCE = "earthquakes";
45
private static final String CIRCLE_LAYER_ID = "earthquakes-circle";
46
47
private MapView mapView;
48
private NextbillionMap nextbillionMap;
49
50
@Override
51
public void onCreate(Bundle savedInstanceState) {
52
super.onCreate(savedInstanceState);
53
setContentView(R.layout.activity_heatmaplayer);
54
mapView = findViewById(R.id.mapView);
55
mapView.onCreate(savedInstanceState);
56
mapView.getMapAsync(map -> {
57
nextbillionMap = map;
58
59
try {
60
nextbillionMap.setStyle(new Style.Builder()
61
.fromUri("https://api.nextbillion.io/maps/dark/style.json")
62
.withSource(createEarthquakeSource())
63
.withLayerAbove(createHeatmapLayer(), "waterway-bridge")
64
.withLayerBelow(createCircleLayer(), HEATMAP_LAYER_ID)
65
);
66
} catch (URISyntaxException exception) {
67
}
68
});
69
}
70
71
private GeoJsonSource createEarthquakeSource() throws URISyntaxException {
72
return new GeoJsonSource(EARTHQUAKE_SOURCE_ID, new URI(EARTHQUAKE_SOURCE_URL));
73
}
74
75
private HeatmapLayer createHeatmapLayer() {
76
HeatmapLayer layer = new HeatmapLayer(HEATMAP_LAYER_ID, EARTHQUAKE_SOURCE_ID);
77
layer.setMaxZoom(9);
78
layer.setSourceLayer(HEATMAP_LAYER_SOURCE);
79
layer.setProperties(
80
81
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
82
// Begin color ramp at 0-stop with a 0-transparancy color
83
// to create a blur-like effect.
84
heatmapColor(
85
interpolate(
86
linear(), heatmapDensity(),
87
literal(0), rgba(33, 102, 172, 0),
88
literal(0.2), rgb(103, 169, 207),
89
literal(0.4), rgb(209, 229, 240),
90
literal(0.6), rgb(253, 219, 199),
91
literal(0.8), rgb(239, 138, 98),
92
literal(1), rgb(178, 24, 43)
93
)
94
),
95
96
// Increase the heatmap weight based on frequency and property magnitude
97
heatmapWeight(
98
interpolate(
99
linear(), get("mag"),
100
stop(0, 0),
101
stop(6, 1)
102
)
103
),
104
105
// Increase the heatmap color weight weight by zoom level
106
// heatmap-intensity is a multiplier on top of heatmap-weight
107
heatmapIntensity(
108
interpolate(
109
linear(), zoom(),
110
stop(0, 1),
111
stop(9, 3)
112
)
113
),
114
115
// Adjust the heatmap radius by zoom level
116
heatmapRadius(
117
interpolate(
118
linear(), zoom(),
119
stop(0, 2),
120
stop(9, 20)
121
)
122
),
123
124
// Transition from heatmap to circle layer by zoom level
125
heatmapOpacity(
126
interpolate(
127
linear(), zoom(),
128
stop(7, 1),
129
stop(9, 0)
130
)
131
)
132
);
133
return layer;
134
}
135
136
private CircleLayer createCircleLayer() {
137
CircleLayer circleLayer = new CircleLayer(CIRCLE_LAYER_ID, EARTHQUAKE_SOURCE_ID);
138
circleLayer.setProperties(
139
140
// Size circle radius by earthquake magnitude and zoom level
141
circleRadius(
142
interpolate(
143
linear(), zoom(),
144
literal(7), interpolate(
145
linear(), get("mag"),
146
stop(1, 1),
147
stop(6, 4)
148
),
149
literal(16), interpolate(
150
linear(), get("mag"),
151
stop(1, 5),
152
stop(6, 50)
153
)
154
)
155
),
156
157
// Color circle by earthquake magnitude
158
circleColor(
159
interpolate(
160
linear(), get("mag"),
161
literal(1), rgba(33, 102, 172, 0),
162
literal(2), rgb(103, 169, 207),
163
literal(3), rgb(209, 229, 240),
164
literal(4), rgb(253, 219, 199),
165
literal(5), rgb(239, 138, 98),
166
literal(6), rgb(178, 24, 43)
167
)
168
),
169
170
// Transition from heatmap to circle layer by zoom level
171
circleOpacity(
172
interpolate(
173
linear(), zoom(),
174
stop(7, 0),
175
stop(8, 1)
176
)
177
),
178
circleStrokeColor("white"),
179
circleStrokeWidth(1.0f)
180
);
181
182
return circleLayer;
183
}
184
185
@Override
186
protected void onStart() {
187
super.onStart();
188
mapView.onStart();
189
}
190
191
@Override
192
protected void onResume() {
193
super.onResume();
194
mapView.onResume();
195
}
196
197
@Override
198
protected void onPause() {
199
super.onPause();
200
mapView.onPause();
201
}
202
203
@Override
204
protected void onStop() {
205
super.onStop();
206
mapView.onStop();
207
}
208
209
@Override
210
public void onSaveInstanceState(Bundle outState) {
211
super.onSaveInstanceState(outState);
212
mapView.onSaveInstanceState(outState);
213
}
214
215
@Override
216
public void onLowMemory() {
217
super.onLowMemory();
218
mapView.onLowMemory();
219
}
220
221
@Override
222
public void onDestroy() {
223
super.onDestroy();
224
mapView.onDestroy();
225
}
226
}
227

This code is an example of an Android activity that showcases the use of a heatmap layer in a map view. The activity creates a map view, sets up a heatmap layer with a GeoJSON data source, and adds the heatmap layer to the map view.

initMapView:

  • The map view is initialized in the onCreate method by calling mapView.onCreate(savedInstanceState). This sets up the map view and prepares it for use.

Create HeatMap source with GeoJson Source:

  • The createEarthquakeSource method creates a GeoJsonSource for the heatmap layer using a GeoJSON data source. It takes the URL of the GeoJSON data as a parameter and creates a new GeoJsonSource object with a unique ID and the provided data source URL.

Create HeatMap Layer with heatmap properties:

  • The createHeatmapLayer method creates a HeatmapLayer object with a unique ID and sets various properties for the heatmap layer.

  • The properties include the color ramp for the heatmap, the weight of the heatmap based on frequency and magnitude, the intensity and radius of the heatmap based on the zoom level, and the opacity transition from the heatmap to the circle layer.

Add HeatMap Layer to MapView:

  • In the onCreate method, after setting up the map view, the nextbillionMap.setStyle method is called to set the map style and add the heatmap layer to the map view.

  • The Style.Builder is used to create a new map style and the createEarthquakeSource and createHeatmapLayer methods are called to create the GeoJSON data source and heatmap layer, respectively.

  • The created source and layer are then added to the map style using the withSource and withLayerAbove or withLayerBelow methods, depending on the desired layer order.

Note: The code also includes methods for creating a circle layer, setting up the map view lifecycle callbacks, and handling various other lifecycle events of the activity.

© 2024 NextBillion.ai all rights reserved.