Overlaying a heat map

For this recipe we are going to overlay a heat map over a map layer. This is a bit more challenging than what we did before but it should go smoothly as the concept is not that complex. Heat maps are used to represent density over a region by adding different colors over certain areas. In the case, we are going to display the number of animal specimens over the area of the United States using the Global Biodiversity Information Facility's data.

Overlaying a heat map

Getting ready

Open the files from the code downloaded from the Packt Publishing web site in the folder Chapter 6 and within that, Recipe 6.

How to do it...

The following are the steps required to overlay a heat map on a map:

  1. First get over to the gbif.org website to download an XML file with the US data in it. The URL is given as http://es.mirror.gbif.org/ws/rest/density/list?originisocountrycode=US.
  2. Remove the extra markup in the XML file just so that it would be easier to parse it in ActionScript.
  3. Embed the XML file in the Main class as shown in the following code snippet:
    [Embed(source = "/AnimalsUS.xml", mimeType="application/octet-stream")]
        private var XmlData:Class;
  4. Parse the XML file and put the data in our holder class HeatMapData.
    var byteArray:ByteArray = (new XmlData()) as ByteArray;
    var xml:XML = XML(String(byteArray.readUTFBytes( byteArray.length )));
    var xmlList:XMLList = xml.children();
    
    var data:Vector.<HeatMapData> = new Vector.<HeatMapData>();
    
    var i:int;
    for (i = 0; i < xmlList.length(); i++) {
      data.push(new HeatMapData(xmlList[i].count, xmlList[i].minLongitude, xmlList[i].minLatitude));
    }
  5. Loop over every heatMapData instance to find its neighbors in all eight directions.
  6. Loop over the data another time to calculate the average value over its neighbors and to find the maximum of those averaged values.
  7. Create the map and the VectorLayer class to hold the heat map:
    _map = new Map();
    _map.size = new Size(800, 500);
    _map.center = new Location(-93.98,40.77, "EPSG:4326");
    _map.resolution = new Resolution(10000, "EPSG:900913");
    
    var bing:Bing = new Bing("Ar3-LKk-acyISMevsF2bqH70h21mzr_FN9AhHfi7pS26F5hMH1DmpI7PBK1VCLBk","Aerial");
    _map.addLayer(bing);
    
    var heatLayer:VectorLayer = new VectorLayer("HeatMap");
    _map.addLayer(heatLayer);
  8. Go over the data one last time to generate a polygon for each data point. Much of the work for this is done in the createPolygon function of the HeatMapData class.

How it works...

To make a heat map we need the data to be packaged in a particular way. We need one value to correspond to one area. For this recipe, the data from the Global Biodiversity Information Facility was aggregated over an area of one degree squared.

The first step is to get the data from the XML file into our holder class. Notice how using XML is a bit less straightforward than using JSON like in the Parsing data to use as region fill recipe.

Once we got that, we will need to loop over the data multiple times in order to calculate various values. We first need to average each value in relation to its neighbors. We do so, so that it creates more rounded regions on the heat map and also brings back values that would otherwise be too high to create a smoother range. To calculate this average we must do a double loop so that each data point can look at every other data point to check if it is one of its eight possible neighbors.

Once we got the neighbors, we loop over the data once more to create the average (we can't create the average while we are looking for neighbors, because a neighbor could use an already calculated average and that would skew the data) and find the maximum value of those averages. In this particular case we don't have to find a minimum as we know it is zero.

With the maximum found we can calculate the scaleRatio value:

var scaleRatio:Number = 495 / maximumCount;

495 here is our color range (255 for red and 240 for green).

Now we create the map so that we can add our polygons (they will be squares, much like pixels). We are ready for the last loop over the data. This is where we will create the PolygonFeature class and assign it a color depending on its averaged count value. If the averaged count value is equal to the maximum value, its polygon will be fully red, otherwise it will go from red to yellow to green. We put all the code to generate the polygon inside the HeatMapData class to keep the Main class cleaner.

The Coloring a map recipe has all the explanations on creating a PolygonFeature class and assigning it a color. Once we have all our polygons, we add them to the map. Note that since there are so many polygons on the map, it becomes a bit unresponsive when interacting with it, which is not really a problem if you want to use it as a static map.

There's more...

By using more precise data and a bigger color range we could make a better heat map.

Using more precise data

The XML file we used had data for buckets of the size of one degree squares. This made it so, that the resolution of our heat map wasn't so great. By using more precise data we could have a much smoother heat map. Everything starts from the data.

Starting from blue

Our color range went from green to yellow to red, but we could have started from blue instead and added even more depth to our visualization.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.76.175