# How to create Vera Molnar’s Structure de Quadrilatères in p5.js

When trying to learn how to create art, it is helpful to study and copy works of the masters. Painters call this exercise the master study. This exercise is also helpful in generative art!

This tutorial is a master study of one of Vera Molnar’s Structure de Quadrilatères using p5.js:

A couple things to keep in mind:

• It is important to remember that a master study is a learning exercise, not something to be passed off as your own art. Give credit where credit is due. This is Vera Molnar’s work.
• This isn’t a pixel-perfect recreation, but rather a generative technique that will create a similar work.
• This tutorial isn’t perfect. There are other (probably better) ways to structure this code. Use it as a learning tool.
• Write the code yourself and play around with the parameters to get a sense of how it works.
• This tutorial assumes you already know how to set up a p5 canvas and the basics of the setup and draw functions. If not, check out the p5js.org Get Started tutorial first.

This is a great piece to learn some of the basics of generative art with. It uses nested iteration, randomization, an 8×8 grid, and a nice color scheme.

Let’s break it down into some manageable chunks:

I like to start with making sure I know how to make each of the basic elements in the sketch before trying to throw them all together. In this piece, one of the basic elements is in the name: Quadrilaterals, the shape with four edges and four vertices.

Taking a look at the Shapes section of the p5 reference, we see that they have a `quad()`primitive. What luck! Another way would be to draw four separate connecting lines, or drawing a square and skewing it in various ways.

So let’s draw a basic quadrilateral to get a sense of how they work.

```
function setup() {
createCanvas(400,400);
}

function draw() {
background(255);

quad(10, 10, 300, 30, 390, 375, 40, 290);
}

```

Great! Now let’s add in some randomization. We’re going to use the `noLoop()` function so that we only get one quadrilateral each time we hit Play. If it looks like your sketch is glitching, you probably forgot the noLoop.

To add in some randomization, we are going to use the `random()` function. While doing this, keep in mind the order of arguments for the quad function: Clockwise from upper left. That will help us set the bounds for what we want `random()` to return. For example, for the first (upper left) vertex, we probably want a point somewhere between (0,0) and (50,50). So that would mean the first two arguments of the quad function need to be `random(50), random(50)`, meaning: “pick a number between 0 and 50 for x1 and a number between 0 and 50 for y1.”

Now that we’ve added in the random() function for each vertex, each time you hit play you should see a different quadrilateral.

```
function setup() {
createCanvas(400,400);
noLoop()
}

function draw() {
background(255);

random(50), random(50), //x1, y1
random(300,400), random(50), //x2, y2
random(300,400), random(300,400), //x3, y3
random(50), random(200,350) //x4, y4
);
}

```

Great! Play around with this a bit to grok how it works. Next step: Draw a bunch of these in a grid.

## Drawing randomized quadrilaterals in a grid

Iteration might seem like a bit of a jump if you’ve never encountered it before. If not, that is okay–go check out Dan Shiffman’s videos on loops and then come back.

Here I’m setting up a grid, which is an embedded iteration (nested for loops), and then at each spot in that grid I’m drawing a quadrilateral.

You’ll notice a few other things in this code:

• Some variables
• numShapes
• The number of shapes per side. Vera used and 8×8 grid, so we will too.
• Change this number and see how the grid changes!
• size
• The size of each shape based on the canvas width, number of shapes per side, and the space we want around the outside
• width
• height
• push() and pop()
• push() starts a new drawing state, then pop() resets it. Critical here because we are using translate() to move the starting point for each shape. If we did this without push() and pop(), the translate would be additive, so it would not look like a grid. Comment out push() and pop() to see how it would look.
• translate()
• translate() moves the starting point for everything that comes after the translate() function. Here we use it to move each shape to its correct location within the grid by using the x and y variables provided by the for() loop multiplied by the size variable, and offset by the spacing.
• If you are having trouble understanding it, play around with translate() on a fresh sketch to get a sense of how it works.
• Different values for random inside the quad function than we used earlier
• This is because we are offsetting in absolute numbers, not relative percentages. 20 pixels on a shape that is 300 pixels wide is a smaller relative amount than 20 pixels on a shape that is 40 pixels wide.
• ❇️ Bonus challenge: figure out how to make the offsets relative!
```
function setup() {
createCanvas(400,400);
noLoop();
noFill();
}

function draw() {
background(255);

let numShapes = 8; // number of shapes per side
let size = (8*width/10)/numShapes; // the size of each shape based on the canvas width, number of shapes per side, and the space we want around the outside

// iterate in the y direction
for (y=0; y<numShapes; y++) {
// iterate in the x direction
for (x=0; x<numShapes; x++) {
push(); // start a new drawing state
// change the starting point of each instance to the correct location
translate(width/10 + x*size, height/10 + y*size);
random(-5,5), random(-5,5),
random(size/2-5,size+5), random(-5,5),
random(size/2-5, size+5), random(size/2-5,size+5),
random(-5,5), random(size/2-5,size+5)
)
pop(); // reset the drawing state
}
}
}

```

