Choropleth mapping of half-million buildings in Philadelphia using Mapbox
When you start web mapping, you may use Leaflet and geojson
to create your first web-based geovisualization. However, if you try to visualize more geographical features, like tens of thousands or even more features, you may find your web map becomes very slow as your geojson
becomes much larger. Using Mapbox Tilling, you can visualize hundreds of thousands of features efficiently. Here is an example to create a choropleth map of about 500,000 building blocks in Philadelphia using Mapbox.
- Data preparation
The building footprint map and parcel-level land use map can be downloaded from Pennsylvania Spatial Data Access (Link). Fig 1. shows the building footprint map in Philadelphia.
In order to get the land-use type of each building block, I used Python + R-Tree
to do the intersection of the building footprint map and the land use map to assign the land use type for each building block. If you don’t want to do the intersection yourself, you can download the dataset from here. Fig. 2 shows the overlay of the land use map and building footprint map in a small region of Philadelphia.
After the intersection, the new building footprint map will have land-use information with a size of 125M. In order to visualize those building blocks on the web, we need to convert the shapefile into geojson
a file. There are many tools available to do the conversion. You can use GDAL
the command to do that, type the following command in your anaconda prompt,
ogr2ogr -f GeoJSON -t_srs crs:84 buildings_ft.geojson building_ft_lu.shp
Note: Make sure the building_ft_lu.shp
file is in your working directory.
If you don’t like to use the commands, you can use QGIS to do the conversion,
You will find the generated geojson
file is about 500M, much larger than your original shapefile and it is way beyond the upload limit of a geojson
file in Mapbox Studio.
You can convert the geojson
file into mbtiles
file using the tool of Tippecanoe. Type in the following command to do the conversion if you have Tippecanoe installed.
tippecanoe -ac -an -y landuse -l buildings -A “© Building land use types by Xiaojiang Li” -o buildings.mbtiles buildings.geojson
Here are some details about different parameters,
1. -y
to remove all metadata except for the landuse
field.
2. -ac
to coalesce adjacent features with the same property (in this case, matching only landuse
since that’s all we keep). Coalescing will have the effect of only allowing identical styling between these coalesced features, but since I just want to style based on land use type, this doesn’t really matter.
3. -an
to drop the physically smallest features in order to keep tile sizes within reasonable limits. For lower-zoom tiles which show many buildings at once, this won’t be noticeable visibly.
If you don’t have the Tippecanoe installed, you can install it easily. On Mac OS, the easiest way to install tippecanoe
on OSX is with Homebrew:
$ brew install tippecanoe
On Ubuntu it will usually be easiest to build from the source repository:
git clone https://github.com/mapbox/tippecanoe.git
cd tippecanoe
make -j
make install
The Tippecanoe is only available on Mac and Linux. If you are on Windows, you can use a Linux virtual machine or try to use a cloud computing environment.
You new mbtiles
file is much smaller, with a size of 15M. This is much smaller than 500M or 150M. Now, we are done with the data preparation and are ready for the geovisualization part. I provide the mbtiles
file here, if you are not able to do the conversion yourself.
2. Upload to Mapbox Studio and style your map
If you don’t have a Mapbox account, you need to register one for the following steps. Go to studio.mapbox.com to register your account.
Then click the Tileset
the menu on the top right of your page, and then click the New tileset
to upload your mbtiles
file.
After uploading your mbfiles
, then you can style your map in Mapbox studio. Click the Style
on the top right of your web page to create a new Style. Select one template as the basemap,
In my case, I select one dark basemap,
Click the layer on the top left of your styling page and add a new layer and find the id of your uploaded mbtiles
file. Then you can style your data layer, assign different land-use types as different colors.
When everything is done, then you can publish your data layer,
3. Let Mapbox Studio and Mapbox GL JS work together
Now let write code to create our web-map. Let’s first create a blank HTML page,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Display a map</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css" rel="stylesheet" /><style>
body {
margin: 0;
padding: 0;
}
h2,
h3 {
margin: 10px;
font-size: 1.2em;
}
h3 {
font-size: 1em;
}
p {
font-size: 0.85em;
margin: 10px;
text-align: left;
}
.map-overlay {
position: absolute;
bottom: 0;
right: 0;
background: rgba(255, 255, 255, 0.8);
margin-right: 20px;
font-family: Arial, sans-serif;
overflow: auto;
border-radius: 3px;
}
#map {
position: absolute;
top: 0;
bottom: 0;
width: 100%;
}
#features {
top: 0;
height: 100px;
margin-top: 20px;
width: 250px;
}
#legend {
padding: 10px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
line-height: 18px;
height: 150px;
margin-bottom: 40px;
width: 100px;
}
.legend-key {
display: inline-block;
border-radius: 20%;
width: 10px;
height: 10px;
margin-right: 5px;
}</style>
</head>
<body>
<div id="map"></div>
<div class="map-overlay" id="features">
<h2>Building footprint map</h2>
<div id="pd"><p>The building id is</p></div>
</div>
<div class="map-overlay" id="legend"></div><script></script></body>
</html>
We are going to write JavaScript code and add map elements. First, add your Mapbox token and map instance,
// put you token here
mapboxgl.accessToken = 'your-token'; var map = new mapboxgl.Map({
container: 'map',
style: 'mapbox://your-style-url',
zoom: 10,
center: [-75.150996, 39.992945]
});
Using your Mapbox Studio URL to replace the above mapbox://url
. You can find your URL by clicking sharing
on the top right of the Mapbox studio.
You can then open your .html
file and check your web page.
Adding the following code to add a legend to your map,
// add legend to your map
var layers = ['Commercial land', 'Residential land', 'Institutional land', 'Other'];
var colors = ['#bf0808', '#32f145', '#e9f54d', '#000000'];for (i = 0; i < layers.length; i++) {
var layer = layers[i];
var color = colors[i];
var item = document.createElement('div');
var key = document.createElement('span');
key.className = 'legend-key';
key.style.backgroundColor = color;var value = document.createElement('span');
value.innerHTML = layer;
item.appendChild(key);
item.appendChild(value);
legend.appendChild(item);
}
Add information window, when the cursor is hovering over a building block, the building land use information will show up.
map.on('load', function() {
map.getCanvas().style.cursor = 'default';
map.fitBounds([
[-75.299998, 40.091772],
[-75.011607, 39.884492]
]);
// change info window on hover
map.on('mousemove', function(e) {
var states = map.queryRenderedFeatures(e.point, {
layers: ['buildings-lu-new'] // get from the mapbox top left layer information
});
if (states.length > 0) {
document.getElementById('pd').innerHTML =
'<h3><strong> building id:' +
// states[0].properties.fid +
'</strong></h3><p><strong><em>' +
states[0].properties.landuse;
} else {
document.getElementById('pd').innerHTML =
'<p>The building id is: </p>';
}
});
});
Reference
Make choropleth maps using Mapbox, https://docs.mapbox.com/help/tutorials/choropleth-studio-gl-pt-1/
Visualzing building footprint using Mapbox, https://blog.mapbox.com/visualizing-an-entire-citys-buildings-live-with-runtime-styling-453fe7e39ae6