- Home
- Tutorials
- Flash
- Intermediate
- Creating a Mandelbrot-set
Creating a Mandelbrot-set

Roto - zoom
Milan Toth
Milan Toth is the Chief Flash Developer of Jasmin Media Group, he created one of the world's biggest flash media server system. He loves Eclipse and OS X, AS3 and JAVA, sci-fi and horror, metal and electronic.
For roto-zoom we need five continously changing variables : the interval borders and the angle. Create a new function called rotoZoom, which modifies these values periodically, based on Stage's enterframe event. Rotation happens in drawset, before requesting a new coordinate from getCycles. Let's see:
package
{
import flash.geom.Point;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
public class Mandelbrot extends Sprite
{
// display dimensions, set this as default size
private static var DWTH:Number = 200;
private static var DHTH:Number = 200;
// maximum function cycles
private static var CYCLES:Number = 30;
private var xmin:Number = -1;
private var xmax:Number = 1;
private var ymin:Number = -1;
private var ymax:Number = 1;
private var angle:Number = 0;
private var step:Number = 0.01;
// the set's bitmapdata
private var bitmapData:BitmapData;
public function Mandelbrot ( )
{
// creating new bitmap instance
var setBitmap:Bitmap = new Bitmap( );
// creating new bitmapdata
bitmapData = new BitmapData( DWTH , DHTH , false , 0x000000 );
// attaching bitmapdata to bitmap
setBitmap.bitmapData = bitmapData;
// attaching bitmap to display list
addChild( setBitmap );
// start trigger
addEventListener( Event.ENTER_FRAME , rotoZoom );
}
public function rotoZoom ( event:Event ):void
{
xmin += step;
xmax -= step;
ymin += step;
ymax -= step;
angle += step;
// start drawing
drawSet( xmin , xmax , ymin , ymax );
}
public function drawSet ( rmin:Number , // interval minimum on real axis
rmax:Number , // interval maximum on real axis
imin:Number , // interval minimum on imaginary axis
imax:Number ):void
{
// real axis stepping
var rStep:Number = ( rmax - rmin ) / DWTH;
// imaginary axis stepping
var iStep:Number = ( imax - imin ) / DHTH;
// actual real coordinate
var r:Number;
// actual imaginary coordinate
var i:Number;
// looping thorugh every display point
for ( var px:int = 0 ; px < DWTH ; px++ )
{
r = rmin + px * rStep;
for ( var py:int = 0 ; py < DHTH ; py++ )
{
i = imin + py * iStep;
// needed for polar length
var point:Point = new Point( r , i );
// calculating new angle
var alfa:Number = Math.atan2( i , r ) + angle;
// rotating point based on polar coordinate
point = Point.polar( point.length , alfa );
var color:uint;
var cycles:int = getCycles( point.x , point.y );
// if cycles == CYCLES, the function tends to infinity
if ( cycles == CYCLES ) color = 0x000000;
// in not, we generate a greenish colour with bitwise left shit
else color = cycles << 16 | ( cycles + 50 ) << 8 | cycles;
// putting pixel
bitmapData.setPixel( px , py , color );
}
}
}
// calculating function cycle number
public function getCycles ( r:Number , i:Number ):uint
{
var zr:Number = 0;
var zi:Number = 0;
var cr:Number = r;
var ci:Number = i;
// z's old values
var ozr:Number = 0;
var ozi:Number = 0;
// z's old square values
var zrsq:Number = 0;
var zisq:Number = 0;
for ( var a:int = 0 ; a < CYCLES ; a++ )
{
zi = ozr * ozi * 2 + ci;
zr = zrsq - zisq + cr;
zrsq = zr * zr;
zisq = zi * zi;
ozr = zr;
ozi = zi;
if ( ( zrsq + zisq ) > 4 ) break;
}
return a;
}
}
}
It is quite good now. But we should try to zoom to a central point, and we should move all local variables to global scope, because local variables in a loop - hell like this can eat plenty of memory and processor time.
My final version is:
package
{
import flash.geom.Point;
import flash.events.Event;
import flash.display.Sprite;
import flash.display.Bitmap;
import flash.display.BitmapData;
public class Mandelbrot extends Sprite
{
// display dimensions, set this as default size
public static var DWTH:Number = 150;
public static var DHTH:Number = 150;
// maximum function cycles
public static var CYCLES:Number = 20;
public var xmin:Number = -2;
public var xmax:Number = 1;
public var ymin:Number = -1;
public var ymax:Number = 1;
public var angle:Number = 0;
public var step:Number = Math.PI / 64;
public var xcenter:Number = 1;
public var ycenter:Number = 0;
// the set's bitmapdata
public var bitmapData:BitmapData;
// variables for function drawSet
public var rStep:Number;
public var iStep:Number;
public var r:Number;
public var i:Number;
public var tempPoint:Point;
public var alfaAngle:Number;
public var color:uint;
public var cycles:int;
// variables for function getCycles
public var zr:Number;
public var zi:Number;
public var cr:Number;
public var ci:Number;
public var ozr:Number;
public var ozi:Number;
public var zrsq:Number;
public var zisq:Number;
public function Mandelbrot ( )
{
// creating new bitmap instance
var setBitmap:Bitmap = new Bitmap( );
// creating new bitmapdata
bitmapData = new BitmapData( DWTH , DHTH , false , 0x000000 );
// attaching bitmapdata to bitmap
setBitmap.bitmapData = bitmapData;
// attaching bitmap to display list
addChild( setBitmap );
// start trigger
addEventListener( Event.ENTER_FRAME , rotoZoom );
}
public function rotoZoom ( event:Event ):void
{
xmin += ( xcenter - xmin ) / 64;
xmax += ( xcenter - xmax ) / 64;
ymin += ( ycenter - ymin ) / 64;
ymax += ( ycenter - ymax ) / 64;
angle += step;
// start drawing
drawSet( xmin , xmax , ymin , ymax );
}
public function drawSet ( rmin:Number , // interval minimum on real axis
rmax:Number , // interval maximum on real axis
imin:Number , // interval minimum on imaginary axis
imax:Number ):void
{
// real axis stepping
rStep = ( rmax - rmin ) / DWTH;
// imaginary axis stepping
iStep = ( imax - imin ) / DHTH;
// looping thorugh every display point
for ( var px:int = 0 ; px < DWTH ; px++ )
{
r = rmin + px * rStep;
for ( var py:int = 0 ; py < DHTH ; py++ )
{
i = imin + py * iStep;
// needed for polar length
tempPoint = new Point( r , i );
// calculating new angle
alfaAngle = Math.atan2( i , r ) + angle;
// rotating point based on polar coordinate
tempPoint = Point.polar( tempPoint.length , alfaAngle );
cycles = getCycles( tempPoint.x , tempPoint.y );
// if cycles == CYCLES, the function tends to infinity
if ( cycles == CYCLES ) color = 0x000000;
// in not, we generate a greenish colour with bitwise left shit
else color = cycles << 16 | ( cycles + 50 ) << 8 | cycles;
// putting pixel
bitmapData.setPixel( px , py , color );
}
}
}
// calculating function cycle number
public function getCycles ( argR:Number , argI:Number ):uint
{
zr = 0;
zi = 0;
cr = argR;
ci = argI;
ozr = 0;
ozi = 0;
zrsq = 0;
zisq = 0;
for ( var a:int = 0 ; a < CYCLES ; a++ )
{
zi = ozr * ozi * 2 + ci;
zr = zrsq - zisq + cr;
zrsq = zr * zr;
zisq = zi * zi;
ozr = zr;
ozi = zi;
if ( ( zrsq + zisq ) > 4 ) break;
}
return a;
}
}
}
Check it under attachments.
Spread The Word
Attachments
2 Responses to "Creating a Mandelbrot-set" 
|
said this on 25 Nov 2007 9:10:43 AM CST
It doesn't work - big
1037: |
|
said this on 27 Mar 2008 10:04:45 AM CST
"Packages cannot be
Then var this.addChild(man And it w |



Author/Admin)