Mandelbrot Fractal Generator
Mandelbrot Fractal Generator
package ui.mandelbrot;
/////////////////////////////////////////////////////////////////////////////////////////
// (c) Copyright 2009, Daniel P. Darnell
// This software is provided AS IS.
// Permission to use, copy and modify this software for any purpose and
// without fee is hereby granted provided that I am given credit for
// creating this original work.
//
// I DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL I
// BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
// DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
// IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
// OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//////////////////////////////////////////////////////////////////////////////////////////
import com.ibm.egl.rui.widgets.*;
import egl.javascript.Job;
import draw2d.*;
handler Main type RUIhandler{initialUI =[ui], onConstructionFunction=initialization}
ui Div { backgroundColor="white", children =[buttonBox, d] };
buttonBox Box { backgroundColor="gray", height = 30, width = 286, columns = 2,
children =[startButton, messageLabel] };
startButton Button { marginTop = 2, text = "New", onClick ::= clickStartButton };
messageLabel TextField { width = 200, marginLeft = 10, marginTop = 5,
borderWidth = 0, fontSize = 12, fontWeight = "bold", backgroundColor = "gray",
text = "(May take several minutes)" };
d Draw2D { borderStyle="solid", borderColor="lightgrey", borderWidth=3,
zIndex = 1, width = 280, height = 320, onStartDrag = start, onDrag = drag,
onDropOnTarget = drop };
private const vwidth int = 280;
private const vheight int = 320;
private const voffset int = 30;
// Mandlebrot formula variables
private left, right, top, bottom float;
private const iters int = 128; // Increase this for greater definition.
function initialization()
Document.body.appendChild(showDrag);
end
function clickStartButton(e Event in)
// Default formula parameters
left = -2.25;
right = 1.75;
top = 1.5;
bottom = -2.5;
startButton.setDisabled(true);
buildMandelbrot();
end
/* -------------------------------------------------------------------------------
* Drag and drop
* ------------------------------------------------------------------------------- */
showDragX, showDragY int;
showDrag HTML { position = "absolute", visibility = "hidden",
zIndex = 999, background = "lightgrey", opacity = 0.5, x = 0, y = 0 };
private function start(w Widget in, startX int in, startY int in) returns(boolean)
showDragX = startX;
showDragY = startY;
showDrag{visibility = "visible", x = startX, y = startY};
return(true);
end
private function drag(w Widget in, dropw Widget in, dragX int in, dragY int in)
showDrag.width = dragX - showDragX;
showDrag.height = dragY - showDragY;
end
private function drop(w Widget in, dropw Widget in, dragX int in, dragY int in)
showDrag.visibility = "hidden";
if(dragX > showDragX and dragY > showDragY)
xi float =(right - left) / vwidth;
yi float =(bottom - top) / vheight;
right = left +(dragX * xi);
left = left +(showDragX * xi);
bottom = top +((dragY - voffset) * yi);
top = top +((showDragY - voffset) * yi);
startButton.setDisabled(true);
buildMandelbrot();
end
end
/* -------------------------------------------------------------------------------
* Build Mandelbrot: Set intial variables and then fire up scheduled job
* to build image one vertical line at a time.
* ------------------------------------------------------------------------------- */
xi, yi float;
xx1, yy1 float;
x0, y0 float;
x1, y1 float;
x2, y2 float;
xz, yz, zz float;
c float;
j, k, l, zcolor, rcolor, gcolor, bcolor int;
buildMandelbrotJob Job { runFunction = buildMandelbrotIteration };
private function buildMandelbrot()
d.clear();
d.lineWidth = 1;
// Calculate increment
xi =(right - left) / vwidth; // Width
yi =(bottom - top) / vheight; // Height
// Set starting point back by increment
xx1 = left - xi;
yy1 = top - yi;
j = 1;
buildMandelbrotJob.repeat(1);
end
/* --------------------------------------------------------------------------------
* Build and draw one vertical line of the image.
*
* Use job scheduling functionality to iterate so that other things can
* happen too (like display of the progress icon).
* ------------------------------------------------------------------------------- */
private function buildMandelbrotIteration()
if(j < vwidth)
messageLabel.text = "("+(j*100/vwidth)as int+"% Complete)";
xx1 = xx1 + xi;
yy1 = top - yi;
// Loop for height
k = 1;
lastk int = 1;
lastColor String = "";
while(k < vheight)
yy1 = yy1 + yi;
x1 = xx1;
y1 = yy1;
x0 = xx1;
y0 = yy1;
zcolor = 100;
// Perform iterations
l = 1;
while(l < iters)
xz = x1 * x1;
yz = y1 * y1;
zz = xz + yz;
c = MathLib.sqrt(zz);
if(c > 2)
l = iters;
else
zcolor = zcolor + 5000;
x2 = xz +(yz * -1);
y2 =(x1 * y1) * 2;
// Set up for next iteration
x1 = x2 + x0;
y1 = y2 + y0;
end
l += 1;
end
bcolor = zcolor / 65536;
gcolor =(zcolor -(65536 * bcolor)) / 256;
rcolor = zcolor -(65536 * bcolor + 256 * gcolor);
color string = "RGB(" + rcolor + "," + gcolor + "," + bcolor + ")";
if (color != lastColor)
d.color = lastColor;
lastColor = color;
d.drawLine(j, lastK, j, k);
lastK = k;
end
k += 1;
if (k == vheight)
d.color = color;
d.drawLine(j, lastK, j, k+1);
end
end
j += 1;
else
buildMandelbrotJob.cancel();
startButton.setDisabled(false);
messageLabel.text = "Click and drag to zoom in";
end
end
end