Shrinking Spiral Square - Processing - processing

I'm trying as a task given to create a pattern of 20 squares that are 500x500px and in the middle of a screen size of 600x600px. With each one slightly smaller and rotated by 1o and each one with an alpha value of 40. I have attached an image what it needs to look like. I have no idea how to start it and may need a lot of assistance. Thanks in advance.

Draw the rectangles by using the function rect in a loop.
Set the fill color with an alpha channel. Since the default belnd mode is BLEND, the objects are blendend. This means, if more objects are drawn at the same place, then the scene will become more saturated at this parts.
Use scale and rotate to consecutively change the model matrix, but reset the model matrix at the begin of each loop iteration by resetMatrix.
The amount of the angle of rotation does not linear increase, but it increases more as the index i increases.
void setup(){
size(500,500);
}
float angle_degree = 1.1;
float scale_percent = 3.7;
float size = 400;
void draw() {
background(255);
stroke(0);
fill(0,0,255,40);
float current_ang = 0;
float current_scale = 1.0;
for( int i=0;i < 20; ++i ) {
resetMatrix();
translate(width/2, height/2);
scale(current_scale);
rotate(current_ang);
rect(-size/2, -size/2, size, size);
current_scale -= scale_percent / 100.0;
current_ang -= i * angle_degree * PI/180.0;
}
}
Preview:

Related

Processing: Efficiently create uniform grid

I'm trying to create a grid of an image (in the way one would tile a background with). Here's what I've been using:
PImage bgtile;
PGraphics bg;
int tilesize = 50;
void setup() {
int t = millis();
fullScreen(P2D);
background(0);
bgtile = loadImage("bgtile.png");
int bgw = ceil( ((float) width) / tilesize) + 1;
int bgh = ceil( ((float) height) / tilesize) + 1;
bg = createGraphics(bgw*tilesize,bgh*tilesize);
bg.beginDraw();
for(int i = 0; i < bgw; i++){
for(int j = 0; j < bgh; j++){
bg.image(bgtile, i*tilesize, j*tilesize, tilesize, tilesize);
}
}
bg.endDraw();
print(millis() - t);
}
The timing code says that this takes about a quarter of a second, but by my count there's a full second once the window opens before anything shows up on screen (which should happen as soon as draw is first run). Is there a faster way to get this same effect? (I want to avoid rendering bgtile hundreds of times in the draw loop for obvious reasons)
One way could be to make use of the GPU and let OpenGL repeat a texture for you.
Processing makes it fairly easy to repeat a texture via textureWrap(REPEAT)
Instead of drawing an image you'd make your own quad shape and instead of calling vertex(x, y) for example, you'd call vertex(x, y, u, v); passing texture coordinates (more low level info on the OpenGL link above). The simple idea is x,y would control the geometry on screen and u,v would control how the texture is applied to the geometry.
Another thing you can control is textureMode() which allows you control how you specify the texture coordinates (U, V):
IMAGE mode is the default: you use pixel coordinates (based on the dimensions of the texture)
NORMAL mode uses values between 0.0 and 1.0 (also known as normalised values) where 1.0 means the maximum the texture can go (e.g. image width for U or image height for V) and you don't need to worry about knowing the texture image dimensions
Here's a basic example based on the textureMode() example above:
PImage img;
void setup() {
fullScreen(P2D);
noStroke();
img = loadImage("https://processing.org/examples/moonwalk.jpg");
// texture mode can be IMAGE (pixel dimensions) or NORMAL (0.0 to 1.0)
// normal means 1.0 is full width (for U) or height (for V) without having to know the image resolution
textureMode(NORMAL);
// this is what will make handle tiling for you
textureWrap(REPEAT);
}
void draw() {
// drag mouse on X axis to change tiling
int tileRepeats = (int)map(constrain(mouseX,0,width), 0, width, 1, 100);
// draw a textured quad
beginShape(QUAD);
// set the texture
texture(img);
// x , y , U , V
vertex(0 , 0 , 0 , 0);
vertex(width, 0 , tileRepeats, 0);
vertex(width, height, tileRepeats, tileRepeats);
vertex(0 , height, 0 , tileRepeats);
endShape();
text((int)frameRate+"fps",15,15);
}
Drag the mouse on the Y axis to control the number of repetitions.
In this simple example both vertex coordinates and texture coordinates are going clockwise (top left, top right, bottom right, bottom left order).
There are probably other ways to achieve the same result: using a PShader comes to mind.
Your approach caching the tiles in setup is ok.
Even flattening your nested loop into a single loop at best may only shave a few milliseconds off, but nothing substantial.
If you tried to cache my snippet above it would make a minimal difference.
In this particular case, because of the back and forth between Java/OpenGL (via JOGL), as far as I can tell using VisualVM, it looks like there's not a lot of room for improvement since simply swapping buffers takes so long (e.g. bg.image()):
An easy way to do this would be to use processing's built in get(); which saves a PImage of the coordinates you pass, for example: PImage pic = get(0, 0, width, height); will capture a "screenshot" of your entire window. So, you can create the image like you already are, and then take a screenshot and display that screenshot.
PImage bgtile;
PGraphics bg;
PImage screenGrab;
int tilesize = 50;
void setup() {
fullScreen(P2D);
background(0);
bgtile = loadImage("bgtile.png");
int bgw = ceil(((float) width) / tilesize) + 1;
int bgh = ceil(((float) height) / tilesize) + 1;
bg = createGraphics(bgw * tilesize, bgh * tilesize);
bg.beginDraw();
for (int i = 0; i < bgw; i++) {
for (int j = 0; j < bgh; j++) {
bg.image(bgtile, i * tilesize, j * tilesize, tilesize, tilesize);
}
}
bg.endDraw();
screenGrab = get(0, 0, width, height);
}
void draw() {
image(screenGrab, 0, 0);
}
This will still take a little bit to generate the image, but once it does, there is no need to use the for loops again unless you change the tilesize.
#George Profenza's answer looks more efficient than my solution, but mine may take a little less modification to the code you already have.

How to create a sinusoidal wave of a line so that the start of the wave returns to being flat

I know how to create a sinusoidal movement with particles as per the code below. What I would like to do however is to create an effect which is more of a ripple along a string. The idea is that a wave moves along a string but the section that is not currently in a wave returns to the zero position and doesn't undergo a further wave- ie just one wave passing down the line.
How do I amend the sinusoidal movement below to achieve this?
int xspacing = 16; // How far apart should each horizontal location be spaced
int w; // Width of entire wave
float theta = 0.0; // Start angle at 0
float amplitude = 75.0; // Height of wave
float period = 500.0; // How many pixels before the wave repeats
float dx; // Value for incrementing X, a function of period and xspacing
float[] yvalues; // Using an array to store height values for the wave
void setup() {
size(640, 360);
w = width+16;
dx = (TWO_PI / period) * xspacing;
yvalues = new float[w/xspacing];
}
void draw() {
background(0);
calcWave();
renderWave();
}
void calcWave() {
// Increment theta (try different values for 'angular velocity' here
theta += 0.02;
// For every x value, calculate a y value with sine function
float x = theta;
for (int i = 0; i < yvalues.length; i++) {
yvalues[i] = sin(x)*amplitude;
x+=dx;
}
}
void renderWave() {
noStroke();
fill(255);
// A simple way to draw the wave with an ellipse at each location
for (int x = 0; x < yvalues.length; x++) {
ellipse(x*xspacing, height/2+yvalues[x], 16, 16);
}
}
I'm not totally sure exactly what you're going for. Drawing out some examples might help explain it better.
But the short answer to your question is: you'd change the height of the sin wave by modifying this line:
yvalues[i] = sin(x)*amplitude;
Right now every particle has the same amplitude, so it your wave has a uniform height. Instead, what you want to do is give each particle a different amplitude. Here's a very simple example:
yvalues[i] = sin(x) * x * 10;
This causes particles towards the left of the screen to have a smaller amplitude, and particles at the right of the screen to have a larger amplitude. In other words, the wave starts out flat and gets larger as it moves to the right.
What I would probably do is create a Particle class that encapsulates each particle's position, movement, and amplitude. Then I'd decrease the amplitude of each particle over time, maybe increasing it when the user clicks (or whatever event you want to spawn your waves).
Shameless self-promotion: I've written a tutorial on creating classes in Processing available here.

