// this timer happens every millisecond. This is my workaround to // always get control back to the map-generating routine. private void timer1_Tick(object sender, EventArgs e) { if (!ImageComplete) { // record when you entered the loop DateTime TimeOfEntry = DateTime.Now; int ElapsedTimeMs; // work on the map do { // start the particle out at the current <x, y> coordinates Particles[0].PositionX = ImageToParticleSpace(x); Particles[0].PositionY = ImageToParticleSpace(y); // set the moving particle's initial velocity. Particles[0].VelocityX = RotationVelocityAmplitude * Math.Cos(RotationVelocityInitialPhase + RotationAngle * ImageNumber / Math.Max(1, Convert.ToDouble(RotationSamplePoints - 1))); Particles[0].VelocityY = RotationVelocityAmplitude * Math.Sin(RotationVelocityInitialPhase + RotationAngle * ImageNumber / Math.Max(1, Convert.ToDouble(RotationSamplePoints - 1))); // run the simulation until the moving particle hits one of the stationary particles // have a timeout to prevent the programming from going in an endless loop bool collision = false; int iterations = 0; while ((!collision) && (iterations < IterationsMax)) { // check to see if the moving particle has collided with any of the others foreach (Particle p in Particles.GetRange(1, Particles.Count - 1)) { collision = Particle.CollisionCheck(Particles[0], p); // if the particle collided, set the pixel to the appropriate color. if (collision) { //Image.SetPixel(x, y, p.Color); Image.SetPixel(x, y, ImageDefaultColor); break; } } // run the simulation for a little while Particle.UpdateSingle(Particles[0], Particles.GetRange(1, Particles.Count - 1), IterationTimeStep); iterations++; } // if our test particle did not collide with ANY target particles, if (!collision) { // calculate the blended color of all particles double ColorProA = 1; double ColorSumR = 0; double ColorSumG = 0; double ColorSumB = 0; foreach (Particle p in Particles.GetRange(1, Particles.Count - 1)) { double dist_squared = (Particles[0].PositionX - p.PositionX) * (Particles[0].PositionX - p.PositionX) + (Particles[0].PositionY - p.PositionY) * (Particles[0].PositionY - p.PositionY); double coloration_constant = 0.0001; ColorProA *= (0xff - p.Color.A) / 0xff; ColorSumR += Math.Pow(p.Color.R, 2) * (p.Color.A / 0xff) * coloration_constant / dist_squared; ColorSumG += Math.Pow(p.Color.G, 2) * (p.Color.A / 0xff) * coloration_constant / dist_squared; ColorSumB += Math.Pow(p.Color.B, 2) * (p.Color.A / 0xff) * coloration_constant / dist_squared; } ColorProA = (1 - ColorProA) * 0xff; double ColorMax; ColorMax = Math.Max(ColorSumR, ColorSumG); ColorMax = Math.Max(ColorSumB, ColorMax); // limit the maximum color intensity if (ColorMax > 0xff) { ColorSumR *= 0xff / ColorMax; ColorSumG *= 0xff / ColorMax; ColorSumB *= 0xff / ColorMax; } // convert the color components to integers int intR = Convert.ToInt32(ColorSumR); int intG = Convert.ToInt32(ColorSumG); int intB = Convert.ToInt32(ColorSumB); Image.SetPixel(x, y, Color.FromArgb(0xff, intR, intG, intB)); } // increment x and y x++; // if you have gotten to the right edge of the bitmap, if (x >= ImageWidth) { x = 0; y++; } // if you have completed the image, close it. if (y >= ImageHeight) { // make a directory if it doesn't exist Directory.CreateDirectory(OutputFileDirectory); // save the image with date Image.Save(OutputFileDirectory + OutputFileName + "_" + (DateTime.Now).ToString("yyyy-MM-ddTHH.mm.ss") + "_" + ImageNumber.ToString() + ".png", System.Drawing.Imaging.ImageFormat.Png); y = 0; //try //{ // SoundPlayer player = new SoundPlayer("gotmail.wav"); // player.Play(); //} //catch //{ // // oh well. //} ImageNumber++; if (ImageNumber >= RotationSamplePoints) { ImageComplete = true; TimeRenderStop = DateTime.Now; } } ElapsedTimeMs = (int)(DateTime.Now - TimeOfEntry).TotalMilliseconds; } // keep working on the map until you need to refresh the screen again while ((ElapsedTimeMs < this.ScreenRefreshPeriodMs) && !ImageComplete); Invalidate(); } }