Transformation

In p5, we can change shapes by changing the fill, shape and size, but we can also change their relationship to the coordinate system using transformations.

Usually we draw everything starting at 0,0 in the upper left corner, but we can change that. We can also change the scale, rotation and shear of shapes. And we can do it multiple times throughout the program. This is an convenient way to create new effects and animations.

translate

translate moves the origin to a new point on the canvas.

function setup() { createCanvas(640, 360); background(220); ellipse(0, 0, 100); translate(200, 200); ellipse(0, 0, 100); translate(200, -100); ellipse(0, 0, 100); }

Notice that each ellipse has the same xy coordinate, 0,0, but appear in different places.

Also notice that transformations are cumulative, meaning they add together.

rotate

Translate is useful because rotations are done around the origin point, 0,0. To rotate a shape around a specific point, translate is required.

rotate rotates the canvas around it's origin point.

Be default, angles in p5 are measured in units of PI. PI is a mathematical constant that describes the relationship of a circles circumference to it's diameter and is equivalent to roughly 3.14. For our purposes, it is only necessary to know that PI is half a rotation and TWO_PI or PI * 2 is a full rotation. p5 also has smaller measurement including HALF_PI and QUARTER_PI.

Rotation in p5 goes positive in the clockwise direction.

function setup() { createCanvas(400, 400); background(220); translate(200, 100); rect(0, 0, 50, 50); ellipse(100, 100, 60); rotate(QUARTER_PI); rect(0, 0, 50, 50); ellipse(100, 100, 60); rotate(QUARTER_PI); rect(0, 0, 50, 50); ellipse(100, 100, 60); rotate(QUARTER_PI); rect(0, 0, 50, 50); ellipse(100, 100, 60); }

scale

Scale is pretty straight forward, it changes the scale of the shapes.

function setup() { createCanvas(640, 360); background(220); rectMode(CENTER); ellipse(40, 40, 20); rect(60, 40, 20, 20); scale(2); ellipse(40, 40, 20); rect(60, 40, 20, 20); scale(3); ellipse(40, 40, 20); rect(60, 40, 20, 20); }

shear

shear is a little more complicated. Shear shifts the points of a shape away from a set point. In the example with rectangle, two point of the rectangle are shifted while the other two points stay in place. This creates a visual effect where the shape appear to be bending around a point. Shear is applied with the shearX or shearY function.

function setup() { createCanvas(640, 360); } function draw() { background(220); translate(width/2, height/2); var s1 = map(mouseX, 0, width, 0, HALF_PI); var s2 = map(mouseY, 0, height, 0, HALF_PI); push(); shearX(s1); ellipse(0, 0, 100); pop(); shearY(s2); ellipse(0, 0, 100); }

push & pop

In p5, transformations accumulate as they are added, so if you want to translate multiple shapes from different location, you may need to use multiple transformations.

p5 has two functions that make it possible to do multiple transformations in one sketch: push and pop.

push() saves the current transform (any rotation or translation), and pop() returns it to the saved state. Usually we want to save the transform at the original state, starting with 0,0 in the upper left, and no rotation.

function setup() { createCanvas(640, 360); background(220); push(); // save default origin and rotation translate(width/2, height/2); fill(0); ellipse(0, 0, 10); // origin point // rects fill(255); rotate(PI/16); rect(0, 0, 40, 40); rotate(PI/16); rect(0, 0, 40, 40); rotate(PI/16); rect(0, 0, 40, 40); pop(); // return to saved state fill(0); ellipse(0, 0, 10); // origin point // circles fill(255); ellipse(100, 100, 40); rotate(PI/16); ellipse(100, 100, 40); rotate(PI/16); ellipse(100, 100, 40); }

Animating with transformation

Using transformation functions can add some new effects to our animations.

function draw() { background(220); translate(width/2, height/2); var r = frameCount / 1000 * PI; rotate(r); rect(0, 0, 100, 100); }
function setup() { createCanvas(640, 360); textSize(100); textFont('Comic Sans MS'); textAlign(CENTER, CENTER); fill('plum'); } function draw() { background(220); translate(width/2, height/2); var r = frameCount / 1000 * PI; shearX(r); text('MMP 210', 0, 0); }