drawing outside draw()

Hello, so i basically i have a convex polygon that i want to fill. In my setup() i have all the loops that generate the points inside the polygon and am using ellipse() to draw each of them in a nice pattern, then i Thread.sleep(200) to make them get draw every 200ms

but now in this implementation all the points get drawn on the canvas right after setup() is done, and they get drawn all at the same time.

the question is,** how can i draw an ellipse outside draw() immediately after calling ellipse() ?** or how can i implement this in another way?

i can post some code too if it helps

Tagged:

Answers

  • Can you show your code -- or a minimal version of your code exhibiting this problem?

    Until seeing the sketch, I'm not quite sure I understand why you are using Thread at all. Setup all happens before screen drawing starts. draw() is called every frameRate() seconds... so why not do the gradually polygon fillin of ellipses in draw()?

  • the thing is even if i draw them in draw() and not in setup(), it will still draw them all at the same time setup()

      public void setup(){
          colorMode(RGB, 255, 255, 255);
          background(0);
          noStroke();
          fill(255,255,255);
          
          //generate points
          PVector[] points = new PVector[TOTAL_POINTS];
          for(int i=0;i<points.length;i++){
              points[i] = new PVector(random(width), random(height));
              ellipse(points[i].x, points[i].y, 10,10);
          }
    
          //calculate vertices that make the convex hull
          ArrayList<PVector> vertices = makeConvexHull(points);
          
          //show convex hull
          showConvexHull(vertices);
          
          //fill the convex hull
          fillConvexHull(vertices);
    
      }
    

    and then i have some nested loops in fillConvexHull():

      private void fillConvexHull(ArrayList<PVector> vertices) {
          strokeWeight(2);
          stroke(255,0,0);
          fill(255,0,0);
          
          PVector driver = vertices.get(0);
          for(int i=0;i<vertices.size()-1;i++){ //for every side
              for(float ratio=0.1f;ratio<1;ratio+=0.1){ //for every point in the side
                  PVector start = vertices.get(i);
                  PVector end = vertices.get(i+1);
                  
                  PVector wallpoint = getPointBetween(start, end, ratio);
                  for(float walk=0.01f;walk<1;walk+=0.01){
                      PVector point = getPointBetween(driver, wallpoint, walk);
                      ellipse(point.x, point.y, 5, 5);
                  }
              }
          }
      }
    
  • edited October 2016 Answer ✓

    not sure if this is what you mean :

    the screen is updated only at the end of draw() (and setup()) - and only once

    when you're using for-loops you'll never see a gradually growing of your scene

    it's all saved behind the scene and then when done put on the screen at once

    if this is your issue, you can of tackle it in different ways, basically using the fact that draw in itself approx. 60 times per second

    e.g. get rid of for(int i=0;i<vertices.size()-1;i++){

    and instead just

    say in draw()

    i++; 
    
    if(i>=vertices.size()-1)
               i=0;
    

    at the end of draw() [not at the end of setup, since setup doesn't loop]

    and before draw() [not IN draw] int i=0;

  • you could just say frameRate(24); to slow things down

  • A runnable example is always better than fragments.

  • or use delay (200); although that as also disadvantages

  • You cannot do animation without using the draw method you don't understand the role of setup and draw methods. You can find out in the Technical FAQ discussion.

  • Please post a working sketch if you are hoping for more detailed feedback. Ideally it should be an MCVE (minimal, complete, and verifiable example). The code you have shared cannot be run.

    Your paradigm for drawing is off. You seem to imagine that "fillConvexHull" will completely fill the hull.

    What you might want is function calls like

    fillConvexHullPart(1);
    fillConvexHullPart(2);
    fillConvexHullPart(3);
    ...
    

    ...or

    fillConvexHullProgress(0.25);
    fillConvexHullProgress(0.50);
    fillConvexHullProgress(0.75);
    ...
    

    ...or

    fillConvexHullNext();
    

    In order to make a series of calls like that over a period of time, each time you are going to draw to the screen, and then draw differently to the screen each time, you need something like (one approach):

    int t;
    void setup(){
      frameRate(10) // built-in, sets fps speed of draw loop
      t =0;
    }
    void draw(){ // built-in, loops, draws
      t++;
      if(t< hullLength){
        fillConvexHullPart(t);
      }
    }
    

    ...so that each time you are going to draw to the screen, you draw something slightly different.

    Processing actually also has a built-in called frameCount for knowing how many frames you have drawn so that you don't have to count them yourself.

    void draw(){
      if(frameCount < hullLength){
        fillConvexHullPart(frameCount);
      }
    }
    
  • Hello thanks you all your answers(too late i know:P) back then i eventually made it with another graphics engine.

    The problem in processing is it whenever you make a drawing call (e.g ellipse(),line()..) they dont get drawn at this time, but they gather up all together in sequence and when draw() is done, it draws them all together.

    example: You want to draw some circles, one after another with 1second delay between. the following wont work: (example 1)

    void draw(){
      background(0);
      for(int i=0;i<circles.length;i++){
        Circle c = circles[i];
        ellipse(c.x, c.y, c.r*2, c.r*2);
        delay(1000);
      }
    }
    

    it will wait for circles.length seconds and then it will draw them all at the same time.

    One solution would be(as Chrisir suggested):

    int i = 0;
    void draw(){
      Circle c = circles[i];
      ellipse(c.x, c.y, c.r*2, c.r*2);
      delay(1000);
    
      i++;
      if(i>=circles.length){ //reset
        background(0);
        i = 0;
      }
    }
    

    it will work, but however in my case i had nested loops... and its not so easy to convert a nested loop into a "draw()" loop like in the above code.

    so today i was making something else and faced this problem again..luckily i found a solution this time

    The other solution is to:

    -have a DRAWING variable for drawing.

    -make draw() method only draw whatever the DRAWING value is.

    -on a different thread change DRAWING value and delay();

    for the (example 1) above the code converts to this(full code):

    float x,y;//for all
    float xd, yd;//for ellipse
    float w, h;//for rect
    float x2, y2; //for line
    final int CLEAR = 0;
    final int DRAW_ELLIPSE = 1;
    final int DRAW_RECTANGLE = 2;
    final int DRAW_LINE = 3;
    int DRAWING = CLEAR; //the state variable
    
    Circle[] circles;
    
    void setup(){
      size(500,500);
      fill(0,0,255);
      stroke(255,0,0);
      background(0); //important
      //init circles array
      circles = new Circle[30];
      for(int i=0;i<circles.length;i++)
        circles[i] = new Circle(random(width),random(height),random(50));
    
      Thread t = new Thread(new Runnable(){
        public void run(){
          while(true){
            realDraw();
            delay((int)(1000/frameRate)); //set frameRate of realDraw() same as draw()
          }
        }
      });
      t.start();
    }
    
    void realDraw(){
      DRAWING = CLEAR;
      for(int i=0;i<circles.length;i++){
        Circle c = circles[i];
        //simulate ellipse() for circle
        DRAWING = DRAW_ELLIPSE;
        //ellipse arguments...
        x = c.x;
        y = c.y;
        xd = c.r * 2;
        yd = c.r * 2;
        delay(1000); //this will work!
      }
    }
    
    void draw(){
      if(DRAWING == CLEAR)
        background(0);
      else if(DRAWING == DRAW_ELLIPSE)
        ellipse(x,y,10,10);
      else if(DRAWING == DRAW_RECTANGLE)
        rect(x,y,w,h);
      else if(DRAWING == DRAW_LINE)
        line(x,y,x2,y2);
    }
    
    class Circle{
      float x,y,r;
      Circle(float x, float y, float r){
        this.x = x;
        this.y = y;
        this.r = r;
      }
    }
    

    hope that will help others with the same problem! :)

Sign In or Register to comment.