Mandelbrot Set is a set of complex numbers that satisfy certain condition. The beauty if this set is that it forms a fractal - an object that repeats itself while zooming in.
Link to Wikipedia: https://en.wikipedia.org/wiki/Mandelbrot_set
Here is a live coding session that shows how it can be done.
Duration: 4:11
Disclaimer: never use this code in production. It was created for fun.
Let's break down the solution and comment on some complex or interesting things.
The whole solution is done using vanilla JavaScript with drawing on HTML canvas. This means that you don't need any additional software to be installed.
For the project we need some math (in particular - complex numbers) knowledge. Let's recap it.
A complex number z can be represented as z = x + bi
, where x
and y
are real numbers and i is the imaginary unit.
We'll need to know 3 operations over complex numbers:
z + v = (a + bi) + (c + di) = (a + c) + (b + d)i
zv = (a + bi)(c + di) = (ac - bd) + (ad + bc)i
|z| = | a + bi | = sqrt(a^2 + b^2)
c
belongs to Mandelbrot set if and only if Z
sequence is bounded and |z| < 2
0:27 - start with building HTML page with head and body elements.
0:35 - JavaScript by default does not have support for complex numbers (of course we can use some 3-rd party library). So we need to implement the required operations on our own. You can check description above which operations do we need and how they should work.
1:07 - next step is define a function that checks if point c
belongs to Mandelbrot set or not. Important note here - we cannot for sure say if original Z
sequence is bounded or not. Instead we are defining a number of iterations - if after this number of iterations the sequence is still bounded we consider that point c
belongs to the set. Otherwise - does not belong.
1:25 - implementing the drawing logics. For now we only define functions that will draw the pixel (that will correspond to point on a complex plane).
Mathematicians already proved some nice properties of Mandelbrot set and one of them is that all points of this set are inside [-2; 1] x [-1, 1]
area - thus it does not make sense to check points outside of this region.
In this step we should iterate though the canvas (we should know canvas' width and height) and scale canvas coordinates to complex plane (keeping in mind bounds of the set).
Then we iterate by canvas rows and canvas columns and do the following:
re
(real part of complex number) and im
(imaginary part of complex number)draw
function and assume that our canvas will be 450 by 300 pixels and we'll use 100 iterations to check if points belong to Mandelbrot set or not.
2:12 - implement visual parts.
First of all - define HTML canvas element that we will draw on. Pay attention that we are using the same dimensions - 450 by 300 pixels.
Then we need to capture canvas context - it exposes API for actual drawing.
Unfortunatelly HTML canvas is not suited for working with single pixels. There are few options how we can work it around (e.g. draw one pixel line), but it seems that the easier and more performant way is just to draw 1 by 1 pixel rectangle and fill it with required color.
2:29 - checking the first results to see how it looks. How we see that with 100 iterations we got pretty nice aproximation of Mandelbrot set.
2:30 - let's evaluate how the number of iterations affect the look of Mandelbrot set. Obviously the more iterations we do the more precise the visualization will be. On the other hand - fewer iterations will give more rounded image.
Taking some examples for number of iterations and redraw Mandelbrot set with 1 second delay with different number of iterations - from smaller number to bigger number.
You can see that with bigger number of iterations the result looks more similar to classical Mandelbrot set images.
I would say that for such canvas size using 100 iterations is more than enough.
2:59 - As mentioned above technically a point can either belong to Mandelbrot or not. Meaning that the visualization is monochrome (black and white).
However Mandelbrot set is also famous for nice colorful visualizations. People play around with colors and get really nice pictures.
Let's try to do the same and use different colors to determine how "quickly" we determined that point does not belong to Mandelbrot set (for points that do belong we'll use black).
Previously belongs
function just returned boolean value - either true
or false
. Now we change it to return number of iterations that were required to detect if point belongs or not. For the case when point belongs to the set the function will return maxIterations
.
There can be different strategies how to pick colors, we can use different color models.
I personally like to use HSL
(hue, saturation, lightness) scheme here. It provides nice way how to get different colors with smooth transitions. The magic coefficients provided in the example are results of multiple attempts. For sure you can find better colors.
3:15 - with the colors defined the Mandelbrot set looks even better. Here again it's good to find the balance between preciseness of visualization and the colors. I thing that with 100 iterations we get better results where we can clearly see the light-green areas very close to the set itself.
3:24 - as said in the Wikipedia, Mandelbrot set is a fractal. It is an object that repeats itself. If we zoom in some area on the border of the set we should see the same visualization. Here I chose some random point on the set and let's do the iterative visualization of this area.
Of course this zooming process can continue forever.
This concludes this project. Despite being quite complex mathematical object it is quite easy to implement visualization of Mandelbrot set.
Sources: https://github.com/5minute/examples/tree/main/mandelbrot
See live results:https://jsfiddle.net/tpm9cr3L/