London Air Data Visualisation

London Air Data Visualisation

A little while ago we started a project to visualise the rise & fall of pollution levels in London over a year, using King’s College London’s air data -

Here’s how the project turned out…

View on Vimeo:

King’s College is responsible for monitoring and reporting pollution levels (amongst other things) at dozens of sites in Greater London.

London Air are already showing pollutant levels in great detail on their site as historical graphs and and a realtime heatmap shown over Google maps. Graphs & Heatmaps Graphs & Heatmaps

We were interested to see, both out of aesthetic and intellectual curiosity,  if you combined the historical graphing data with each of the sites geolocation, what annual / geographical pattern (if any) would be revealed but also what creative applications rich data like this can be used for.


Once we had gathered the pollutant values and each site’s latitude & longitude we could start plotting values over a map which we sourced over at

As we knew what general area we were mapping and the size of our presentation we could select the exact map graphic we needed and openstreetmap brilliantly gives you the (lat,long) bounds of that selected map.

Generating our map image with

Generating our map image with

To find a (lat,long) position (in pixels) on a map graphic was made easier thanks to this Processing Map Projection utility created by City University London (appropriately) giCentre.

Different maps use different projection systems like Albers, French NTF, Oblique Mercator etc. However, OpenStreetMap and Google use a WebMercator projection.

Knowing this and using the giCentre utility, we could return screen coordinates from input map bounds & individual site’s (lat,long).

import org.gicentre.utils.spatial.*;


// Get corners of map in WebMercator coordinates.
WebMercator proj = new WebMercator();
PVector tlCorner,brCorner;   

void initMapTile() {
  // converted long,lat of top left of map tile
  tlCorner = proj.transformCoords(new PVector(-0.79,51.732));
  // converted long,lat of bottm right of map tile
  brCorner = proj.transformCoords(new PVector(0.489, 51.227));  


// Convert from WebMercator coordinates to screen coordinates.
PVector geoToScreen(PVector geo) {
  return new PVector(map(geo.x,tlCorner.x,brCorner.x,0,1366),

So we could now start seeing individual pollutant levels rising and falling over geo locations on our map.

London Air Data Values Visualised

London Air data values visualised with geolocation pins

A 3D mesh would  be better

Bars are great, but a mesh over the map would be better, as not only would it be aesthetically much nicer, but it would act as 3D graph.

From this you could perhaps get a sense of what a possible value “could” be between 2 “known” data points on the map. (Important to note here it would only be an estimate.)

However, standard 3D meshes are made up of regularly spaced triangles, but our real world geolocations don’t fall into a nice, evenly spaced grid.

An Irregular Mesh

An Irregular Mesh

We needed a grid like this and ToxicLibs, which we were already using for our 3D came to the rescue… here is the thread of the conversation on the Processing forum.

Simply put, we wanted to connect all of a sites together (without creating overlapping triangles) to form this irregular mesh. This is a process called Delaunay Triangulation.

Karsten Schmidt explains it here, but basically you pass your points into a 2D Vornoi instance, and from that you get back triangles for use in your irregular 3D mesh.

Voronoi v=new Voronoi();
// add points

TriangleMesh mesh=new TriangleMesh();
for (Triangle2D t : voronoi.getTriangles()) {
  mesh.addFace(t.a.to3DXY(), t.b.to3DXY(), t.c.to3DXY());

Once we had our irregular mesh, we simply had to push our data values to the “z” value of the corresponding point and there we had an animating mesh of pollutant values over time.

London Air Data Mesh & Pins

London Air Data Mesh & Pins

London Air Data Mesh

London Air Data Mesh

Taking Control of the View

While developing the system, we had obviously created numerous variables that controlled the appearance of the mesh the view.

We also wanted a way of toggling sites on & off so a user could view the pollutant levels at their sites of interest.

We used Andreas Schlegel’s excellent ControlP5 Processing GUI library to give us control over our application’s internal variables like:

  • Viewing Angle
  • Mouse / Auto Rotation
  • Sites Toggle
  • Wireframe Colour
  • Mesh Fill Colour
  • Marker Pin Toggle
  • Data Pause / Play
ControlP5 GUI

ControlP5 GUI

London Air Data Visualisation with ControlP5 GUI

London Air Data Visualisation with ControlP5 GUI

Not The End

As always with a project like this, limitless improvements, ideas and variations are now obvious that we’d love to add / investigate:

  • A timeline to allow scrubbing back & forth through the data
  • A way of representing scale, to show if levels are low, medium or high
  • Multiple pollutant meshes.
  • Creating a web interface (other than the usual Java embed) or App
  • Gesture control, perhaps using a Kinect or LeapMotion
  • Maybe one day a physical installation version of the system.

Let’s see what happens next…

Thanks & Links

Many thanks to everyone involved and those in the Processing community who have created so many great libraries.

This entry was posted in Creative, Projects, Tech and tagged , , , , , , , , . Bookmark the permalink.

One Response to London Air Data Visualisation

  1. Pingback: London air pollution visualisation | Respro® Bulletin Board