Home  >  Development  >  blogs

Visualizing Geographic Data Sets

AddThis Social Bookmark Button
Continuing on with my recent trend of posts related to data visualization and web based mapping, this time I've decided to have some fun and combine the two with the visualization of geographic data.

Before I get started, it is important to note that GIS on the web has become a commodity. There are numerous APIs that can be used to enhance your RIAs with mapping and/or GIS related information. Here are a few web based mapping APIs, just to get started:

Google MAPs API (flex/flash/javascript)
Yahoo Maps API (flex/flash/javascript)
ESRI Arcwebservices (flex/javascript)
MapQuest (flex/flash/javascript)
Modest Maps (flex/flash)
Pushpin (javascript)

In this example, I decided to use the recently released Google Maps API for Flash/Flex. I actually didn't set out on this topic; I started out by google-ing the term "data set", just to see what comes up. I knew there had to be some public data sets that I could tackle for Flex-based data visualization. I came across a library of statistical data sets (from 1996) hosted by Carnegie Melon University.

The "US Temperatures" data set grabbed my attention because it seemed like a perfect data set that can be used to show how to visualize geographically related data. From the dataset:

The data gives the normal average January minimum temperature in degrees Fahrenheit with the latitude and longitude of 56 U.S. cities. (For each year from 1931 to 1960, the daily minimum temperatures in January were added together and divided by 31. Then, the averages for each year were averaged over the 30 years.)

My first thought was that this would be great to show a point on the map for each city, with the color varying to show the average value for that geographic location. Here is what I came up with... This example shows the average temperature per geographic location, and shows the data trend hot to cold (red to blue): I apologize to those that are color blind, since they won't be able to see the nuances of this example.



The map is still completely interactive. You can zoom in/out with the mouse wheel, click and drag, or you can click on a row in the datagrid to center on that lat/lon. One note though, I've noticed that not all of the lat/lon coordinates in the data set exactly match the actual geographic center of the locations.

Now, here's how it all works... The first thing that I had to do was transform the tabular data into a format that can be easily consumed by a flex application. I used simple string replacement to replace tabs (\t) with a colon, and newline (\n) with a semicolon, and then used basic string parsing to transform that into xml that I could easily use in the example.

private function onCreationComplete() : void
{
 	var output : XML = new XML( "<dataset />" );
 	var sourceData : String = "Mobile, AL:44:31.2:88.5;Montgomery, AL:38:32.9:86.8;Phoenix, AZ:35:33.6:112.5;Little Rock, AR:31:35.4:92.8;Los Angeles, CA:47:34.3:118.7;San Francisco, CA:42:38.4:123.0;Denver, CO:15:40.7:105.3;New Haven, CT:22:41.7:73.4;Wilmington, DE:26:40.5:76.3;Washington, DC:30:39.7:77.5;Jacksonville, FL:45:31.0:82.3;Key West, FL:65:25.0:82.0;Miami, FL:58:26.3:80.7;Atlanta, GA:37:33.9:85.0;Boise, ID:22:43.7:117.1;Chicago, IL:19:42.3:88.0;Indianapolis, IN:21:39.8:86.9;Des Moines, IA:11:41.8:93.6;Wichita, KS:22:38.1:97.6;Louisville, KY:27:39.0:86.5;New Orleans, LA:45:30.8:90.2;Portland, ME:12:44.2:70.5;Baltimore, MD:25:39.7:77.3;Boston, MA:23:42.7:71.4;Detroit, MI:21:43.1:83.9;Minneapolis, MN:2:45.9:93.9;St. Louis, MO:24:39.3:90.5;Helena, MT:8:47.1:112.4;Omaha, NE:13:41.9:96.1;Concord, NH:11:43.5:71.9;Atlantic City, NJ:27:39.8:75.3;Albuquerque, NM:24:35.1:106.7;Albany, NY:14:42.6:73.7;New York, NY:27:40.8:74.6;Charlotte, NC:34:35.9:81.5;Raleigh, NC:31:36.4:78.9;Bismarck, ND:0:47.1:101.0;Cincinnati, OH:26:39.2:85.0;Cleveland, OH:21:42.3:82.5;Oklahoma City, OK:28:35.9:97.5;Portland, OR:33:45.6:123.2;Harrisburg, PA:24:40.9:77.8;Philadelphia, PA:24:40.9:75.5;Charleston, SC:38:33.3:80.8;Nashville, TN:31:36.7:87.6;Amarillo, TX:24:35.6:101.9;Galveston, TX:49:29.4:95.5;Houston, TX:44:30.1:95.9;Salt Lake City, UT:18:41.1:112.3;Burlington, VT:7:45.0:73.9;Norfolk, VA:32:37.0:76.6;Seattle, WA:33:48.1:122.5;Spokane, WA:19:48.1:117.9;Madison, WI:9:43.4:90.2;Milwaukee, WI:13:43.3:88.1;Cheyenne, WY:14:41.2:104.9";
 	var rows : Array = sourceData.split( ";" );
 	for each ( var row : String in rows )
 	{
  		var data : XML = new XML( "<data />" ); 
  		var i : int = 0;
  		var columns : Array = row.split( ":" );
  		for each ( var column : String in columns )
  		{
   			switch ( i )
   			{
    				case 0: 
    					data.@location = column;
    					break;
    				case 1: 
    					data.@janTemp = column;
    					break;
    				case 2: 
    					data.@lat = column;
    					break;
    				case 3: 
    					data.@lon = column;
    					break;
    			}
   			i ++;
   		}
  		output.appendChild( data );
  	}
 	outputText.text = output.toXMLString();
}

