Mandelbrot set explorer V0 - Super Zoom

Version 001

I made a follow up version V001, which has: faster approximate rendering, symmetric zoom and drag option.

At the start, with the ‘quality’ 4 it looks like this


It increases to 3

2

1

And finally 0, where each pixel is calculated

No previous pixel is calculated again, just ignored and left as it is (since calculating it again would yield the same results), which is optimized. It short, it does a bit more math and takes a few % longer, but in return, you can get an approximation almost instantly.

Version 001
int iter = 64*3;
double offx = -2, offy=-1.28, scale=1.0/200.0;
color clr[] = new color[64]; //how many colors, excluding black. Any additional color just loop around
color inside = #000000;
double zooms[] = {0.9,1,1/0.9};
boolean update = true;
int lastUpdate = 0;
int quality = 3, desiredQuality = 0; //lower the quality, better image (grid size 2^quality)
void setup() {
  fullScreen();

  //size(512, 512);
  colorMode(HSB);
  for (int i = 0; i < 64; i++) clr[i] = color(i*4, 255, 255);
}
void mouseWheel(MouseEvent event) {
  update = true;
  int e = event.getCount();
  double zoom = zooms[e+1];
  float x = (float)mouseX/(float)width, y = (float)mouseY/(float)height;
  double px = -x*abs(1-(float)zoom)*width*e, py = -y*abs(1-(float)zoom)*height*e;
  offx+=px*scale;
  offy+=py*scale;
  scale*=zoom;
  println(scale, 1/scale);
}
void mouseDragged() {
  offx -= (double)((double)mouseX-(double)pmouseX)*scale;
  offy -= (double)((double)mouseY-(double)pmouseY)*scale;
  update=true;
}

void draw() {
  if(update) partialGen(offx, offy, scale, iter, 4, false);
  else if(millis()-lastUpdate>100) partialGen(offx,offy,scale,iter,constrain(quality-1,desiredQuality,100),true);
  if (mousePressed) getPosC(mouseX, mouseY, offx, offy, scale).printC();
}
void partialGen(double Xoff, double Yoff, double Scl, int Iter, int acc, boolean increase) {
  int accuracy = (int)pow(2,acc);
  loadPixels();
  for (int i = 0; i < width; i+=accuracy) for (int j = 0; j < height; j+=accuracy) {
    if( increase == false || (i/accuracy)%4!=0||(j/accuracy)%4!=0) {
    complex c = getPosC((float)i, (float)j, Xoff, Yoff, Scl), z = new complex(c.re, c.im);
    int it = 0;
    boolean loop = true;
    for (it = 0; it < Iter-1 && loop; it++) {
      z.setValue(z2pc(z, c)); 
      if (inBounds(z)==false) loop = false;
    }
    color endClr = (it == iter-1? inside : clr[it%63]);
    
    for (int a = 0; a < accuracy; a++) for (int b = 0; b < accuracy; b++) {
      pixels[constrain(i+a,0,width-1)+constrain(j+b,0,height-1)*width] = endClr;
    }
    }
  }
  updatePixels();
  update = false;
  lastUpdate=millis();
  quality = acc;
}

void generate(double Xoff, double Yoff, double Scl, int Iter) {
  loadPixels();
  for (int i = 0; i < width; i++) for (int j = 0; j < height; j++) {
    complex c = getPosC((float)i, (float)j, Xoff, Yoff, Scl), z = new complex(c.re, c.im);
    int it = 0;
    boolean loop = true;
    for (it = 0; it < Iter-1 && loop; it++) {
      z.setValue(z2pc(z, c)); 
      if (inBounds(z)==false) loop = false;
    }
    pixels[i+j*width] = (it==iter-1? inside : clr[it%63]);
  }
  updatePixels();
  update = false;
  lastUpdate=millis();
  quality = 0;
}


boolean inBounds(complex c) {
  return(c.re*c.re+c.im*c.im<4);
}
class complex {
  double re, im;
  complex(double re, double im) {
    this.re=re;
    this.im=im;
  }
  void setValue(complex c) {
    re = c.re;
    im = c.im;
  }
  void printC() {
    println(re+" + "+im+"i");
  }
}
//COMPLEX CALCULATIONS ----------------------------------------------------------------------
complex csum(complex z, complex w) {
  return new complex(z.re+w.re, z.im+w.im);
}
complex cmult(complex z, complex w) {
  return new complex(w.re*z.re - w.im*z.im, w.re*z.im + z.re * w.im);
}
complex csq(complex z) {
  return cmult(z, z);
}
complex z2pc(complex z, complex c) { //z^2+c
  return csum((csq(z)), c);
}
//VALUE ASSIGNMENT ---------------------------------------------------------------------------
complex getPosC(float x, float y, double xoff, double yoff, double scl) {
  return new complex(xoff+x*scl, yoff+y*scl);
}

1 Like