Help regarding drawing polygons faster

edited May 2016 in Questions about Code

I can't seem to get the draw function to run fast enough to make the ellipses flow smoothly. How should I fix this?

Link

void setup() {
  size(800, 600);
  background(255);
  noStroke();
  fill(0);
  drawControls();
  fill(0);
  frameRate(300);
  cursor(CROSS);
}

void draw() {
  noStroke();
  if (mousePressed == true && mouseY < height - 110 && mouseY > 80) {
    ellipse(pmouseX, pmouseY, 20, 20);
  } else {
    checkButtons();
  }
}

void drawControls() {
  textBox();
  fill(192); //grey
  rect(0, 500, 800, 100, 10, 10, 0, 0); //bottom bar for palette
  strokeWeight(2); //makes the borders of the next shape stroke 2
  stroke(0); //changes stroke color to 0 (black)
  fill(255, 0, 0); //red
  rect(0, 550, 50, 50, 10, 10, 10, 10);
  fill(0, 255, 0); //blue
  rect(50, 550, 50, 50, 10, 10, 10, 10);
  fill(0, 0, 255); //green
  rect(50, 500, 50, 50, 10, 10, 10, 10);
  fill(0, 0, 0); //black
  rect(0, 500, 50, 50, 10, 10, 10, 10);
  fill(255, 255, 0); //
  rect(100, 500, 50, 50, 10, 10, 10, 10);
  fill(255, 0, 255);
  rect(100, 550, 50, 50, 10, 10, 10, 10);
  fill(0, 255, 255);
  rect(150, 500, 50, 50, 10, 10, 10, 10);
  fill(255, 128, 0);
  rect(150, 550, 50, 50, 10, 10, 10, 10);
  fill(127, 0, 255);
  rect(200, 500, 50, 50, 10, 10, 10, 10);
  fill(215, 215, 215);
  rect(200, 550, 50, 50, 10, 10, 10, 10);
  fill(245, 222, 179);
  rect(250, 500, 50, 50, 10, 10, 10, 10);
  fill(230, 230, 250);
  rect(250, 550, 50, 50, 10, 10, 10, 10);
}

void checkButtons() {
  if (mousePressed == true && mouseX > 0 && mouseX < 50 && mouseY < 550 && mouseY > 500) {
    fill(0, 0, 0);
  }
  if (mousePressed == true && mouseX > 0 && mouseX < 50 && mouseY > 550 && mouseY < 600) {
    fill(255, 0, 0);
  }
  if (mousePressed == true && mouseX > 50 && mouseX < 100 && mouseY < 550 && mouseY > 500) {
    fill(0, 0, 255);
  }
  if (mousePressed == true && mouseX > 50 && mouseX < 100 && mouseY > 550 && mouseY < 600) {
    fill(0, 255, 0);
  }
  if (mousePressed == true && mouseX > 100 && mouseX < 150 && mouseY > 500 && mouseY < 550) {
    fill(255, 255, 0);
  }
  if (mousePressed == true && mouseX > 100 && mouseX < 150 && mouseY > 550 && mouseY < 600) {
    fill(255, 0, 255);
  }
  if (mousePressed == true && mouseX > 150 && mouseX < 200 && mouseY > 500 && mouseY < 550) {
    fill(0, 255, 255);
  }
  if (mousePressed == true && mouseX > 150 && mouseX < 200 && mouseY > 550 && mouseY < 600) {
    fill(255, 128, 0);
  }
  if (mousePressed == true && mouseX > 200 && mouseX < 250 && mouseY > 500 && mouseY < 550) {
    fill(127, 0, 255);
  }
  if (mousePressed == true && mouseX > 200 && mouseX < 250 && mouseY > 550 && mouseY < 600) {
    fill(215, 215, 215);
  }
  if (mousePressed == true && mouseX > 250 && mouseX < 300 && mouseY > 500 && mouseY < 550) {
    fill(245, 222, 179);
  }
  if (mousePressed == true && mouseX > 250 && mouseX < 300 && mouseY > 550 && mouseY < 600) {
    fill(230, 230, 250);
  }
}

void textBox() {
  fill(192);
  rect(0, 0, 800, 70);
}
Tagged:

