Mandelbrot/julia set display problem

Hello, i am trying to code the mandelbrot/julia set challenge from codingtrain and now i am stuck. I wanted to split the screen into two sides. On the left side it should show the julia set and on the right side it should show the mandelbrot set. The thing is that i wanted that you can hover over the mandelbrot set on the right sied and see the corresponding julia set on the left side change with the movement of the mouse. Right now i can hover over the julia set on the left side and everything works perfect but when i hover over the mandelbrot on the right side it displays the julia set wrong ontop of it. How can i fix that?

public void settings() {
  fullScreen();
}
public void draw() {
  background(0);
  loadPixels();

  int maxiterations=100;
  float ca=map(mouseX, 0, width/2, -2, 2);
  float cb=map(mouseY, 0, height, 2, -2);

  //Mandelbrot set
  for (int x=width/2; x<width; x++) {
    for (int y=0; y<height; y++) {
      float a=map(x, width/2, width, -2, 2);
      float b=map(y, 0, height, 2, -2);
      int n=0;
      while (n<maxiterations) {
        float aa=a*a;
        float bb=b*b;
        float ab2=2*(a*b);
        a=aa-bb+a;
        b=ab2+b;
        if (aa+bb>4) {
          break;
        }
        n++;
      }
      if (n == maxiterations) {
        pixels[x+y*width] = color(0);
      } else {
        float norm = map(n, 0, maxiterations, 0, 1);
        pixels[x+y*width] = color(map(sqrt(norm), 0, 1, 0, 255));
      }
    }
  }
  //Julia set
  if (mouseX<width/2) {
    for (int x=0; x<width/2; x++) {
      for (int y=0; y<height; y++) {
        float a=map(x, 0, width/2, -2, 2);
        float b=map(y, 0, height, 2, -2);
        int n=0;
        while (n<maxiterations) {
          float aa=a*a;
          float bb=b*b;
          float ab2=2*(a*b);
          a=aa-bb+ca;
          b=ab2+cb;
          if (aa+bb>4) {
            break;
          }
          n++;
        }
        if (n == maxiterations) {
          pixels[x+y*width] = color(0);
        } else {
          float norm = map(n, 0, maxiterations, 0, 1);
          pixels[x+y*width] = color(map(sqrt(norm), 0, 1, 0, 255));
        }
      }
    }
  } else {
    for (int x=width/2; x<width; x++) {
      for (int y=0; y<height; y++) {
        float a=map(x, width/2, width, -2, 2);
        float b=map(y, 0, height, 2, -2);
        int n=0;
        while (n<maxiterations) {
          float aa=a*a;
          float bb=b*b;
          float ab2=2*(a*b);
          a=aa-bb+ca;
          b=ab2+cb;
          if (aa+bb>4) {
            break;
          }
          n++;
        }
        if (n == maxiterations) {
          pixels[x+y*width] = color(0);
        } else {
          float norm = map(n, 0, maxiterations, 0, 1);
          pixels[x+y*width] = color(map(sqrt(norm), 0, 1, 0, 255));
        }
      }
    }
  }

  updatePixels();
}
1 Like

i like your program,
but it has not much to do with the operation problem / question

could you just open a new / empty sketch,

make it NOT a fullscreen so you still can see PDE console prints
( and please use many println(…) )

and start with the needed STATE logic depending on mouse left or right side
design a OFFSET of 0 OR width/2

now not draw a rectangle on the right, a circle on the left half side of canvas
make 2 draw functions ( for a rectangle and a circle ) BOTH on left side

and now add the above OFFSET to these functions
?at a beginning translate(OFFSET,0);

you still might have the problem with using the mouse position for the dynamic drawings…
inside some calculations,
independent from where they are drawn, ( and what half side the mouse is )
so you need to use the same state logic
and use a value where you subtract the OFFSET from the mouseX for the calculation.

2 Likes

Ok, thank you but I have one remaining question: How can I paint only the first half of the screen with pixels[], like only the pixels from 0 to width/2 or the other width/2 to width? Or is there another better way as pixels[]?

