Craig Hales got me turned on to creating Mandelbrot set images and video sequences (see https://community.jmp.com/t5/Uncharted/Mandelbrot-shallow-tour/ba-p/53295 for where I got my start). It has been an interesting learning experience, not only about the intracacies of fractal sets, but also about JSL programming, video editing, and creating content for YouTube.
I recently encountered some videos about the Mandelbrot power set (sometimes also referred to as the "Multibrot Set" (https://en.wikipedia.org/wiki/Multibrot_set)). I won't go into all the details of the Mandelbrot powerfunction, but the way you use it is as follows:
- Let f_c(z) = z^d + c (where z is the complex number z=x + i y, c=xc + i yc).
- For a given value of c, iterate as follows
- let z_0 = 0
- Let f_c(z_i) = (z_(i-1))^d + c
- repeat until either
- the "bailout" number of iterations have been met (i.e. i>maximum iterations specified) OR
- ||z|| = (x^2 + y^2) > (stopping radius)^2 (where stopping radius is usually equal to 2, but could be smaller)
- record the value i as the number of iterations (or the depth) of the point c
While there is a JSL function Mandelbrot() that will help with generating mandelbrot set images, to do a multibrot set, I needed to write my own JSL function.
f_mandelbrotpowercount = Function( {x, y, d = 2, radius=2, max_n = 100},
{zx, zy, n_iter = 0, r = 0, theta = 0},
if ( x ^ 2 + y ^ 2 <4,
While( (r < radius) & (n_iter < max_n),
zx = r ^ d * Cos( d * theta ) + x;
zy = r ^ d * Sin( d * theta ) + y;
r = Sqrt( zx ^ 2 + zy ^ 2 );
theta = ArcCosine( zx / r ) * ((zy > 0) * 2 - 1);
n_iter++;
);
);
n_iter;
);If you know a little bit about complex numbers and multiplication of complex numbers, you can see that I'm utilizing the identiy that
z=x + i y = R e^(i Theta)
where
R=sqrt(x^2 + y^2), Theta=ArcCosine(x/R) (Theta is constrained to be between (-Pi,Pi)
The syntax is:
f_mandelbrotpowercount(xc,yc,,,)
The default power is 2, the default radius is 2, and the default bailout interations is 100, which should return the same result as the JSL Mandelbrot() function.
If you calculate the result of this function, when power=2, across rectangle defined by
left x value = -2.27, right x value = 2.27
top y value = 1.5, bottom y value = -1.5
and then do some scaling of the results and set RGB colors based on the scaled results, you can get an image like this
The classic Mandelbrot set image!
When power=7, you get an image like this!
Mandelbrot Power Set, power=7
The JSL to create the image file is here
pow=7;<BR />xleft = -1.5*1640/1080;<BR />xright = 1.5*1640/1080;<BR />ytop = 1.5;<BR />ybottom = -1.5;
Parallel Assign(
{f = Name Expr( f_mandelbrotpowercount ), p = pow},
mat[r( ytop, ybottom ), c( xleft, xright )] = f( c, r, p )
);
mat = mat / 100;
green = mat ^ .3;
red = mat ^ 6;
blue = 1 - mat ^ .2;
img = New Image( "rgb", {red, green, blue} );
img << Save image("power7.png");note that this leverages the Parallel Assign() JSl function allow me to use all the cores on my machine to do the calculations. Even with that, a single image at this resolution takes a little more than 2 minutes to generate.
A really cool visual is to watch what happens as you vary the power from 2 up to 10 and back. I created a video of this and posted it on YouTube, if you want to watch it. The sequence is for the power=2 to 10 by increments of 0.005. It took approximately 53 hours to create the image sequences.
Here is the full code to create the image sequences (fair warning, see above, it took me 53 hours to generate the images!)
Names Default To Here( 1 );
f_mandelbrotpowercount = Function( {x, y, d = 2, radius=2, max_n = 100},
{zx, zy, n_iter = 0, r = 0, theta = 0},
if ( x ^ 2 + y ^ 2 <4,
While( (r < radius) & (n_iter < max_n),
zx = r ^ d * Cos( d * theta ) + x;
zy = r ^ d * Sin( d * theta ) + y;
r = Sqrt( zx ^ 2 + zy ^ 2 );
theta = ArcCosine( zx / r ) * ((zy > 0) * 2 - 1);
n_iter++;
);
);
n_iter;
);
xleft = -1.5*1640/1080;
xright = 1.5*1640/1080;
ytop = 1.5;
ybottom = -1.5;
xres = 1640;
yres = 1080;
filenamebase="m000";
fileindex=100000;
mat = J( yres, xres, . );
For( pow = 2, pow <= 10, pow += .005,
Parallel Assign(
{f = Name Expr( f_mandelbrotpowercount ), p = pow},
mat[r( ytop, ybottom ), c( xleft, xright )] = f( c, r, p )
);
mat = mat / 100;
green = mat ^ .3;
red = mat ^ 6;
blue = 1 - mat ^ .2;
img = New Image( "rgb", {red, green, blue} );
img << Save image("D:\mandelbrot\powerbrosequence\m"||char(fileindex)|| ".png");
fileindex+=1;
);Let me know what you think or if you have any questions.