And here is how it turned out...

Next, I setup a flex project to display this in a datagrid, and to display the data on a map. I used the same technique as my previous post on the Google Maps API to display the map within a Flex application.

The next step was to calculate the appropriate colors for the markers on the map, and go ahead and add the markers to the map. I used the color blue (0000FF) to denote the coldest data point, and the color red (FF0000) to denote the warmest data point. I adapted a color-tween technique from Darron Schall to calculate the incremental color values from the low to high value.

public function getTempColor( temp : Number ) : int
{
 	var percentage : Number = (temp / maxTemp);
 	return ( ( maxColorObj.r - percentage * delta.r ) << 16 )
            + ((maxColorObj.g - percentage * delta.g ) << 8 )
            + ( maxColorObj.b - percentage * delta.b );
}

Then, the map markers were added based on the calculated color and the lat/lon coordinates:
public function getTempColor( temp : Number )for each ( var data : XML in dataSet.data )
{
 	var latlng:LatLng = new LatLng( parseFloat( data.@lat ), -parseFloat( data.@lon ) );
 	var markerOptions : MarkerOptions = new MarkerOptions({
          strokeStyle: new StrokeStyle({color: 0x000000}),
          fillStyle: new FillStyle({color: getTempColor( parseFloat( data.@janTemp.toString() ) ), alpha: 0.8}),
          radius: 12,
          hasShadow: true
        })
 	markerOptions.tooltip = data.@location.toString() + ":    " + data.@janTemp.toString() + " F";
 	var marker : Marker = new Marker( latlng, markerOptions );
 	map.addOverlay( marker );
}


Full source code is available at:
http://www.tricedesigns.com/portfolio/googletemps/srcview/

___________________________________
Andrew Trice
Principal Architect
Cynergy Systems
http://www.cynergysystems.com

Comments

2 Comments

Great example, hopefully I can incorporate some to my site. Thanks!

Gary T said:

This is really cool! One question for you, say you wanted the markers to show up one after another rather than all at once, how would you add a timer to the source code?

Leave a comment


Type the characters you see in the picture above.

Poll: ECMAScript Reaction

The ECMA organization recently decided to stop work on ECMAScript 4 and begin a new version, tentatively described as ES "Harmony." How would you like to see this affect the evolution of ActionScript?

Vote | View Poll Results | Read Related Blog Entry

Tag Cloud

Related Books

Development Series

Get an overview of the tools and technologies that work together to allow developers to build Rich Internet Applications (RIAs) quickly and easily.

Anatomy of an Enterprise Flex RIA

Archives


 
 


Or, visit our complete archive.  

About This Site

Welcome to the premiere community site for all things RIA sponsored by O'Reilly Media and Adobe Systems Incorporated.

About Us
Meet the Experts
Meet Our Contributors
Send Us Feedback