Mandelbrot Set in JS
Tags: mandelbrot, set, javascript, fractal
Published: 2020-04-24 01:47:36

In this entry I want to share with you, a little of my knowledge to show you how to plot a ***[Mandelbrot Set](https://en.wikipedia.org/wiki/Mandelbrot_set)*** without any library just JS, so go ahead!.

**Note:** If you are not familiar with the mathematical terms used here, I recommend you to read about [complex numbers](https://en.wikipedia.org/wiki/Complex_number) and [fractals](https://en.wikipedia.org/wiki/Fractal).

First of all, ***What a heck is a Mandelbrot Set?***, according to [mathworld](https://mathworld.wolfram.com/MandelbrotSet.html):

*A* **Mandelbrot Set**, *is used to refer both to a general class of [fractal](https://en.wikipedia.org/wiki/Fractal) sets and to a particular instance of such a set. In general, a Mandelbrot set marks the set of points in the complex plane such that the corresponding Julia set is connected and not computable.*

In a nutshell, a mandelbrot set is one of the most beautiful and famous [fractal](https://en.wikipedia.org/wiki/Fractal), that is defined by the set of [complex numbers](https://en.wikipedia.org/wiki/Complex_number).

In the next picture you can see what I mean.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/uymtwdcj96dku6137lau.png)
              ***Figure 1:*** Mandelbrot set - black and white

In this entry you will learn how to plot in JS, the previous image.

But before, let's see a little more theory about how this set works.

##Definition
As we mention before, the mandelbrot set is defined in the set of complex numbers ***c*** for which the function,
![mandlebrot set](https://static.packt-cdn.com/products/9781787120495/graphics/33907ca6-9f25-439c-bb21-4e0ddbc9272e.jpg)
does not [diverge](https://en.wikipedia.org/wiki/Stability_theory#DIVERGE) when iterated from ***z = 0***.

Below, the previous equation is broken down:

As you can see, the ***Mandelbrot set*** is obtained from the quadratic recursive equation where, ***z*** and ***c*** represents a complex number.

To represent visually this set we need to find, for each point ***c***
 of a part of the complex plane, if ***Zn*** is bounded. When the modulus of ***Zn*** is greater than ***2***, means that the number does not belong to ***Mandelbrot set***, otherwise it is part of the set. The number of iterations to reach a modulus greater than 2 can be used to determine the color to use when we are plotting.

A complex plane can be represented in a normal 2D plane, where the ***X*** axis, will represent the real number, meanwhile the ***Y*** axis will represent the imaginary number, for instance, ***x = 3; y= 5i***.

For a better understanding please refer to [this video](https://www.youtube.com/watch?v=NGMRB4O922I).

##Plot of the Mandelbrot Set

Finally, after understand a bit of the Mandelbrot equation, it's time to implement it:
![mandlebrot set](https://wikimedia.org/api/rest_v1/media/math/render/svg/191627a3eebdd6608c9b226786defc468b747502)
```javascript
const MAX_ITERATION = 80
function mandelbrot(c) {
    let z = { x: 0, y: 0 }, n = 0, p, d;
    do {
        p = {
            x: Math.pow(z.x, 2) - Math.pow(z.y, 2),
            y: 2 * z.x * z.y
        }
        z = {
            x: p.x + c.x,
            y: p.y + c.y
        }
        d = Math.sqrt(Math.pow(z.x, 2) + Math.pow(z.y, 2))
        n += 1
    } while (d <= 2 && n < MAX_ITERATION)
    return [n, d <= 2]
}
```
1. The ***mandelbrot*** function receives a complex number, it has real and imaginary part, here we are representing those components as ***x*** and ***y***.
2. The ***p*** variable contains the computing of the square of ***z***, which is also a complex number, please refer to [this](https://www.khanacademy.org/math/algebra2/x2ec2f6f830c9fb89:complex/x2ec2f6f830c9fb89:complex-mul/a/complex-number-operations-review), to understand how basic operations such as addition, subtraction and multiplication works in complex numbers. 
3. ***z*** is recalculated and now it contains the addition of the received complex number ***(c)*** and the previous ***z***.
4. ***d*** is the modulus of the new complex number ***(z)***, computed before.
5. Add one when each iteration is completed ***(n += 1)***.
6. The whole process is repeated while the modulus of ***z*** belongs to ***Mandelbrot set*** and the iteration number is less than ***80***.
7. Finally, the function returns a tuple, with the iteration number that it took to reach a modulus greater than 2, and whether the complex number passed to it, belongs to ***Mandelbrot set***.

And that's it!, we have implemented a mandelbrot equation.
Now is time to plot.

```javascript
var canvas = document.getElementById('myCanvas')
var ctx = canvas.getContext('2d')

const WIDTH = window.innerWidth
const HEIGHT = window.innerHeight
ctx.canvas.width = WIDTH
ctx.canvas.height = HEIGHT

const REAL_SET = { start: -2, end: 1 }
const IMAGINARY_SET = { start: -1, end: 1 }

const colors = new Array(16).fill(0).map((_, i) => i === 0 ? '#000' : `#${((1 << 24) * Math.random() | 0).toString(16)}`)

function draw() {
    for (let i = 0; i < WIDTH; i++) {
        for (let j = 0; j < HEIGHT; j++) {
            complex = {
                x: REAL_SET.start + (i / WIDTH) * (REAL_SET.end - REAL_SET.start),
                y: IMAGINARY_SET.start + (j / HEIGHT) * (IMAGINARY_SET.end - IMAGINARY_SET.start)
            }

            const [m, isMandelbrotSet] = mandelbrot(complex)
            ctx.fillStyle = colors[isMandelbrotSet ? 0 : (m % colors.length - 1) + 1]
            ctx.fillRect(i, j, 1, 1)
        }
    }
}
```
1. In the first lines, the ***canvas*** element is found and its ***context***, then the ***window*** ***width*** and ***height*** is assigned to the canvas.
2. ***REAL_SET*** constant represent the real numbers of ***Mandlebrot set***, as you saw the ***Figure 1*** of this entry, the domain in ***x axis*** goes from ***-2*** to ***1***.
3. ***IMAGINARY_SET*** represent, the imaginary numbers in ***y axis***, the domain in ***y axis*** goes from ***-1*** to ***1***.
4. ***colors***, store a list of ***16*** random hexadecimal colors.
5. ***draw*** function:
   - The entire ***width*** and ***height*** of the canvas are iterated.
   - The ***"complex"*** variable store a complex number; ***x*** and ***y***, are calculated getting a relative value, of the width and height of the canvas, plus the values ​​that belong to the *mandelbrot set*.
   - ***mandelbrot*** function is called
   - A color is assigned to canvas pixel, if the complex number passed to ***mandelbrot*** function belongs to set, the black color is chosen, otherwise the color depends of the number of iteration made by ***mandelbrot function***.
    - A pixel (rectangle of 1 width and height) is plotted  in the position ***i, j***.

That's all, we've finished, it was so easy! isn't it?

If we run the code, it shows the next figures.
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zp9dc62mc75gp774dhzy.png)
***Figure 2.*** Mandelbrot set, example 1.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/p7wtllt2rjco6i8cjr57.png)
***Figure 3.*** Mandelbrot set, example 2.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/s1m3aiugtoxyr38b3fi7.png)
***Figure 4.*** Mandelbrot set, example 3.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/0jbpzgmea0jfrb1sysaa.png)
***Figure 5.*** Mandelbrot set, example 4.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ys0k6qprgl4holy0r00w.png)
***Figure 6.*** Mandelbrot set, example 5.

I hope you've enjoyed!.

[Live demo](https://jsbin.com/ruhuxefabo/1/edit?js,output)
[Full code](https://github.com/foqc/mandelbrot-set)

By the way, It's my first blog, written entirely in English (I'm not a native speaker), maybe you've already realized, so sorry for the misspellings!, please If you have any recommendation, or comment you can leave in the comments section.

##Next steps
Our fractal is plotted, so in the [next entry](https://dev.to/foqc/mandelbrot-set-in-js-zoom-in-2hmc) I will implement the **zoom**, when a part of the image is clicked.

Stay safe and thanks for reading!