Polygons Distribution with loops

Hi there! I am learning about loops these weeks and I have been able to do a screen full of rectangles like the one you can see in the picture. Now I would like to do a screen full of quadrilaterals, but If I do a loop all of them are on top of each others. When you create a loop for rect() you can type random positions and sizes, but how could you do the same with quads? I have created a function but I dont know what to do with It :sweat_smile:!


void setup(){
  

  size(1000,1000);
  for(int i=0; i<30; i++){
  float x1 = random(width);
  float x2 = random(width);
  float x3 = random(width);
  float x4 = random(width);
  float y1 = random(height);
  float y2 = random(height);
  float y3 = random(height);
  float y4 = random(height);
  drawQuad(x1,y1,x2,y2,x3,y3,x4,y4);
  
 
}
}

void drawQuad(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4){
fill(random(255),random(255),random(255));
noStroke();
quad(x1,y1,x2,y2,x3,y3,x4,y4);
}

1 Like

Hello,

All you need to do is to change the way you draw you quads.
Imagine that instead of giving it the coordinates of the 4 corners, you give it a center point and an average radius. In the case, it is easy to spread them away because you just need to separate their centers.

That what I did in the code below.

The drawQuad function take as arguments cx and cy which are like a center point and av_r the average radius of the quad.

The loop is used to compute the coordinate of each corner of the quad.
First an angle is selected randomly (the first one between 0 and 45°, the second between 45° and 90° and so on…)
Once the angle is found I grab a random radius between 0.5 av_r and 1.5 av_r
Having an angle and a radius I can compute each corner of the quad using basic trig math.

void setup() {
  size(500, 500);
  noFill();
  stroke(230);
  strokeWeight(2);
  background(20);
  drawQuad(random(width), random(height), 50);
}


void draw() {
  
}


void mouseClicked() {
  background(20);
  drawQuad(random(width), random(height), 50);
}


void drawQuad(float cx, float cy, float av_r) {
  PVector[] pts = new PVector[4];
  
  for (int i = 0; i < 4; i++) {
    float angle = random(i * HALF_PI, (i + 1) * HALF_PI);
    float r = random(0.5 * av_r, 1.5 * av_r);
    float x = cx + r * cos(angle);
    float y = cy + r * sin(angle);
    pts[i] = new PVector(x, y);
  }
  
  quad(pts[0].x, pts[0].y, pts[1].x, pts[1].y, pts[2].x, pts[2].y,pts[3].x, pts[3].y);
}

Of course, that’s a quick and dirty exemple and this code is less “random” than your code since there are some constraints to select the points. But it is up to you to adapt it according to your needs or even to found a complete different way of creating your quads.

3 Likes

Thank you so much! It is difficult to me to undestand, how could I make more flexible the distance between vertexes?

@jb4x that’s quite the pro approach.

I’ve added below two other ways you achieve a similar result, one a slightly simpler version of the one jb4x proposed. I’m not a fan of the “quad” method… it’s awkward having to put 8 arguments into it… @humano look up “beginShape()” in the Processing reference?

int numObjects = 100;

void setup() 
{
  size(500, 500);  
  
}

void draw() 
{
  background(255);
  noStroke();
  
  // draw red 'quads' using the random rect method
  for(int i = 0; i < numObjects; i++)
  {
    float xPos = random(width/2);
    float yPos = random(height);
    float minS = 10;
    float maxS = 20;
    
    colorMode(HSB, 360, 100, 100);
    fill(0, 100, random(100));
    drawRandomRect(xPos, yPos, minS, maxS);
  }
  
  // draw blue quads using the angular quad method
  for(int i = 0; i < numObjects; i++)
  {
    float xPos = width/2 + random(width/2);
    float yPos = random(height);
    float minS = 10;
    float maxS = 20;
    
    colorMode(HSB, 360, 100, 100);
    fill(220, 100, random(100));
    drawRandomQuad(xPos, yPos, minS, maxS);
  }
  
  noLoop();
}

void drawRandomRect(float x, float y, float minSize, float maxSize) 
{
  float randomRot = random(HALF_PI); // randomly rotate each rect
  
  pushMatrix();
  translate(x, y);
  rotate(randomRot);
  
  beginShape();
  vertex(0, 0);
  vertex(0 + random(minSize, maxSize), 0);
  vertex(0 + random(minSize, maxSize), 0 + random(minSize, maxSize));
  vertex(0, 0 + random(minSize, maxSize));
  endShape(CLOSE);
  
  popMatrix();
}

void drawRandomQuad(float x, float y, float minSize, float maxSize) 
{  
  float randomRot = random(HALF_PI); // randomly rotate each quad
  
  beginShape();
  for (int i = 0; i < 4; i++) {
    // imagine that we're going round a circle, stopping at 4 points along the circle
    float angle = randomRot + i * HALF_PI; 
    float r = random(minSize, maxSize); // choose a different distance from the centre for each point
    float vx = x + r * cos(angle); // look up trigonometry on wikipedia
    float vy = y + r * sin(angle);
    vertex(vx, vy);
  }
  endShape(CLOSE);
}

1 Like

Thank you so much for your help!

1 Like

Let’s save the coordinates of a little square:

float[] coords = new float[] {
  -10, -10, // x1, y1
   10, -10, // x2, y2
   10,  10, // x3, y2
  -10,  10  // y4, y4
};

Think of it like a metal mold or template for pouring a little rubber stamp. We can make the stamp and use it all at once by passing the coordinates to beginShape() or beginShape(QUADS). Here is a stamp method to do that:

void stamp(float[] coords) {
  beginShape();
  for(int i=0; i<coords.length; i+=2) { // read two numbers each time (x, y)
    vertex(coords[i], coords[i+1]); // draw the next point (x, y)
  }
  endShape(CLOSE);
}

So now we can draw our stamp anywhere with translate:

void draw() {
  translate(width/2, height/2);
  stamp(coords);
}

This will always draw our stamp in the middle of the screen. But we want to move the stamp randomly – like moving our arm random before stamping. We can translate randomly:

void draw() {
  translate(random(width), random(height));
  stamp(coords);
}

Now how to make the stamp shape wiggle from a square into various quads, a different one each time? Rather than randomizing each point on the stamp across the whole sketch canvas, instead make each stamp point move only as much as you want relative to the rest of the stamp.

For our example below which draws 20x20 squares, where should you add random numbers to change the stamp points, and how much randomness should you add?

float[] coords = new float[] {
  -10, -10, // x1, y1
   10, -10, // x2, y2
   10,  10, // x3, y2
  -10,  10  // y4, y4
};

void draw() {
  translate(random(width), random(height)); // move before drawing each stamp
  stamp(coords); // draw the stamp
}

// draw one stamp
void stamp(float[] coords) {
  beginShape();
  for(int i=0; i<coords.length; i+=2) { // read two numbers each time (x, y)
    vertex(coords[i], coords[i+1]); // draw the next point (x, y)
  }
  endShape(CLOSE);
}
2 Likes