Rotating Objects Around Central Point

edited March 2017 in Questions about Code

I have this code that draws a flower-like object on the screen where ever you click. However, I only have four petals on it, so it's kind of a lame flower. My question is about adding more petals, but first here is the code:

int c_center;
int c_petal = 20;
int petalsize = int(random(60, 70));
color rcol;

void setup(){
  fullScreen();
  background(0);
}

void draw(){
  //updates values
  rcol = color(random(255), random(255), random(255));
  c_center = int(random(10, 22));
}

void mouseClicked(){
  flower();
}

void flower(){
  //left petal
  make_petal(mouseX - (petalsize - c_petal), mouseY, petalsize, c_petal);
  //right petal
  make_petal(mouseX + (petalsize - c_petal), mouseY, petalsize, c_petal);
  //top petal
  make_petal(mouseX, mouseY - (petalsize - c_petal), c_petal, petalsize);
  //bottom petal
  make_petal(mouseX, mouseY + (petalsize - c_petal), c_petal, petalsize);
  //flower center
  fill(random(255), random(255), random(255));
  ellipse(mouseX, mouseY, c_center, c_center);
}
void make_petal(int a, int b, int c, int d){
  fill(rcol);
  ellipse(a, b, c, d);
}

I was wondering if it was possible to call the petals function again in the mouseClicked function but use some function to rotate it some amount of degrees around the flower center? That way instead of having to code more flower petals I can just rotate the original four (as many times as needed) to get more petals. If you have a better/easier way to achieve this feel free to give such suggestions as well.

Tagged:

Answers

  • Check out the regular polygon example. Rather than equidistant petals around the edge of a flower, it uses a for loop to create equidistant points around the edge of a shape.

    If you use an approach like this -- a for loop -- then you can call flower(4) or flower(10) for four petals or ten petals.

  • That's cool.

    I imagine you can make a star polygon, in which you would just need to draw the central ellipse over it and it would look flower-like as well.

  • Feel free to share your new code here if you arrive at a solution you like -- or if you get stuck and have further questions.

  • Here's an example code I did. I'm sure there's a way to achieve this with less lines of code, but it works nevertheless.

    color c;
    int w;
    int center1_size;
    int center2_size;
    int petal1_size;
    int petal2_size;
    
    void setup() {
      fullScreen();
      background(255);
    }
    
    void draw() {
      c = color(random(255), random(255), random(255));
      w = int(random(30, 40));
      center1_size = int(random(30, 40));
      petal1_size = int(random(100, 150));
      center2_size = int(random(60, 80));
      petal2_size = int(random(60, 70));
    }
    
    void mouseClicked(){
      int r = int(random(0, 10));
      flower_1();
    }
    
    void flower_1(){
      pushMatrix();
      translate(mouseX, mouseY);
      noStroke();
      fill(c);
      rotate(PI/2);
      polygon(0, 0, petal1_size, 5);
      fill(c);
      rotate(-PI/2);
      polygon(0, 0, petal1_size, 5);
      fill(c);
      rotate(PI/4);
      polygon(0, 0, petal1_size, 5);
      fill(c);
      rotate(-PI/4);
      polygon(0, 0, petal1_size, 5);
      fill(c);
      rotate(PI - PI/4);
      polygon(0, 0, petal1_size, 5);
      popMatrix();
    
      fill(random(255), random(255), random(255));
      ellipse(mouseX, mouseY, center1_size, center1_size);
    }
    
    void polygon(float x, float y, float radius, int npoints) {
      float angle = TWO_PI / npoints;
      beginShape();
      for (float a = 0; a < TWO_PI; a += angle) {
        float sx = x + cos(a) * radius;
        float sy = y + sin(a) * radius;
        vertex(sx, sy);
      }
      endShape(CLOSE);
    }
    

    As you said, using this you can easily just change the number of points to get various flower-like shapes. I noticed also that you can get the polygon to rotate by some frame rate about an axis, but that it requires that the rotate function be in draw() so to continuously load that rotation. I was trying to figure out a way to do that here that will still allow me to click and have the shape appear, but also allow it to continuously rotate in space.

  • edited March 2017

    I'm sure there's a way to achieve this with less lines of code

    Like one line very long line?

    float a,b,c,d,e=TAU,f,g;boolean s;void setup(){fullScreen();}void draw(){}void f(){fill(int(random(#000000)));}void mouseClicked(){f=mouseX;g=mouseY;d=b=random(25,35);d*=4;s=false;c=0;pushMatrix();translate(f,g);noStroke();f();while(c<e){rotate(c+=e/((s=(s)?false:true)?8:4));beginShape();for(a=0;a<e;a+=e/5){vertex(cos(a)*d,sin(a)*d);}endShape();}popMatrix();f();ellipse(f,g,b,b);}
    
  • Reading that makes my eyes hurt...

    and this part is a little strange:

    rotate(i+=t/((s=(s)?false:true)?8:4))

    but it appears to check out.

  • haha yup, the ? is an if(), gives a warning but no error

  • Another question on this one about conditional statements:

    void mouseClicked() {
      r = int(random(0, 20));
    
      if (r <= 5) {
        f1.draw_flower_1();
      } else if (r > 5 && r <= 10) {
        f2.draw_flower_2();
      } else if (r > 10 && r <= 15) {
        f3.draw_flower_3();
      } else if(r > 15){
        f4.draw_flower_4();
      }
    }
    

    This outputs a random flower where ever you click, and the randomness (or sort of randomness) is obtained via the variable r. However, occasionally the flowers will overlay, so something about the logic isn't quite right. If I comment out the last else if statement and leave the other three I don't have that problem, so it's something to do with the last one. It's likely something simple, but I'm not seeing it.

  • You got f1,f2,f3,f4 as objects??? And in each of them draw_flower_1 and draw_flower_2 and draw_flower_3 and draw_flower_4. This in itself is confusing.

    Why not only have one function draw_flower ?

    And flowers with different positions or types?

  • What is the difference btw draw_flower_#() functions? It is not possible to reproduce the problem with the code you have provided.

    Kf

  • Post your entire code

  • edited March 2017

    The whole code is over multiple tabs. I have four classes, each representing a different shaped flower. f1, f2, f3, & f4 are just instances of each of those flowers. I mean I could put all of the code in one tab, but it's easier to keep up with across multiple tabs.

    Flower_1 f1;
    Flower_2 f2;
    Flower_3 f3;
    Flower_4 f4;
    
    int r;
    
    void setup() {
      fullScreen();
      background(255);
      f1 = new Flower_1();
      f2 = new Flower_2();
      f3 = new Flower_3();
      f4 = new Flower_4();
    }
    
    void draw() {
    }
    
    void mouseClicked() {
      r = int(random(0, 20));
    
      if (r <= 5) {
        f1.draw_flower_1();
      } else if (r > 5 && r <= 10) {
        f2.draw_flower_2();
      } else if (r > 10 && r <= 15) {
        f3.draw_flower_3();
      } else if(r > 15){
        f4.draw_flower_4();
      }
    }
    
  • However, occasionally the flowers will overlay, so something about the logic isn't quite right. If I comment out the last else if statement and leave the other three I don't have that problem, so it's something to do with the last one

    To address your question, we will need to have a look at the code in the other tabs. As it is right now, the code you presented so far seems all right.

    Kf

  • Okay.

    Class 1:

    class Flower_1{
      int center1_size;
      int petal1_size;
    
      Flower_1(){
      }
    
      void draw_flower_1(){
        center1_size = int(random(30, 40));
        petal1_size = int(random(80, 100));
    
        pushMatrix();
        translate(mouseX, mouseY);
        noStroke();
        fill(random(255), random(255), random(255));
        rotate(PI/2);
        polygon(0, 0, petal1_size, 5);
        rotate(-PI/2);
        polygon(0, 0, petal1_size, 5);
        rotate(PI/4);
        polygon(0, 0, petal1_size, 5);
        rotate(-PI/4);
        polygon(0, 0, petal1_size, 5);
        rotate(PI - PI/4);
        polygon(0, 0, petal1_size, 5);
        popMatrix();
    
        fill(random(255), random(255), random(255));
        ellipse(mouseX, mouseY, center1_size, center1_size);
      }
    
      void polygon(float x, float y, float radius, int npoints) {
        float angle = TWO_PI / npoints;
        beginShape();
        for (float a = 0; a < TWO_PI; a += angle) {
          float sx = x + cos(a) * radius;
          float sy = y + sin(a) * radius;
          vertex(sx, sy);
        }
        endShape(CLOSE);
      }
    }
    

    Class 2:

    class Flower_2 {
      int w;
      int center2_size;
      int petal2_size;
    
      Flower_2() {
      }
    
      void draw_flower_2() {
        w = int(random(45, 46));
        center2_size = int(random(60, 80));
        petal2_size = int(random(60, 70));
    
        pushMatrix();
        translate(mouseX, mouseY);
        strokeWeight(w);
        stroke(random(255), random(255), random(255));
        rotate(PI/2);
        polygon(0, 0, petal2_size, 2);
        rotate(-PI/2);
        polygon(0, 0, petal2_size, 2);
        rotate(PI/4);
        polygon(0, 0, petal2_size, 2);
        rotate(-PI/4);
        polygon(0, 0, petal2_size, 2);
        rotate(PI - PI/4);
        polygon(0, 0, petal2_size, 2);
        popMatrix();
    
        fill(random(255), random(255), random(255));
        ellipse(mouseX, mouseY, center2_size, center2_size);
      }
    
      void polygon(float x, float y, float radius, int npoints) {
        float angle = TWO_PI / npoints;
        beginShape();
        for (float a = 0; a < TWO_PI; a += angle) {
          float sx = x + cos(a) * radius;
          float sy = y + sin(a) * radius;
          vertex(sx, sy);
        }
        endShape(CLOSE);
      }
    }
    

    Class 3:

    class Flower_3 {
      int center3_size;
      int petal3_size;
    
      Flower_3() {
      }
    
      void draw_flower_3() {
        center3_size = int(random(20, 30));
        petal3_size = int(random(70, 100));
        fill(random(255), random(255), random(255));
    
        pushMatrix();
        translate(mouseX, mouseY);
        noStroke();
        rotate(QUARTER_PI);
        star(0, 0, petal3_size/2, petal3_size, 5); 
        rotate(PI);
        star(0, 0, petal3_size/2, petal3_size, 5); 
        popMatrix();
    
        fill(random(255), random(255), random(255));
        ellipse(mouseX, mouseY, center3_size, center3_size);
      }
    
      void star(float x, float y, float radius1, float radius2, int npoints) {
        float angle = TWO_PI / npoints;
        float halfAngle = angle/2.0;
        beginShape();
        for (float a = 0; a < TWO_PI; a += angle) {
          float sx = x + cos(a) * radius2;
          float sy = y + sin(a) * radius2;
          vertex(sx, sy);
          sx = x + cos(a+halfAngle) * radius1;
          sy = y + sin(a+halfAngle) * radius1;
          vertex(sx, sy);
        }
        endShape(CLOSE);
      }
    }
    

    Class 4:

    class Flower_4 {
      int center4_size;
      int petal4_size;
      int line_size;
    
      Flower_4() {
      }
    
      void draw_flower_4() {
        center4_size = int(random(20, 30));
        petal4_size = int(random(70, 100));
        fill(random(255), random(255), random(255));
    
        pushMatrix();
        translate(mouseX, mouseY);
        noStroke();
        rotate(QUARTER_PI);
        star(0, 0, petal4_size/2, petal4_size, 5); 
        stroke(255, random(30, 50));
        rotate(PI/5);
        polygon(-30, 0, petal4_size/2.5, 2);
        rotate(PI/2.5);
        polygon(-30, 0, petal4_size/2.5, 2);
        rotate(PI/1.25);
        polygon(-30, 0, petal4_size/2.5, 2);
        rotate(PI/0.415);
        polygon(-30, 0, petal4_size/2.5, 2);
        rotate(PI/-1.25);
        polygon(-30, 0, petal4_size/2.5, 2);
        popMatrix();
    
        fill(random(255), random(255), random(255));
        ellipse(mouseX, mouseY, center4_size, center4_size);
      }
    
      void star(float x, float y, float radius1, float radius2, int npoints) {
        float angle = TWO_PI / npoints;
        float halfAngle = angle/2.0;
        beginShape();
        for (float a = 0; a < TWO_PI; a += angle) {
          float sx = x + cos(a) * radius2;
          float sy = y + sin(a) * radius2;
          vertex(sx, sy);
          sx = x + cos(a+halfAngle) * radius1;
          sy = y + sin(a+halfAngle) * radius1;
          vertex(sx, sy);
        }
        endShape(CLOSE);
      }
    
      void polygon(float x, float y, float radius, int npoints) {
        float angle = TWO_PI / npoints;
        beginShape();
        for (float a = 0; a < TWO_PI; a += angle) {
          float sx = x + cos(a) * radius;
          float sy = y + sin(a) * radius;
          vertex(sx, sy);
        }
        endShape(CLOSE);
      }
    }
    

    It's likely that there are more efficient and condensed ways to get these shapes, but I'm still new to this...so forgive my novice. They all work nevertheless and give the shapes I desire. Sorry about having to post so much code, but if you find the issue or just have some advice on shortening the code let me know.

  • I don't see any problem.

    However, occasionally the flowers will overlay, so something about the logic isn't quite right.

    What are you referring to? What is not quite right?

    Kf

  • edited March 2017

    Flowers

    Here's a example. Most of the flowers are fine, but some of the star shaped ones look like they're overlapped by other flowers...or that other flowers are showing through. I'm not sure what it is exactly. That would be in Flower 4.

  • edited March 2017

    Oh, jeez I'm stupid. I forgot I set the transparency value for the lines overlaying the flower.

  • .Flowers

    Actually, it didn't really help changing it. This is what they're supposed to look like, and it works when I output Flower 4 by itself. But when I output it randomly with the others it looks like the other picture. I don't really know what's going on.

  • Answer ✓

    I can see the problem now. Use pushStyle() and popStyle() inside each of your classes before you start drawing the flower and right before you leave the function. Alternatively, you can place it at the beginning and end of your mouse event.

    Kf

  • Works great!

    And it's always nice to learn about new functions. I didn't know anything about those. Thank you.

  • I wanted to add this extra class that has to do with the very first problem I asked about rotating petals around a center point. It was a simple fix, I was just drawing the flower using mouseX and mouseY and then translating with both as well, which made the flower petals off center.

    class Flower_5 {
      int c_center = 20;
      color rcol;
    
      Flower_5() {
      }
    
      void draw_flower_5(){
        int w = int(random(5, 15));
        int p_s = int(random(20, 70));
    
        pushMatrix();
        translate(mouseX, mouseY);
        fill(random_color());
        noStroke();
        //draws and rotates petal (starts from top)
        for(int r = 0; r < 360; r+=5){
          rotate(radians(r));
          ellipse(0, 0 - (p_s - w), w, p_s);
        }
    
        //draws center
        fill(random_color());
        noStroke();
        ellipse(0, 0, c_center, c_center);
        popMatrix();
      }
    
      color random_color(){
        rcol = color(random(255), random(255), random(255));
        return rcol;
      }
    }
    
  • Please provide a MCVE: https://stackoverflow.com/help/mcve

    Although a change the constructor, that change is not needed in your case. In fact, you only need function calls to create the flowers unless you want to store the flowers and keep track of them. for example, if you want them to move around.

    I added an extra set of push/pop matrices as rotations are accumulative: https://processing.org/tutorials/transform2d/

    I also changed the rotation step as that gives me a better result. You might also want to adjust the range of w and p_s when they are initialized.

    Kf

    class Flower_5 {
      int c_center = 20;
      color rcol;
    
      int w;
      int p_s ;
    
      Flower_5() {
        w = int(random(5, 15));
        p_s = int(random(20, 70));
      }
      void draw_flower_5() {
    
    
        pushMatrix();
        translate(mouseX, mouseY);
    
        fill(random_color());
        noStroke();
        //draws and rotates petal (starts from top)
        for (int r = 0; r < 360; r+=15) {
          pushMatrix();
          rotate(radians(r));
          ellipse(0, 0 - (p_s - w), w, p_s);
          popMatrix();
        }
    
        //draws center
        fill(random_color());
        noStroke();
        ellipse(0, 0, c_center, c_center);
        popMatrix();
      }
    
      color random_color() {
        rcol = color(random(255), random(255), random(255));
        return rcol;
      }
    }
    
    
    Flower_5 f5;
    void setup() {
      fullScreen();
      background(255);
      f5 = new Flower_5();
    }
    
    void draw() {
    }
    
    void mouseClicked() {
    
      f5.draw_flower_5();
    }
    
  • Looks good. I left the w and p_s variables in the draw_flower function as it allows the petal size to randomly change every time you draw one.

    Sorry, I'm not sure what your first comment is referring to. I was just adding this as a solution to the original question I asked at the top of this post. I made it an extra class to add to the other 4 classes and main function I posted above.

Sign In or Register to comment.