animating sine waves in processing

how do I animate the sin lines in the following code to move along the y-axis, to somehow look more like moving water waves?
-if you take out the velocity and acceleration codes you will see what I was trying to work with
float scaleVal = 6.0;
float angleInc = 0.19;
float velocity=0.0;
float acceleration=0.01;
void setup(){
size(750,750);
stroke(255);
}
void draw(){
background (0);
float angle=0.0;
for (int offset = -10; offset < width+10; offset += 10) {
for (int y = 1; y <= height; y += 3) {
float x = offset + (sin(angle) * scaleVal);
line(x, y, x, y+2);
angle += angleInc;
velocity += acceleration;
y += velocity;
}
angle += PI;
}
}
Try using sin() to change the y position instead of x.
The x position can simply increment.
The math may be daunting, but it gets fun once you get the hang of it.
Imagine going around a circle with the radius of 1.0 in a cartesian coordinate system (0 is centre , x and y increase to the right and down and decrease towards left and top):
Let's say you start at the top, the highest value, the length radius of your circle (1.0).
As you decrease the angle, the x move to the left, but the y will go towards the centre( 0.0 )
then x will increase as it gets close to the centre and y will drop to bottom of the circle (-1.0)
then x will keep increasing until it reaches the right edge of the circle and the y value will increase and reach the vertical centre (0.0)
finally the x will decrease until it reaches the horizontal centre and y will increase and reach back to the top of the circle (1.0)
This image explains it pretty well:
Essentially it's like a converter: you plug in an angle from 0 to 360 degrees or TWO_PI radians (as sin works with angles in radians) and you get back a value between -1.0 and 1.0.
If you want to draw a sine wave, you have to draw multiple points:
the x position will increase value directly
the y position will increase the angle, but use the result of the sin() function to obtain a value that goes up and down.
The last thing to do is multiple the result of the sin() function by a larger number to essentially scale the sine wave (from -1.0 to 1.0) to a size more appropate for the screen.
Here's a quick commented demo you can use the mouse position to play with:
function setup(){
createCanvas(640,100);
}
function draw(){
background(255);
var numberOfPoints = 1+(mouseX/2);
//how often apart will the points be
var widthPerPoint = width / numberOfPoints;
//how much will the angle change from one point to another
var anglePerPoint = TWO_PI/numberOfPoints;
var waveHeight = 25;
for(var i = 0; i < numberOfPoints; i++){
var x = i * widthPerPoint;
var y = sin(anglePerPoint * i) * waveHeight;
ellipse(x,50 + y,5,5);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
The gist of it is this line:
var y = sin(anglePerPoint * i) * waveHeight;
which can be broken down to:
//increment the angle
var incrementedAngle = anglePerPoint * i;
//compute sine (-1.0,1.0)
var sine = sin(incrementedAngle);
//scale sine result
var waveY = sine * waveHeight;
Once you can draw a static sine wave, it's pretty easy to animate: to the angle increment at each point you add an increasing value. This increases the angle and essentially goes around the circle (TWO_PI) for you.
You can create your own variable to increase at your own rate or you
can easily use an increasing value based on time(millis()) or frame(frameCount) which you can scale down (divide by a large number...or better yet multiple by a small fractional number):
function setup(){
createCanvas(640,100);
}
function draw(){
background(255);
var numberOfPoints = 1+(mouseX/2);
//how often apart will the points be
var widthPerPoint = width / numberOfPoints;
//how much will the angle change from one point to another
var anglePerPoint = TWO_PI/numberOfPoints;
var waveHeight = 25;
for(var i = 0; i < numberOfPoints; i++){
var x = i * widthPerPoint;
var y = sin(anglePerPoint * i + frameCount * 0.01) * waveHeight;
ellipse(x,50 + y,5,5);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
Hopefully the animation and simple demos above help illustrate the point.
In even simpler terms, it's a bit of an illustion: you draw points that only move up and down, but each point use an increasing angle along the circle.
Have a look at Reuben Margolin's kinectic sculpture system demo:
(I recommend checking out the whole PopTech talk: it's inspiring)
You should have a look at the Processing SineWave example as well.
Here's a more complex encapsulating the notions in a resuable function to draw multiple waves to hint at an atmospheric perspective:
int numWaves = 5;
void setup(){
size(400,400);
noStroke();
}
void draw(){
background(255);
for(int i = 0 ; i < numWaves; i++){
fill(30,120,180,map(i,0,numWaves-1,192,32));
drawSineWave(HALF_PI,0.00025 * (i+1),50 + (10 * i),8,width,mouseY);
}
fill(255);
text("drag mouse x to change number of waves",10,height-10);
}
/*
* radians - how often does the wave cycle (larges values = more peaks)
* speed - how fast is the wave moving
* amplitude - how high is the wave (from centre point)
* detail - how many points are used to draw the wave (small=angled, many = smooth)
* y - y centre of the wave
*/
void drawSineWave(float radians,float speed,float amplitude,int detail,float size,float y){
beginShape();
vertex(0,height);//fix to bottom
//compute the distance between each point
float xoffset = size / detail;
//compute angle offset between each point
float angleIncrement = radians / detail;
//for each point
for(int i = 0 ; i <= detail; i++){
//compute x position
float px = xoffset * i;
//use sine function compute y
//millis() * speed is like an ever increasing angle
//to which we add the angle increment for each point (so the the angle changes as we traverse x
//the result of sine is a value between -1.0 and 1.0 which we multiply to the amplitude (height of the wave)
//finally add the y offset
float py = y + (sin((millis() * speed) + angleIncrement * i) * amplitude);
//add the point
vertex(px,py);
}
vertex(size,height);//fix to bottom
endShape();
}
void mouseDragged(){
numWaves = 1+(int)mouseX/40;
}
Which you can also run bellow:
var numWaves = 5;
function setup(){
createCanvas(400,400);
noStroke();
}
function draw(){
background(255);
for(var i = 0 ; i < numWaves; i++){
fill(30,120,180,map(i,0,numWaves-1,192,32));
drawSineWave(HALF_PI,0.00025 * (i+1),50 + (10 * i),8,width,mouseY);
}
fill(255);
text("drag mouse x to change number of waves",10,height-10);
}
/*
* radians - how often does the wave cycle (larges values = more peaks)
* speed - how fast is the wave moving
* amplitude - how high is the wave (from centre point)
* detail - how many points are used to draw the wave (small=angled, many = smooth)
* y - y centre of the wave
*/
function drawSineWave(radians,speed,amplitude,detail,size,y){
beginShape();
vertex(0,height);//fix to bottom
//compute the distance between each point
var xoffset = size / detail;
var angleIncrement = radians / detail;
for(var i = 0 ; i <= detail; i++){
var px = xoffset * i;
var py = y + (sin((millis() * speed) + angleIncrement * i) * amplitude);
vertex(px,py);
}
vertex(size,height);//fix to bottom
endShape();
}
function mouseDragged(){
numWaves = ceil(mouseX/40);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.4/p5.min.js"></script>
The only other suggestion I have, in terms of rendering, it to have play with beginShape(). Rather than having to worry about where to draw each line, simply pass a bunch of points(via vertex(x,y)) in between beginShape()/endShape() calls and let Processing connect the dots for you.
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for more specific "I tried X, expected Y, but got Z instead" type questions. That being said, I'll try to help in a general sense.
If you want to animate something going up and down, you have to modify its Y position over time.
One approach is to use the sin() or cos() functions to come up with a value that alternates between -1 and 1, which you can then multiply by a height and add to a center:
void setup() {
size(100, 200);
}
void draw() {
background (0);
float centerY = height/2;
float waveHeight = 75;
float input = frameCount/10.0;
float ballY = centerY+sin(input)*waveHeight;
ellipse(width/2, ballY, 10, 10);
}
Another approach is to keep track of the position and speed yourself. When the position reaches a min or max, just reverse the speed. Something like this:
float ballY = 100;
float ySpeed = 1;
void setup() {
size(100, 200);
}
void draw() {
background (0);
ballY += ySpeed;
if(ballY < 0 || ballY > height){
ySpeed *= -1;
}
ellipse(width/2, ballY, 10, 10);
}
You could also use the lerp() function. The point is that there are a million different ways to do this. The best thing you can do is to try something and post an MCVE if you get stuck. Good luck.

Calculate ellipse size in relation to distance from center point

I want to achieve a slow fade in size on every collapse into itself. In other words, when the circle is at its biggest, the ellipses will be at the largest in size and conversely the opposite for the retraction. So far I am trying to achieve this affect by remapping the cSize from the distance of the center point, but somewhere along the way something is going wrong. At the moment I am getting a slow transition from small to large in ellipse size, but the inner ellipses are noticeably larger. I want an equal distribution of size amongst all ellipses in relation to center point distance.
I've simplified the code down to 4 ellipses rather than an array of rows of ellipses in order to hopefully simplify this example. This is done in the for (int x = -50; x <= 50; x+=100).
I've seen one or two examples that slightly does what I want, but is more or less static. This example is kind of similar because the ellipse size gets smaller or larger in relation to the mouse position
Distance2D
Here is an additional diagram of the grid of ellipses I am trying to create, In addition, I am trying to scale that "square grid" of ellipses by a center point.
Multiple ellipses + Scale by center
Any pointers?
float cSize;
float shrinkOrGrow;
void setup() {
size(640, 640);
noStroke();
smooth();
fill(255);
}
void draw() {
background(#202020);
translate(width/2, height/2);
if (cSize > 10) {
shrinkOrGrow = 0;
} else if (cSize < 1 ) {
shrinkOrGrow = 1;
}
if (shrinkOrGrow == 1) {
cSize += .1;
} else if (shrinkOrGrow == 0) {
cSize -= .1;
}
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
float d = dist(x, y, 0, 0);
float fromCenter = map(cSize, 0, d, 1, 10);
pushMatrix();
translate(x, y);
rotate(radians(d + frameCount));
ellipse(x, y, fromCenter, fromCenter);
popMatrix();
}
}
}
The values you're passing into the map() function don't make a lot of sense to me:
float fromCenter = map(cSize, 0, d, 1, 100);
The cSize variable bounces from 1 to 10 independent of anything else. The d variable is the distance of each ellipse to the center of the circle, but that's going to be static for each one since you're using the rotate() function to "move" the circle, which never actually moves. That's based only on the frameCount variable, which you never use to calculate the size of your ellipses.
In other words, the position of the ellipses and their size are completely unrelated in your code.
You need to refactor your code so that the size is based on the distance. I see two main options for doing this:
Option 1: Right now you're moving the circles on screen using the translate() and rotate() functions. You could think of this as the camera moving, not the ellipses moving. So if you want to base the size of the ellipse on its distance from some point, you have to get the distance of the transformed point, not the original point.
Luckily, Processing gives you the screenX() and screenY() functions for figuring out where a point will be after you transform it.
Here's an example of how you might use it:
for (int x = -50; x <= 50; x+=100) {
for (int y = -50; y <= 50; y+=100) {
pushMatrix();
//transform the point
//in other words, move the camera
translate(x, y);
rotate(radians(frameCount));
//get the position of the transformed point on the screen
float screenX = screenX(x, y);
float screenY = screenY(x, y);
//get the distance of that position from the center
float distanceFromCenter = dist(screenX, screenY, width/2, height/2);
//use that distance to create a diameter
float diameter = 141 - distanceFromCenter;
//draw the ellipse using that diameter
ellipse(x, y, diameter, diameter);
popMatrix();
}
}
Option 2: Stop using translate() and rotate(), and use the positions of the ellipses directly.
You might create a class that encapsulates everything you need to move and draw an ellipse. Then just create instances of that class and iterate over them. You'd need some basic trig to figure out the positions, but you could then use them directly.
Here's a little example of doing it that way:
ArrayList<RotatingEllipse> ellipses = new ArrayList<RotatingEllipse>();
void setup() {
size(500, 500);
ellipses.add(new RotatingEllipse(width*.25, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.25));
ellipses.add(new RotatingEllipse(width*.75, height*.75));
ellipses.add(new RotatingEllipse(width*.25, height*.75));
}
void draw() {
background(0);
for (RotatingEllipse e : ellipses) {
e.stepAndDraw();
}
}
void mouseClicked() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
void mouseDragged() {
ellipses.add(new RotatingEllipse(mouseX, mouseY));
}
class RotatingEllipse {
float rotateAroundX;
float rotateAroundY;
float distanceFromRotatingPoint;
float angle;
public RotatingEllipse(float startX, float startY) {
rotateAroundX = (width/2 + startX)/2;
rotateAroundY = (height/2 + startY)/2;
distanceFromRotatingPoint = dist(startX, startY, rotateAroundX, rotateAroundY);
angle = atan2(startY-height/2, startX-width/2);
}
public void stepAndDraw() {
angle += PI/64;
float x = rotateAroundX + cos(angle)*distanceFromRotatingPoint;
float y = rotateAroundY + sin(angle)*distanceFromRotatingPoint;
float distance = dist(x, y, width/2, height/2);
float diameter = 50*(500-distance)/500;
ellipse(x, y, diameter, diameter);
}
}
Try clicking or dragging in this example. User interaction makes more sense to me using this approach, but which option you choose really depends on what fits inside your head the best.

How to draw string objects at an angle in Processing?

The code below draws a spiral using objects from a string array. Everything is fine, except that I would like the text objects to be drawn at a roughly 45 degree angle at each instance (based on the current x, y coordinates in the code below) rather than being drawn horizontally (when the text is horizontally drawn, it naturally overlaps with other text at concentrated points along the top & bottom of the curve). I researched some methods, but I'm still very new to all of this, and potential solutions have all evaded me.
String example = "";
String[] wordSet = split(example, " ");
float x, y;
float angle = 0;
float radiusSpiralLine = 10;
size (800, 800);
translate(width/2, height/2);
background(#ffffff);
smooth();
fill(0);
for (int i = 0; i < wordSet.length; i++) {
angle += .05;
radiusSpiralLine += .5;
x = cos(angle) * radiusSpiralLine;
y = sin(angle) * radiusSpiralLine;
textSize(9);
text(wordSet[i], x, y);
}
Here is tutorial to very similar problem. In basic you need to store projection matrix by pushMatrix() then translate and rotate according to position of letter on curve and then restore matrix by popMatrix(). I don't know how exactly do you want to rotate you text but just fold round your text() function like this maybe it will help you:
pushMatrix();
translate(x, y);
rotate(angle);
text(wordSet[i], 0, 0);
popMatrix();
First, you should start getting in the habit of wrapping code in the setup() and draw() functions. Since you're drawing a static image you don't need the draw() function, but I think it's good practice to have those two.
Now, what you are doing now is simply translating the words by a very small amount. Do the math:
x = cos(angle) * radiusSpiralLine; //cos(.05)*.5 = .499
y = sin(angle) * radiusSpiralLine; //sin(.05)*.5 = .024
That means they move less than a pixel, and they're not rotating at all.
What you need is your good ol' friend, the rotate() function.
Let's re-write code:
String example = "These are a bunch of words going around!";
String[] wordSet = split(example, " ");
float x, y;
float angle = 0;
void setup() {
size (800, 800);
background(#ffffff);
smooth();
fill(0);
pushMatrix();
translate(width/2, height/2); //Translate when you need to translate, not before
for (int i = 0; i < wordSet.length; i++) {
angle = PI/5; //Our good friends, radians
textSize(20); //What is this, text for ants? Change to 20
rotate(angle);
text(wordSet[i], 20, 0);
}
popMatrix();
}
void draw() {
}
First notice, the setup() and draw(). I like them there. It looks nicer, I think.
A couple of important things to note.
The effects of rotate() and translate() are on the canvas are cumulative.
We could have had the same effect in different ways:
for (int i = 0; i < wordSet.length; i++) {
angle = PI/5;
textSize(20);
rotate(angle); //always rotating by PI/5 ON TOP of previous rotation
text(wordSet[i], 20, 0);
}
//Everything from now on will still be rotated, we don't want that!
Slightly better, but not there yet:
for (int i = 0; i < wordSet.length; i++) {
angle += PI/5; //constantly increasing the angle
textSize(20);
pushMatrix(); //push a new canvas on top of everything
rotate(angle); //rotate by angle (which increases every loop)
text(wordSet[i], 20, 0);
popMatrix(); //pop the rotated canvas out, go back to original canvas
} //Things won't be rotated, but they'll still be translated, since translate() is outside of pushMatrix and popMatrix
Hope this helps.

Resources