Answers

  • edited May 2016 Answer ✓

    The first thing to say is the checkButtons code is very inefficient. You check every button even if the mouse button is not pressed. If it is over a button it still continues to checks the other buttons even though it cant be over them..

    Second thing to say is that when the mouse moves quickly the difference between frames of the mouse means that you are not going to get a 'solid' line. Changine frameRate will not help much.

    This code solves both problems. The drawLine method is recursive and draw a series of ellipses between previous and current mouse positions. Notice I have removed the frameRate(300) statement - no longer needed.

    Enjoy

    void setup() {
      size(800, 600);
      background(255);
      noStroke();
      fill(0);
      drawControls();
      fill(0);
      cursor(CROSS);
    }
    
    void draw() {
      noStroke();
      if (mousePressed == true && mouseY < height - 110 && mouseY > 80) {
        drawLine(pmouseX, pmouseY, mouseX, mouseY);
      } else {
        checkButtons();
      }
    }
    
    void drawControls() {
      textBox();
      fill(192); //grey
      rect(0, 500, 800, 100, 10, 10, 0, 0); //bottom bar for palette
      strokeWeight(2); //makes the borders of the next shape stroke 2
      stroke(0); //changes stroke color to 0 (black)
      fill(255, 0, 0); //red
      rect(0, 550, 50, 50, 10, 10, 10, 10);
      fill(0, 255, 0); //blue
      rect(50, 550, 50, 50, 10, 10, 10, 10);
      fill(0, 0, 255); //green
      rect(50, 500, 50, 50, 10, 10, 10, 10);
      fill(0, 0, 0); //black
      rect(0, 500, 50, 50, 10, 10, 10, 10);
      fill(255, 255, 0); //
      rect(100, 500, 50, 50, 10, 10, 10, 10);
      fill(255, 0, 255);
      rect(100, 550, 50, 50, 10, 10, 10, 10);
      fill(0, 255, 255);
      rect(150, 500, 50, 50, 10, 10, 10, 10);
      fill(255, 128, 0);
      rect(150, 550, 50, 50, 10, 10, 10, 10);
      fill(127, 0, 255);
      rect(200, 500, 50, 50, 10, 10, 10, 10);
      fill(215, 215, 215);
      rect(200, 550, 50, 50, 10, 10, 10, 10);
      fill(245, 222, 179);
      rect(250, 500, 50, 50, 10, 10, 10, 10);
      fill(230, 230, 250);
      rect(250, 550, 50, 50, 10, 10, 10, 10);
    }
    
    void checkButtons() {
      if (mousePressed) { // only interested if mouse pressed
        if (mouseY > 500 && mouseY < 550) {
          if (mouseX > 0 && mouseX < 50) { // top row
            fill(0, 0, 0);
          } else if (mouseX > 50 && mouseX < 100) {
            fill(0, 0, 255);
          } else if (mouseX > 100 && mouseX < 150) {
            fill(255, 255, 0);
          } else if (mouseX > 150 && mouseX < 200) {
            fill(0, 255, 255);
          } else if (mouseX > 200 && mouseX < 250) {
            fill(127, 0, 255);
          } else if (mouseX > 250 && mouseX < 300) {
            fill(245, 222, 179);
          }
        } else if (mouseY > 550 && mouseY < 600) { // Bottom row
          if (mouseX > 0 && mouseX < 50) {
            fill(255, 0, 0);
          } else if (mouseX > 50 && mouseX < 100) {
            fill(0, 255, 0);
          } else if (mouseX > 100 && mouseX < 150) {
            fill(255, 0, 255);
          } else if (mouseX > 150 && mouseX < 200) {
            fill(255, 128, 0);
          } else if (mouseX > 200 && mouseX < 250) {
            fill(215, 215, 215);
          } else if (mouseX > 250 && mouseX < 300) {
            fill(230, 230, 250);
          }
        }
      }
    }
    
    void drawLine(float x0, float y0, float x1, float y1) {
      float midX = (x0+x1)/2;
      float midY =(y0+y1)/2;
      if (abs(x0-x1) > 1 || abs(y0-y1) > 1) {
        drawLine(x0, y0, midX, midY);
        drawLine(midX, midY, x1, y1);
      }
      ellipse(midX, midY, 20, 20);
    }
    
    void textBox() {
      fill(192);
      rect(0, 0, 800, 70);
    }
    
  • Quark, thanks for the help, the code works! I would just like to know how the void drawLine command works, as that's the only part I really don't understand. Thanks :)

  • The drawLine is recursive function, that is a function that calls itself. We can see that in lines 90 and 91. There is a lot about about recursion on the Internet so I won't repeat the theory behind it but rather explain in words what is happening in your sketch.

    We first call the function in line 14 to draw a line of ellipses between two points P0 : [x0,y0] & [P1 : x1,y1].

    The function first calculates the midway point (Pmid) between P0 and P1 and if the x coordinates OR the y coordinates differ by 1 or more pixel it calls the same method but with the 2 smaller lines P0-Pmid and Pmid-P1. This logic is then repeated for the 2 small lines until the two points are within 1 pixel.

    The code below does something similar but is modified to clearly show the order the ellipses are drawn. Note that we use 64 instead of 1 pixel as the distance between ellipses. Here is the ouput recur

    The numbers correspond to the order that they are drawn. The Y offset is to show that more clearly. If you trace the code and see when the ellipses are drawn it will give you a better idea of what is happening.

    int n = 0;
    void setup() {
      size(512, 200);
      background(255);
      fill(255, 200, 200);
      stroke(128, 0, 0);
      drawLine(0, 30, width, 30, 0);
    }
    
    void drawLine(float x0, float y0, float x1, float y1, int offset) {
      float midX = (x0+x1)/2;
      float midY = (y0+y1)/2;
      if (abs(x0-x1) > 64 || abs(y0-y1) > 64) {
        drawLine(x0, y0, midX, midY, offset + 40); // left half
        drawLine(midX, midY, x1, y1, offset + 40);  // right half
      }
      fill(255, 200, 200);
      stroke(128, 0, 0);
      ellipse(midX, midY + offset, 32, 32);
      // Draw ellipse number
      fill(0);
      float dx = (n > 9) ? 8 : 4;
      text(n, midX - dx, midY + offset + 4);
      n++;
    }
    
Sign In or Register to comment.