On the previous page, I posted an example of using Flash to read publicly available global elevation data and use the BitmapData class to display an elevation map. Data is returned from NOAA's grid application as a comma-delimited text file, which I used LoadVars.onData method to read and parse in Flash. But because the data being returned will not change, it would make more sense to read it once and put it into a format that would be easier and faster to parse in Flash.
Parsing strings of text, whether done via LoadVars or reading an XML file, is always slower than pulling the data directly from, say, a database, especially if that database is accessed via Flash Remoting, which returns data in binary object form rather than as strings of text. But an even faster way to access it would be to put it into a native structure in Flash so that no parsing is required at all. The tradeoff of course is that more up-front work needs to be done to parse and save the data (some of it manual paste and compile in this case), but you can see by comparing the access time for the sample above with the original sample that the access time becomes much improved.
This sample uses three different fla's:
The first fla is the one which reads and parses data. It has a big TextArea component on stage that the output, in the form of compilable actionscript, will be dumped into. As in the previous example, onData is used to parse the data, but instead of calling a function drawPoints to display the map, it calls displayPoints to create a string s that contains two variable declaration/assignments and a populated array, out to the TextArea component named results. This is that function:
// create an array to use with the BitmapData class and write it to results
function displayPoints() {
var cell:Number;
var proportion:Number;
var s:String;
s = "var nrows:Number = "+filedata.nrows+";\nvar ncols:Number = "+filedata.ncols+";\nvar colorpts:Array = [";
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++) {
if (pts[cell] >= colors[j-1].ht && pts[cell] <= colors[j].ht) {
// set color proportionally
proportion = (pts[cell] - colors[j-1].ht) / (colors[j].ht - colors[j-1].ht);
s += calculateColor(colors[j-1].clr, colors[j].clr, proportion) + ", ";
break;
}
}
}
}
results.text = s.slice(0, s.length-2) + "];";
}
I ran that fla from the IDE and right-clicked the textarea in the output window, choosing Select All and then Copy, and then opened a new Flash document, clicked in frame 1, and pasted the contents into the actions panel. Here's a screenshot:
With the content pasted in, I saved that fla with a name indicating which part of the map it represented (North 50-40 by East 30-50, with samples every 4 minutes of latitutde/longitude, as returned from the NOAA program). Thus n5040_e3050_4min.fla. You could create similar fla's for every quadrant of interest and have their published swfs all available for use by the display program. The last step was to publish this fla to a swf of the same name.
The final fla, the one that will use and display the saved elevation data, is bitmap_fromswf.fla. In this movie, I created an empty movieclip called dataclip to hold the data from my external swf, n5040_e3050_4min.swf using MovieClipLoader:
var dataLoader:MovieClipLoader;
...
function init() {
dataLoader = new MovieClipLoader();
dataLoader.addListener(this);
// movieclip to hold data
this.createEmptyMovieClip("dataclip", 10);
...
// movieclip to hold bitmap
this.createEmptyMovieClip("map1", 1);
...
dataLoader.loadClip("n5040_e3050_4min.swf", dataclip);
}
Then I use the data in dataclip to supply information to the function drawPoints that actually draws the bitmap (onLoadInit is called when the data swf has been completely read in):
function onLoadInit() {
drawPoints(dataclip.ncols, dataclip.nrows, dataclip.colorpts);
}
// use the BitmapData class to create a bitmap of the topo map based on values in $pts
function drawPoints($ncols:Number, $nrows:Number, $pts:Number):Void {
var cell:Number;
var topodata:BitmapData = new BitmapData($ncols, $nrows);
// put topo above renderings
realtopo.swapDepths(3);
for (var row=0; row < $nrows; row++) {
for (var col=0; col < $ncols; col++) {
cell = row*$ncols+col;
topodata.setPixel(col, row, $pts[cell]);
}
}
map1.attachBitmap(topodata, 2, "auto", true);
}
The results are shown above. I've saved all three fla's and the data swf in a zip file which may be downloaded by subscription from the link above at right.
last update: 28 Oct 2006
Discussed on this page:
Using a SWF as a data holder for elevation data as source for a map drawn with bitmapdata class
Files:
bitmap_makearray.fla
n5040_e3050_4min.fla + swf
bitmap_fromswf.fla
In bitmaptopo.zip, password required
Subscription:
A password may be obtained by subscription
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.