Brandon Hillard Projects Personal Experience About Me

Exploring the Mandelbrot Set with JavaScript and p5.js



The Mandelbrot set is a famous mathematical set of complex numbers that has captivated mathematicians, artists, and programmers for decades. It's a fractal, meaning that it exhibits self-similarity at different scales, and its intricate patterns and colors make it a popular subject for generating stunning visualizations.

Recently, I ended up spending an afternoon coding an implementation in p5.js to visualize the mandelbrot set. Who am I kidding, I also wanted to see if I could make a good looking picture like many other mandelbrot visualizations.



Setting Up the Canvas


The first thing we'll do is set up the canvas. We'll create a 800x800 canvas, and set the background to white. Add the following code to the `setup()` function as well as add some global variables we will use later on:

let magnificationFactor = 300;
let panX = 2;
let panY = 1.5;

function setup() {
    createCanvas(800, 800);
    background(220);
    drawHowieMandel();
}

As you may have guessed, the global variables will be used in the visualization to determine what part of the set we want to fill our view window with. Feel free to change the values yourself however these are the values I found most useful for getting the best visualization.


Drawing the Mandelbrot Set


Now let's start drawing the Mandelbrot set. I personally called this function `drawHowieMandel()` because this was a project for fun and that name was sure to never leave my head, feel free to change this name as you see fit.

This function will loop through all the pixels in the canvas and color each pixel based on whether or not it belongs to the Mandelbrot set. Here's the code for the `drawHowieMandel()` function:

function drawHowieMandel(){
    for(var x=0; x < 800; x++) {
        for(var y=0; y < 800; y++) {
            var belongsToSet = 
                checkMandelbrot(x/magnificationFactor - panX,y/magnificationFactor - panY);
            if(belongsToSet !== 0) {
                stroke((belongsToSet) * 255);
                point(x,y); 
            }else{
            //do nothing
            }                
        } 
    }
}

If the pixel belongs to the set, we color it based on its distance from the boundary of the set. We use the `stroke` function to do this in p5.js.

Now we have to build the method `checkMandelbrot()` which will take in our desired x and y values and return if the point belongs to the Mandelbrot set.

function checkMandelbrot(x,y){
    var realComponentOfResult = x;
    var imaginaryComponentOfResult = y;
    var maxIterations = 700;

    for(var i = 0; i < 700; i++) {
            // Calculate the real and imaginary components of the result
            // separately
            var tempRealComponent = realComponentOfResult * realComponentOfResult- imaginaryComponentOfResult * imaginaryComponentOfResult+ x;

            var tempImaginaryComponent = 2 * realComponentOfResult * imaginaryComponentOfResult+ y;

            realComponentOfResult = tempRealComponent;
            imaginaryComponentOfResult = tempImaginaryComponent;

            if(realComponentOfResult * imaginaryComponentOfResult > 5){ 
                return (i/maxIterations);
            }
        }
    return 0;
}

An important piece to understanding this part of the code is to know that the formula for the Mandelbrot Set is `Z^2+C`. To calculate it, we start off with Z as 0 and we put our starting location into C. Then you take the result of the formula and put it in as Z and the original location as C. This is considered only one of our iterations.

What we have done is taken the iterative formula of the mandelbrot set and gotten the C location from our original point. We then calculate the complex value of our point using real and imaginary components, complete our iteration, and then repeat to the degree of precicion we are looking for.

As this is a very intensive way to do this, regenerating our visualization will take some time to compute. One could possibly reduce the time complexity of this program utilizing some more advanced data structures and algorithimic math however for a simple one off project, I was happy with our returned result.

Please feel free to copy this code and test it out yourself!