Can I selectively delete something from canvas?

I have seen this question asked before, and it seems the answer is no. Still, perhaps I am wrong…

I am running a random walk inspired by Dan Shiffman’s first chapter of Nature of Code. It slowly creates a pretty pattern that I would like to keep. I would also like to highlight where the walker currently is, i.e which pixel is currently being painted, for example by a circle around it or an arrow pointing to it.

This would require erasing and redrawing the circle at each iteration. To make objects move, one normally erases the entire canvas and draws objects at their new locations, but I would lose the pretty pattern that has been created so far.

Is there a way to erase and redraw just my circle? Or can I add a second, transparent canvas that just contains the circle (like a layer in a photo processing program)? Or is there no other solution than redrawing everything, which would require remembering all the dots that have been drawn so far?

2 Likes

There are three methods you can try, either as you suggested separate canvases whi is doable, or use draw with no background, draw does not automatically clears the canvas, this has to be done by either filling the background at each cycle or using clear().
Or you could use an arraylist which could store all the positions and then instead of drawing one circle you would draw all circles in the arraylist
However is there any way to erase and redraw just my circle, well thats what clear or background would do.

2 Likes

They would also delete the entire pattern with the circle

  • So either write the pattern in a PGrapics and display the moving circle upon it - as you said.

  • or write pattern in an ArrayList<PVecor> listPV = new ArrayList(); , using background() throughout plus displaying the ArrayList plus the moving circle upon it - as you said, (remembering all the dots that have been drawn so far)

  • By the way: you can add interactivity for example upon c clear canvas, upon r change color to red.

And welcome to the forum, great to have you here!

Chrisir

Example with an ArrayList

ArrayList<PVector> points = new ArrayList();

void setup() { 
  size(800, 800); 
  background(255);
  noCursor();
}

void draw() { 
  background(255);

  // show points in green 
  strokeWeight(4);
  stroke(0, 255, 0);  // GREEN
  for (PVector pv1 : points) {
    point(pv1.x, pv1.y);
  }

  // show red X 
  showMouse(); 

  // read mouse
  mousePressedThroughout();
}// function draw()

// -------------------------------------------------------------------

void keyPressed() {
  // delete all 
  points.clear();
}

void mousePressedThroughout() {
  // read mouse
  if (mousePressed) {
    //draw
    points.add(new PVector(mouseX, mouseY));
  }//if
}

void showMouse() {
  strokeWeight(1); 
  stroke(255, 0, 0); // RED 

  line( mouseX-3, mouseY-3, 
    mouseX-23, mouseY-23);
  line( mouseX+3, mouseY+3, 
    mouseX+23, mouseY+23);
  line( mouseX+3, mouseY-3, 
    mouseX+23, mouseY-23);
  line( mouseX-3, mouseY+3, 
    mouseX-23, mouseY+23);
}
//
1 Like

And I feel very welcome, thanks paulgoux and Chrisir!

So I will learn about PGraphics and canvases. Great input, and fast.

Stay healthy.

1 Like

Why PGraphics?

How do you like my arraylist example?

I don’t know if it is good form to reply to my 3.5 years old thread. My apologies if not. At the time, I abandoned Processing since other projects got in the way.

With a revived interest, I have now studied the language more and rediscovered this thread. I tried both methods, drawing the random walker on a PGraphics object (the mouse is displayed on the main canvas), and Chrisir’s ArrayList method. Both work very well, though displaying the ArrayList, which grows at a rate of one element per frame, stresses the CPU in the long run. The PGraphics method features stable and low CPU utilization even at later stages of the program.

Thanks again, paulgoux and Chrisir.

1 Like

It is not necessary that it grows. Please check your code.

Edited:

  • I improved my code, because previously you were right (my apologies), when we press and hold mouse button and don’t move the mouse points were still being added.

New version is improved, it adds a new point only when it has a new position.
It shows the ArrayList size() in the upper left corner.

Also use

  • c to clear canvas and
  • Backspace to delete the last point(s) - undo
  • d (hold d down) delete old point close to mouse

You could also alter each old point individually, e.g. change pos, color or size, but I haven’t done this.

Chrisir



ArrayList<PVector> points = new ArrayList();

void setup() {
  size(800, 800);
  background(255);
  noCursor();
}

void draw() {
  background(255);

  // show points in green
  strokeWeight(4);
  stroke(0, 255, 0);  // GREEN
  for (PVector pv1 : points) {
    point(pv1.x, pv1.y);
  }

  // show red X
  showMouse();

  // read mouse
  mousePressedThroughout();

  fill(0);
  text(points.size(), 17, 17);
}// function draw()

// -------------------------------------------------------------------

void keyPressed() {
  if (key=='c') {
    // delete all
    points.clear();
  } else if (key==ESC) {
    key=0; // kill ESC
  } else if (key==BACKSPACE) {
    if (points.size()>0) {
      points.remove(points.size()-1);
    }
  } else if (key=='d') {
    // delete one point that is near mouse
    for (int i=points.size()-1; i >= 0; i--) {
      PVector pv1=points.get(i);
      if (dist(mouseX, mouseY, pv1.x, pv1.y)<9)
        points.remove(i);
    }
  }
}

void mousePressedThroughout() {
  // read mouse
  if (mousePressed&&mouseButton==LEFT) {
    //draw
    if (points.size()>0) {
      PVector previous = points.get( points.size()-1 );
      if (mouseX==previous.x&&mouseY==previous.y) {
        return;
      }
    }
    points.add(new PVector(mouseX, mouseY));
  }//if
}

void showMouse() {
  strokeWeight(1);
  stroke(255, 0, 0); // RED

  line( mouseX-3, mouseY-3,
    mouseX-23, mouseY-23);
  line( mouseX+3, mouseY+3,
    mouseX+23, mouseY+23);
  line( mouseX+3, mouseY-3,
    mouseX+23, mouseY-23);
  line( mouseX-3, mouseY+3,
    mouseX-23, mouseY+23);
}
//


1 Like