Thursday, August 6, 2009

GradientControl: Making Thematic Mapping Easier, One Gradient at a Time

I'm Simon, and I work as a Site Reliability Engineer at Google. One of the benefits of working here is that I get to choose interesting 20% projects to work on. Recently, I worked with Project Vulcan at Purdue University to create a map that visualized greenhouse gas emissions. I chose to visualize that data by coloring countries depending on the values associated with them. This technique is called chloropleths, or thematic maps.

Google APIs made most of the map creation tasks quite easy, but fine-tuning thematic maps still required a lot of work. I wanted to load a dataset and make a single library call to calculate the color gradients, but at the same time I wanted to be able to express complex rules, like "draw all negative values with a red-yellow gradient, then draw the bottom 50% of the positive values with a yellow-orange gradient, and the rest with a orange-red gradient".

Developer Bjørn Sandvik created the great Thematic Mapping library using the Google Earth API and Google Visualization APIs in JavaScript, but while it supports a large number of thematic map types, it can only draw a gradient between two colors. So, to satisfy my needs for multi-colored gradients and more control, I wrote a library for the Maps API for Flash called GradientControl.

Here's a simple example of using GradientControl, with just a three-color gradient, from green to yellow to red:

You can drag the slider under the map to change the position of the middle color and immediately see the results. Click on a country to see the value associated with it. You can also try out a larger version of this example, with two middle colors and three sliders.

The color gradient configuration can be either constructed with Actionscript function calls, or moved into an external XML file. The complex example that I wanted to write would look like this:

<gradientRuleList> 
  <gradientRule> 
    <gradient> 
      <minColor>0x0000ff</maxColor> 
      <maxValue>0</minValue> 
    </gradient> 
   </gradientRule> 
   <gradientRule> 
     <gradientRuleList> 
       <gradientRule> 
         <gradient> 
           <minColor>0xff0000</minColor>     
           <maxColor>0xff8000</maxColor> 
           <maxPercent>50</maxPercent> 
         </gradient> 
       </gradientRule> 
       <gradientRule> 
         <gradient> 
           <minColor>0xffff00</minColor>
           <maxColor>0x00ff00</maxColor> 
         </gradient> 
      </gradientRule> 
    </gradientRuleList> 
  </gradientRule> 
 </gradientRuleList>

This is verbose, of course, but still much easier than writing custom code.

To get started using the library, check out the source, read the documentation, and post in the forum if you're having issues (or simply to show off what you've made). If you're interested in improving this control or making it work better with existing standards or APIs, please join the utility library forum. Enjoy!