for (int x=width/2; x<width; x++) {

this writes only to right side?

so i not understand the last question

you can use

if ( rightside ) offset = width/2;
else offset = 0;

for (int x=0+offset; x<width/2+offset; x++) {

better ? get set / no
easier but slower…

I wrote some comments next to the lines where it should be changed. Maybe now it is clear what i mean.

public void settings() {
  //fullScreen();
  size(900, 700);
}
public void draw() {
  background(0);
  pixelDensity(1);
  loadPixels();

  int maxiterations=100;

  //Mandelbrot set displayed on the right side
  for (int x=width/2; x<width; x++) {
    for (int y=0; y<height; y++) {
      float a=map(x, width/2, width, -2, 2);
      float b=map(y, 0, height, 2, -2);
      int n=0;
      while (n<maxiterations) {
        float aa=a*a;
        float bb=b*b;
        float ab2=2*(a*b);
        a=aa-bb+a;
        b=ab2+b;
        if (aa+bb>4) {
          break;
        }
        n++;
      }
      if (n == maxiterations) {
        pixels[x+y*width] = color(0);
      } else {
        float norm = map(n, 0, maxiterations, 0, 1);
        pixels[x+y*width] = color(map(sqrt(norm), 0, 1, 0, 255));
      }
    }
  }
  //Julia set both should be displayed on the left side
  if (mouseX<width/2) { // this gets actually displayed on the left side
    float ca=map(mouseX, 0, width/2, -2, 2);
    float cb=map(mouseY, 0, height, 2, -2);
    for (int x=0; x<width/2; x++) {
      for (int y=0; y<height; y++) {
        float a=map(x, 0, width/2, -2, 2);
        float b=map(y, 0, height, 2, -2);
        int n=0;
        while (n<maxiterations) {
          float aa=a*a;
          float bb=b*b;
          float ab2=2*(a*b);
          a=aa-bb+ca;
          b=ab2+cb;
          if (aa+bb>4) {
            break;
          }
          n++;
        }
        if (n == maxiterations) { // this works fine
          pixels[x+y*width] = color(0);
        } else {
          float norm = map(n, 0, maxiterations, 0, 1);
          pixels[x+y*width] = color(map(sqrt(norm), 0, 1, 0, 255));
        }
      }
    }
  } else { //if the mouse hovers over the right side (mandelbrot)
    float ca=map(mouseX, width/2, width, -2, 2);
    float cb=map(mouseY, 0, height, 2, -2);
    for (int x=width/2; x<width; x++) { //this doesnt get displayed on the left side instead it gets displayed on the right side over the mandelbrot
      for (int y=0; y<height; y++) {
        float a=map(x, width/2, width, -2, 2);
        float b=map(y, 0, height, 2, -2);
        int n=0;
        while (n<maxiterations) {
          float aa=a*a;
          float bb=b*b;
          float ab2=2*(a*b);
          a=aa-bb+ca;
          b=ab2+cb;
          if (aa+bb>4) {
            break;
          }
          n++;
        }
        if (n == maxiterations) { // this is written to display the julia set on the right side which is wrong and it should be written to display it on the left side so the following lines have to be changed
          pixels[x+y*width] = color(0);
        } else {
          float norm = map(n, 0, maxiterations, 0, 1);
          pixels[x+y*width] = color(map(sqrt(norm), 0, 1, 0, 255));
        }
      }
    }
  }

  updatePixels();
}

1 Like

You have an indexing problem, but beyond that this approach is brittle and hard to debug – it will break if you change dimensions, or make one image wider and another narrower, or have three or four, etc. Even swapping the two from left to right is a huge pain.

One alternate approach is to treat each image as its own buffer. You can still do this with fast pixel-array updating. First, buffers. Also, don’t bother redrawing if the mouse hasn’t moved! These can be expensive frames to compute, and that will save tons of wasted cycles.

PGraphics julia;
PGraphics mandelbrot;

public void settings() {
  size(900, 700);
  julia = createGraphics(width/2, height);
  mandelbrot = createGraphics(width/2, height);
  noLoop();
}
void mouseMoved(){
  redraw();
}

Now let’s set up our draw logic –

void draw(){
  if(mouseX>width/2) {
    updateMandelBrot(mandelbrot, mouseX-width/2, mouseY);
    updateJulia(julia, mouseX-width/2, mouseY);
  } else {
    updateJulia(mouseX, mouseY);
  }
  image(julia, 0, 0);
  image(mandelbrot, width/2, 0);
}
void updateMandelbrot(PGraphics pg, int x, int y){
  // ...
}
void updateJulia(PGraphics pg, int x, int y){
  // ...
}

So, if our mouse is on the right, we pass a left-shifted mouse to both update functions, and update both. If it is on the left, we only update Julia. We expressed this in six lines – and if we want to change it, we can, easily. The update functions just take an x, y, and they will then write to the buffer (using julia.beginDraw, julia.loadPixels, julia.updatePixels, julia.endDraw) and the image pixels will be copied onto the canvas.

Does this make sense?

1 Like