Great! We are getting somewhere. Now let's do another loop so that we get multiple quadrilaterals in each spot on the grid.

## Drawing multiple quadrilaterals at each spot in the grid

Now we need to go back and look at Vera's original piece and make a choice: Do we draw all of the quadrilaterals in each spot before moving on to the next, or do we draw all of the bottom layer, then all of the second layer, etc? The answer to this determines where we put the loop: Inside the grid loop where the quad() function is, or outside the grid loop to draw multiple grids.

Looking at how the lines on Vera's original piece overlap, I think we should do the latter: Drawing multiple grids. This doesn't matter so much when the lines are all black, but it will make a big difference when they are in color.

```
function setup() {
createCanvas(400,400);
noLoop();
noFill();
}

function draw() {
background(255);

let numShapes = 8; // number of shapes per side
let size = (8*width/10)/numShapes; // the size of each shape based on the canvas width, number of shapes per side, and the space we want around the outside

for (i=0; i<12; i++) { // iterate to draw multiple grids
// iterate in the y direction
for (y=0; y<numShapes; y++) {
// iterate in the x direction
for (x=0; x<numShapes; x++) {
push(); // start a new drawing state
// change the starting point of each instance to the correct location
translate(width/10 + x*size, height/10 + y*size);
random(-10,10), random(-10,10),
random(size/2-5,size+5), random(-5,5),
random(size/2-5, size+5), random(size/2-5,size+5),
random(-5,5), random(size/2-5,size+5)
)
pop(); // reset the drawing state
}
}

}
}

```

Looking pretty good! Go ahead and play around with some of the variables and the inputs to the random() functions to see how it affects the output.

Okay, getting close! Now we need to add some color.

For a single grid that would be easy: Just set up an array of colors and pass that array to random() inside the stroke() function right before the quad() inside the loop. It isn't that simple when we are drawing multiple grids with a loop because that will lead to different colors within a pile of quadrilaterals. That might look cool, but it isn't what Vera's piece looks like.

So what do we do? There are multiple ways to solve this problem, but my preferred way to making an array of color options and using a loop to create an array of color assignments the same size as the grid.

You'll note that I'm using the HSB color mode here. Check out Tyler Hobbs's great article about it.

I sampled Vera's original piece and created an array of the HSB version of colors she used with 0.9 opacity (trying to mimic the pen color bleed-through overlap).

```
function setup() {
createCanvas(400,400);
noLoop();
noFill();
colorMode(HSB);
}

function draw() {
background(255);

let numShapes = 8; // number of shapes per side
let size = (8*width/10)/numShapes; // the size of each shape based on the canvas width, number of shapes per side, and the space we want around the outside

// Colors
let vera = [color(18, 80, 91, 0.9), color(178, 100, 63, 0.9), color(212, 100, 63, 0.9), color(300, 29, 9, 0.9), color(257, 52, 61, 0.9)];
let shapeColors = [];
for (c=0; c<(numShapes*numShapes); c++) {
shapeColors.push(random(vera));
}

for (i=0; i<12; i++) { // iterate to draw multiple grids
let s=0; // shape counter for the color array
// iterate in the y direction
for (y=0; y<numShapes; y++) {
// iterate in the x direction
for (x=0; x<numShapes; x++) {
push(); // start a new drawing state
// change the starting point of each instance to the correct location
translate(width/10 + x*size, height/10 + y*size);
stroke(shapeColors[s])
random(-10,10), random(-10,10),
random(size/2-5,size+5), random(-5,5),
random(size/2-5, size+5), random(size/2-5,size+5),
random(-5,5), random(size/2-5,size+5)
)
pop(); // reset the drawing state
s++; // increment the shape counter
}
}

}
}

```

Almost there! Here is one of our versions compared with Vera's:

Looks like we are getting very close. I think the final steps here are to: