The new online love of my life is NOAA, whose publicly available data files are a wonder. A couple weeks ago I discovered their weather forecasting web service, which can be used with Flash's WebService class to produce a Flash-based weather forecast for up to a week for any city in the US. The people at NOAA were very helpful in explaining some of the finer points of the forecast RSS file, and providing links to more information. Yesterday I found a whole new source of interesting data at NOAA's Geophysical Data Center. Among the data provided (for free) here is a complete database of global elevations.
What does this have to do with the BitmapData class? My first thought when I found this data was to try to use it to produce a sort of topographic map using traditional attachMovie methods to create a dot movieclip which I would attach repeatedly and color based on information in the data file. This quickly proved to be unworkable, as it took way too long to render the number of points required with vector graphics. Enter the BitmapData class, whose purpose is to allow the (relatively) quick rendering of bitmap (pixel-based) data in Flash. The results, including the amount of time taken for each step of the process (for 45,000 points) is shown above. A couple seconds to render a map for an area covering 20 degrees longitude and 10 degrees latitude is quite nice, I think.
Rendering bitmap data in a Flash movieclip is simple. Here's an outline of the BitmapData-related steps I used to make the sample above:
This is the code to do that:
import flash.display.BitmapData;
// .. set up variables and read file data ..
var topodata:BitmapData = new BitmapData(filedata.ncols, filedata.nrows);
for (var row=0; row < filedata.nrows; row++) {
for (var col=0; col < filedata.ncols; col++) {
cell = row*filedata.ncols+col;
for (var j=1; j<=colors.length; j++) {
// .. find the right color for this pixel ..
topodata.setPixel(col, row, cellcolor);
break;
}
}
}
this.createEmptyMovieClip("map1", 1);
map1._x = 15;
map1._y = 10;
map1.attachBitmap(topodata, 2, "auto", true);
In the sample above, I created two movieclips and did a separate attachBitmap (of the same bitmapdata instance) to each, specifying smoothing for the top one and not for the bottom one, so you can see the difference when they are expanded.
As is evident above, plotting elevations does not produce a true topographic map with contours or an accurate physical map (which would show actual land boundaries, shading of elevation changes, and an indication of the rainfall associated with an area by its color). But it does a pretty nice approximation, as can be seen by moving the slider at the bottom, which allows simultaneous viewing of a physical map of the same area (a piece of a National Geographic map which I scanned and skewed to get the latitude and longitude lines to match my rendering). And it brings out some interesting features by comparison, such as the fact that the area around the mouth of the Volga (appropriately named the Caspian Depression) is so low-lying that it is not distinguished from the water at all in my rendering, which makes me think the river must overflow a lot and which a bit of googling showed to in fact be the case). I played around with the color ranges for an hour or so, trying to get the best picture of actual landforms based on elevation and finally settled for using gradations of blue for everything at sea level and below, green starting with 50m, and yellow-going-to-red at 500m and above. This produces certain anomalies, such as the Crimean peninsula appearing to be an island instead of a peninsula, but it's so far the best combination of color ranges I've come up with to include an indication of lakes (often a bit higher than sea level) as well as oceans and seas. It does make obvious things like how deep the Black Sea is (especially compared to its neighbor, the Caspian). The color of each pixel was determined by finding its depth in an array of depth ranges I set up, and using the color range calculations described at the bottom of this page to get an intermediate value.
The data I used for the map was obtained by using NOAA's GOEDAS Grid Translator with the input shown below:

This produces a comma-delimited text file which can be downloaded and read in using the LoadVars object and its onData method to create an array of elevation points to plot. Notice that the GEODAS program produces an indication of the number of rows and columns, which you can also plug into your Flash movie.
To read the data from the text file created by GOEDAS, I used a loadVars instance with this onLoad function:
lv.onData = function(s:String) {
// create an array where each element is one line from the data file
// (covers all possible representations of a new line in the file)
pts = s.split("\r\n");
if (pts.length==1) pts = s.split("\r");
if (pts.length==1) pts = s.split("\n");
// put the 3rd comma-delimited value into the pts array
// overwriting its previous value
for (var i=0; i <pts.length; i++) {
var temp:Array = pts[i].split(',');
pts[i] = Number(temp[2]);
}
drawPoints();
}
If you need to save a reference to the latitude and longitude associated with each point, you can do so by saving the first and second items in the comma-delimited string as well. If you don't need those points at all, you can get a smaller file from GEODAS by selecting the ASCII raster format instead of XYZ.
A zip file of the complete fla and data file used to produce the maps above may be downloaded by subscription from the link above at right. A faster version of this, made by saving the data from GEODAS in a compiled swf, can be found in the next sample in this section.
last update: 4 Jun 2006
Discussed on this page:
representation of bitmap data in flash, bitmapdata class for quick rendering of pixel-based data, noaa, goedas, elevation data, topographic map, color range, parse comma-delimited (csv) file with onData
Files:
bitmaptopo.fla
topo data txt file
In bitmaptopo.zip, password required
Subscription:
A password may be obtained by subscription ($20 for one month)
An access password will be emailed to the address you specify within 24 hours of receipt of payment, and will remain active for 30 days thereafter. A list of all files currently available at the site may be viewed here.