Mandelbrot Playground

Choose a preset view by changing the `CURRENT_VIEW` constant or play with the values of `settings.custom`.

Log in to post a comment.

const CURRENT_VIEW = "custom" // normal | star | small | lighting | custom

// [zoom, x, y, cutoff]
const settings = {
    normal: [1, 0, -0.5, 30],
    star: [8000, 0.2075, 0.4245, 100],
    small: [55, 0, -1.475, 40],
    lighting: [300, 0.855, -0, 35],
    custom: [1, 0, -0.5, 30]
}

const QUALITY = 0.8 // between 0 and 0.9
const DEPTH = 1000 * QUALITY
const RES = 1000 // max: 2000
const SHOW_CENTER = true

// don't change those

const ZOOM = settings[CURRENT_VIEW][0]
const X = settings[CURRENT_VIEW][1]
const Y = settings[CURRENT_VIEW][2]
const CUTOFF = settings[CURRENT_VIEW][3]

const NATIVE_RES = 200
const RES_RATIO = RES / NATIVE_RES
const HALF_RES = RES / 2.0

Canvas.setpenopacity(-(1-QUALITY*0.3));
//Canvas.setpenopacity(-1);

const turtle = new Turtle();
if (SHOW_CENTER) {
    for (let a = 0; a < 100; a++) {
        turtle.circle(1)
    }
}
        
class ComplexNumber{
    constructor(real, im){
    	this.r = real || 0.0;
        this.i = im || 0.0;
    }
    
    pow2(){
        let a = this.r;
        let b = this.i;
        this.r = a * a - b * b;
        this.i = 2 * (a * b);
    	return this;
    }
    
    len(){
    	return this.r * this.r + this.i * this.i;
    }
    
    times(k){
        this.r *= k;
        this.i *= k;
        return this;
    }
    
    add(complex){
        this.r += complex.r;
        this.i += complex.i;
        
    	return this;
    }
}

const showPoint = (x, y, k) => {
    //if (Math.random()>QUALITY) {return}
    x /= RES_RATIO
    y /= RES_RATIO
    //if (x > 100 || x < -100 || y > 100 || y < -100) {return}
    
    //for (; k>0; k-=20) {
        turtle.penup()
        turtle.goto(x, y)
        turtle.pendown()
        //turtle.right(Math.random()*360)
        turtle.forward(k)
        //turtle.circle(r)
    //}
}

function pixel(x, y){
    let k;
    
    let i = Y + (y  ) / RES_RATIO / (ZOOM * 100);
    let j = X + (x  ) / RES_RATIO / (ZOOM * 100);
    
    let z = new ComplexNumber(0, 0);
    let c = new ComplexNumber(i, j);
    //c.times(0.13 / ZOOM);
    //c.r -= 0.6
            
    for(k = 0; k < DEPTH; k++) {
    	z = z.pow2().add(c);
        if(z.len() > 3.0){
        	break;
        }
	}
    
    if ((z.len() >= 3.0 || !z.len()) && k > CUTOFF ) {
        showPoint(x, y, k/DEPTH)
    }

}

function walk(i) {
    const x = i - HALF_RES
    const test = false
    
    for (let y = -HALF_RES; y < (test ? 0 : HALF_RES); y+=1) {
        
        if (Math.random() < QUALITY) {
            pixel(x, y)
        }
    }  
    
    return x < (test ? 0 : HALF_RES);
}