I've been a student of fractal geometry for many years. Benoit Mandelbrot is considered the "father" of modern fractals. When his book "The
Fractal geometry of Nature" was published in 1982, I bought a copy. This
is a coffee-table style book with a huge amount of information about the history
of fractals, mathematical formulae, and is loaded with stunning color pictures
of computer -generated fractals of all types. To this day, it remains the seminal
work on fractal geometry.
Fractals are realistic and useful models of many phenomena in the real world. Natural
fractals include the shapes of mountains, coastlines and river basins; the structures
of plants, blood vessels and lungs; the clustering of galaxies; and Brownian
motion. Fractals are found in human pursuits, such as music, painting, architecture,
and stock market prices.
In Silverlight 3, we have the addition of the WriteableBitmap class, which enables
the manipulation of the pixels in an image, as well as to create transforms that
can be used to create reflections and similar effects. Even with some complex
number math and many iterations involved, this class will render a bitmap of
say 480 X 360 pixels of the computed Mandelbrot Set in around 120 milliseconds,
making it a candidate for animation of small bitmaps in Silverlight.
To test this out, I took some C# Mandelbrot Set code and put it into an animation
timeline generated through the use of the DispatcherTimer. Each time the timer
Tick event fires, I increment the viewport dimensions by a small amount and regenerate
the corresponding view of the Mandelbrot Set. This results in an animation that
appears to the user that you are slowly zooming away from the original subset
view until after a minute or so you can see the entire Mandelbrot Set mathematical
domain.
This is Silverlight 3 Beta code, so I can't provide a live sample. But if you're
getting into Silverlight 3, you can download the working solution below and play
around with it.
Here is the class in its entirety:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace WriteableBitmap
{
public partial class MainPage : UserControl
{
private System.Windows.Threading.DispatcherTimer tmr = new DispatcherTimer();
private int _max = 30;
private int _escape = 20;
double rmin = -.75;
double rmax = -.46;
double imin = -.65;
double imax = -.50;
public MainPage()
{
InitializeComponent();
tmr.Interval
= TimeSpan.FromTicks(0);
tmr.Tick
+= new EventHandler(tmr_Tick);
tmr.Start();
}
void tmr_Tick(object sender, EventArgs e)
{
rmin
-= .002;
rmax
+= .002;
imin
-= .002;
imax
+= .002;
DrawMandelbrotSet(this.image1, rmin, rmax, imin, imax, 480,360);
}
private void DrawMandelbrotSet(Image image, double rmin, double rmax,
double imin, double imax, int width, int height)
{
// uncomment next line and 3 lines at bottom to see rendering time in output window
// DateTime start = DateTime.Now;
// Silverlight 2 - you can use Joe Stegman's WriteableBitmap class separately
System.Windows.Media.Imaging.WriteableBitmap
bitmap =
new System.Windows.Media.Imaging.WriteableBitmap(width, height, PixelFormats.Bgr32);
bitmap.Lock();
double dr = (rmax - rmin) / (width - 1);
double di = (imax - imin) / (height - 1);
for (int x = 0; x < width; x++)
{
double cr = rmin + (x * dr);
for (int y = 0; y < height; y++)
{
double ci = imin + (y * di);
double zr = cr;
double zi = ci;
int count = 0;
while (count < _max)
{
double zr2 = zr * zr;
double zi2 = zi * zi;
if (zr2 + zi2 > _escape)
{
bitmap[(y*width)
+ x] = (int) Math.Pow(count + 1, 5) % int.MaxValue;
break;
}
zi
= ci + (2.0 * zr * zi);
zr
= cr + zr2 - zi2;
count++;
}
if (count == _max)
bitmap[(y
* width) + x] = 0; // Black
}
}
bitmap.Invalidate();
bitmap.Unlock();
image1.Source
= bitmap;
// DateTime end = DateTime.Now;
// TimeSpan elapsed = end - start;
// System.Diagnostics.Debug.WriteLine( elapsed.TotalMilliseconds.ToString() );
}
}
}
Here's a small screen cap of the view when it first starts animating:

And here is the same image after it has been zooming out for 30 seconds or so:

If you want to play around with the speed and resolution, try changing the _max and
_escape values. By the way, this is a real memory hog, it may be leaky: don't
be surprised if you get out of memory errors from "playing too hard"!
You can download the Visual Studio 2008 Silverlight 3 Beta Solution here.