Feb 03, 2011

Rotate a Vector (Processing.js!)

The question of how to rotate a PVector object (the data of the vector itself, I’m not talking about rotating while drawing) came up in my nature of code course yesterday. To do this, you’ll need to convert the vector to polar coordinates (radius + angle), adjust the angle, and the convert it back to cartesian to solve for the components (x and y). A function would look something like:

// Rotate a vector in 2D
void rotate2D(PVector v, float theta) {
  // What's the magnitude?
  float m = v.mag();
  // What's the angle?
  float a = v.heading2D();
  
  // Change the angle
  a += theta;
  
  // Polar to cartesian for the new xy components
  v.x = m * cos(a);
  v.y = m * sin(a);
}

(Update thanks to Vilhelm’s comment below: You can also use a 2D rotation matrix!)

void rotate2D(PVector v, float theta) {
  float xTemp = v.x;
  v.x = v.x*cos(theta) - v.y*sin(theta);
  v.y = xTemp*sin(theta) + v.y*cos(theta);
}

Now, this is really just a ruse. A big excuse for me to figure out how to get a Processing example in a wordpress post using processing.js! I was able to do this fairly quickly with three quick steps:

1) Download processing.js 1.0.
2) Install wordpress processing.js plug-in.
3) Update the plug-in to use processing.js 1.0 (it hasn’t been yet). Follow these instructions.

And here it is!

And now the source:

// Rotate2D function
// Daniel Shiffman

void setup() {
  size(200,200);
  smooth();
}

void draw() {
  background(100);
  PVector xaxis = new PVector(75,0);
  float theta = map(mouseX,0,width,0,TWO_PI);
  rotate2D(xaxis,theta);
  drawVector(xaxis,width/2,height/2,1.0);
}

// Rotate a vector in 2D
void rotate2D(PVector v, float theta) {
  // What's the magnitude?
  float m = v.mag();
  // What's the angle?
  float a = v.heading2D();
  
  // Change the angle
  a += theta;
  
  // Polar to cartesian for the new xy components
  v.x = m * cos(a);
  v.y = m * sin(a);
}

// Renders a vector object 'v' as an arrow at a location xy
void drawVector(PVector v, float x, float y, float scayl) {
  pushMatrix();
  float arrowsize = 4;
  // Translate to location to render vector
  translate(x,y);
  stroke(255);
  // Vector heading to get direction (pointing up is a heading of 0)
  rotate(v.heading2D());
  // Scale it to be bigger or smaller if necessary
  float len = v.mag()*scayl;
  // Draw three lines to make an arrow
  line(0,0,len,0);
  line(len,0,len-arrowsize,+arrowsize/2);
  line(len,0,len-arrowsize,-arrowsize/2);
  popMatrix();
}