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

Reply via email to