So I'm begging for some help on a little project I'm working on. In
return for help I promise to name my next child after you ; )
Seriously, what i'm trying to do is build a Geochron in Flash. I've
ported over an open-source Java applet to do the job, but it's extremely
slow -- giving me the "A script is running repetedly and is making your
processor cry" message. If you have the patience to let it finish, it
does work (with a bug, that should be easily addressed, as it's
exactally 12 hours out of phase).
Anyway, I'm begging for some help making this run better -- if my
current method of doing this can even be improved. I'm not even going to
pretend I understand all the math in this code, but I do get the general
idea. Mostly I want to know if I could be handling the bitmap
manipulation better (first time trying), or if it's the calculation of
every pixel's lat/lon and amount of sunlight that's bringing things to a
crawl.
If anyone has a better idea of how to do this or there's already an
existing implementation somewhere, please throw me a bone. I'm throwing
the AS below, but can upload the fla and as file if someone wants to help.
Jher
class below:
import flash.display.BitmapData ;
class Geochron extends MovieClip
{
private static var DtoR:Number = Math.PI/180.;
private static var RtoD:Number = 180./Math.PI;
private static var dayAltMin:Number = 0.; // Minimum solar
altitude for daytime
private static var nightAltMax:Number = -9.; // Maximum solar
altitude for nighttime
private var dayImage:BitmapData ;
private var nightImage:BitmapData ;
private var blendedImage:BitmapData;
private var destination_mc:MovieClip;
private var n_x:Number;
private var n_y:Number;
private var timerID:Number
public function Geochron()
{
}
public function onLoad():Void
{
this.dayImage = BitmapData.loadBitmap("lightImage") ;
this.nightImage = BitmapData.loadBitmap("darkImage") ;
this.n_x = dayImage.width;
this.n_y = dayImage.height;
// Create the empty blendedImage
this.blendedImage = new BitmapData(dayImage.width,
dayImage.height, false, 0x000000) ;
// Create Destination MC for the blended image
this.destination_mc =
this.createEmptyMovieClip("destination_mc", this.getNextHighestDepth()) ;
// create a timer id for the interval.
this.timerID = setInterval(this, "setBlendedImage", 50000);
// call setBlended Image function as it won't call itself the
first time.
setBlendedImage();
}
function setBlendedImage ():Void
{
// Get a calendar for the current GMT
var calendar:Date = new Date()
// Calculate the Greenwich Sidereal Time
var GST:Number = getGreenwichSiderealTime(calendar);
// Calculate the solar right ascension and declination
var alpha:Number = getSolarRightAscension(calendar);
var delta:Number = getSolarDeclination(calendar);
// Loop over the y-pixels of the night/day images
var i_x:Number;
var i_y:Number;
for(i_x = 0; i_x < this.n_x; i_x++)
{
// Calculate the longitude
var longitude:Number = 180. - (i_x+0.5)/this.n_x*360.;
// Calculate the solar hour angle
var HA:Number = GST*360./24. - longitude - alpha;
for(i_y = 0; i_y < this.n_y; i_y++)
{
// Calculate the latitude
var latitude:Number = 90. - (i_y+0.5)/this.n_y*180.;
// Calculate the altitude of the sun
var alt:Number = getAltitude(HA, delta, latitude,
longitude);
// Work out the interpolation factor for drawing the pixel
var intFactor:Number;
if(alt > dayAltMin) {
intFactor = 1.;
}
else if(alt < nightAltMax) {
intFactor = 0.;
}
else {
intFactor = (alt - nightAltMax)/(dayAltMin -
nightAltMax);
}
// Get the RGB pixels of the day and night images
var dayRGB:Number = this.dayImage.getPixel(i_x, i_y);
var nightRGB:Number = this.nightImage.getPixel(i_x, i_y);
var dayR:Number = dayRGB >>> 16 & 0xFF;
var dayG:Number = dayRGB >>> 8 & 0xFF;
var dayB:Number = dayRGB & 0xFF;
var nightR:Number = nightRGB >>> 16 & 0xFF;
var nightG:Number = nightRGB >>> 8 & 0xFF;
var nightB:Number = nightRGB & 0xFF;
// Calculate the interpolated value of the blended pixel
var blendedRGB:Number = Math.floor(dayR*intFactor +
nightR*(1.-intFactor)) << 16 |
Math.floor(dayG*intFactor + nightG*(1.-intFactor))
<< 8 |
Math.floor(dayB*intFactor + nightB*(1.-intFactor));
this.blendedImage.setPixel(i_x, i_y, blendedRGB);
trace("x" + i_x + " y " + i_y) ;
}
}
destination_mc.removeMovieClip() ;
destination_mc = this.createEmptyMovieClip("destination_mc",
this.getNextHighestDepth()) ;
destination_mc.attachBitmap(this.blendedImage,
destination_mc.getNextHighestDepth()) ;
}
private function getDaysSinceJ2000(calendar:Date):Number {
// Calculate the number of days from the epoch J2000.0
// the specified date
var year:Number = calendar.getUTCFullYear();
var month:Number = calendar.getUTCMonth()+1;
var day:Number = calendar.getUTCDate();
var D0:Number = 367*year - 7*(year+(month+9)/12)/4 + 275*month/9
+ day - 730531.5;
var D:Number = D0 + getGreenwichMeanTime(calendar)/24.;
return D;
}
private function getGreenwichMeanTime(calendar:Date):Number
{
// Get the Greenwich Mean Time, in hours
var hour:Number = calendar.getUTCHours();
var minute:Number = calendar.getUTCMinutes();
var second:Number = calendar.getUTCSeconds();
var GMT:Number = hour + minute/60. + second/3600.;
return GMT;
}
private function getGreenwichSiderealTime(calendar:Date):Number
{
// Get the number of days since J2000.0
var D:Number = getDaysSinceJ2000(calendar);
// Calculate the GST
var T:Number = D/36525.;
var GST:Number = (280.46061837 + 360.98564736629*D +
0.000388*T*T)*24./360.;
// Phase it to within 24 hours
while(GST < 0.) { GST += 24.; }
while(GST >= 24.) { GST -= 24.; }
return GST;
}
private function getSolarRightAscension(calendar:Date):Number
{
// Calculate the number of days from the epoch J2000.0
var D:Number = getDaysSinceJ2000(calendar);
// Convert this into centuries
var T:Number = D/36525.;
// Calculate the mean longitude and anomaly
var L:Number = 279.697 + 36000.769*T;
var M:Number = 358.476 + 35999.050*T;
// Calculate the true longitude
var lambda:Number = L + (1.919 - 0.005*T)*Math.sin(M*DtoR) +
0.020*Math.sin(2*M*DtoR);
// Calculate the obliquity
var epsilon:Number = 23.452 - 0.013*T;
// Calculate the right ascension, in degrees
var alpha:Number =
Math.atan2(Math.sin(lambda*DtoR)*Math.cos(epsilon*DtoR),Math.cos(lambda*DtoR))
* RtoD;
return alpha;
}
private function getSolarDeclination(calendar:Date)
{
// Calculate the number of days from the epoch J2000.0
var D:Number = getDaysSinceJ2000(calendar) +
getGreenwichMeanTime(calendar)/24.;
// Convert this into centuries
var T:Number = D/36525.;
// Calculate the obliquity
var epsilon:Number = 23.452 - 0.013*T;
// Calculate the declination, in degrees
var delta:Number =
Math.asin(Math.sin(getSolarRightAscension(calendar)*DtoR)*Math.sin(epsilon*DtoR))
* RtoD;
return delta;
}
private function getAltitude(HA:Number, delta:Number,
latitude:Number, longitude:Number):Number
{
// Calculate the altitude, in degrees
var alt = Math.asin(Math.sin(latitude*DtoR)*Math.sin(delta*DtoR)
+ Math.cos(latitude*DtoR)*Math.cos(delta*DtoR)*Math.cos(HA*DtoR))*RtoD;
return alt;
}
}
_______________________________________________
Flashcoders mailing list
[email protected]
http://chattyfig.figleaf.com/mailman/listinfo/flashcoders