We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpOpenGL and 3D Libraries › angle between 2 vectors
Page Index Toggle Pages: 1
angle between 2 vectors (Read 4451 times)
angle between 2 vectors
Jun 3rd, 2008, 8:48pm
 
hi all,

my goal is to get the angle between 2 vectors for use with rotate functions in processing. now, heres the good news - i figured out how to do calculation (see the getAngleX() etc functions in Vector3D.java). in theory, at least. but it wont work with processing matrix, whysoever. any hints? really starts to bother me. the angle between 2 vectors is the cross product divided by the magnitude of those two lines ( a * b / | a * b |). how to get just the rotation values of the angle between those two vectors in relation to the origin (0,0,0) ? its so frgn bad, cant figure it out. any help would be highly appreciated!

c

heres the code split in several messages. it does something, namely drawing two vertices in space and a not-really-correct-drawing of a rectangle..

angle between 2 vectors (code part 1)
Reply #1 - Jun 3rd, 2008, 8:48pm
 
import processing.opengl.*;
/*
cos alpha = a * b / |a * b|;
alpha = acos( a * b / |a * b| );
*/
Vector3D v0, v1, v2, v3;
float SIZE = 40;
float dx;
float dy;
float rx;
float ry;

void setup(){

 size(800, 600, OPENGL);
 smooth();
 rectMode(CENTER);

 v0 = new Vector3D(0,0,0);
 v1 = new Vector3D(random(200), random(200), random(200));
 v2 = new Vector3D(random(200), random(200), random(200));
 
 Vector3D t1 = Vector3D.sub(v0, v1);
 Vector3D t2 = Vector3D.sub(v2, v1);
 
 v3 =  Vector3D.sub(t1, t2);
 
}

void draw(){

 background(255);
 stroke(0);
 pushMatrix();
 translate(width/2,height/2,0);
 rotation();

 line(v0.x,v0.y,v0.z, v1.x, v1.y, v1.z);
 line(v1.x, v1.y, v1.z, v2.x, v2.y, v2.z);

 pushMatrix();
 translate(v1.x, v1.y, v1.z);
 rotateX(v3.getAngleX()); // println(v1.getAngleZ());
 rotateY(v3.getAngleY());
 rotateZ(v3.getAngleZ());
 
 rect(0,0, SIZE, SIZE);
 popMatrix();
 
 popMatrix();

}

void drawVector(){

}

void drawPlane(){

}

void rotation(){

 dx = (mouseY - height/2) * 0.01;
 dy = (mouseX - width/2) * 0.01;  
 
 rx+=(dx-rx) * 0.1;
 ry+=(dy-ry) * 0.1;  
 
 rotateY(rx);
 rotateZ(ry);
}
angle between 2 vectors (code part 2)
Reply #2 - Jun 3rd, 2008, 8:49pm
 
public class Vector3D {
 /**
  * The x component of the vector.
  */
 public float x;
 /**
  * The y component of the vector.
  */
 public float y;
 /**
  * The z component of the vector.
  */
 public float z;

 /**
  * Constructor for a 3D vector.
  *
  * @param  x_ the x coordinate.
  * @param  y_ the y coordinate.
  * @param  z_ the y coordinate.
  */

 public Vector3D(float x_, float y_, float z_) {
   x = x_;
   y = y_;
   z = z_;
 }

 /**
  * Constructor for a 2D vector: z coordinate is set to 0.
  *
  * @param  x_ the x coordinate.
  * @param  y_ the y coordinate.
  */

 public Vector3D(float x_, float y_) {
   x = x_;
   y = y_;
   z = 0f;
 }

 /**
  * Constructor for an empty vector: x, y, and z are set to 0.
  */

 public Vector3D() {
   x = 0f;
   y = 0f;
   z = 0f;
 }

 public Vector3D(Vector3D v) {
   x = v.x;
   y = v.y;
   z = v.z;
 }

 /**
  * Set the x coordinate.
  *    
  *  @param  x_ the x coordinate.
  */

 public void setX(float x_) {
   x = x_;
 }

 /**
  * Set the y coordinate.
  *    
  *  @param  y_ the y coordinate.
  */
 public void setY(float y_) {
   y = y_;
 }

 /**
  * Set the z coordinate.
  *    
  *  @param  z_ the z coordinate.
  */
 public void setZ(float z_) {
   z = z_;
 }

 /**
  * Set x,y, and z coordinates.
  *    
  *  @param  x_ the x coordinate.
  *  @param  y_ the y coordinate.
  *  @param  z_ the z coordinate.
  */
 public void setXYZ(float x_, float y_, float z_) {
   x = x_;
   y = y_;
   z = z_;
 }

 /**
  * Set x,y, and z coordinates from a Vector3D object.
  *    
  *  @param  v the Vector3D object to be copied
  */
 public void setXYZ(Vector3D v) {
   x = v.x;
   y = v.y;
   z = v.z;
 }

 /**
  * Calculate the magnitude (length) of the vector
  * @return      the magnitude of the vector    
  */
 public float magnitude() {
   return (float) Math.sqrt(x*x + y*y + z*z);
 }

 /**
  * Copy the vector
  * @return      a copy of the vector  
  */
 public Vector3D copy() {
   return new Vector3D(x,y,z);
 }

 /**
  * Copy the vector
  * @param      v the vector to be copied  
  * @return      a copy of the vector  
  */
 public static Vector3D copy(Vector3D v) {
   return new Vector3D(v.x, v.y,v.z);
 }
angle between 2 vectors (code part 3)
Reply #3 - Jun 3rd, 2008, 8:51pm
 
/**
  * Add a vector to this vector
  * @param      v the vector to be added  
  */
 public void add(Vector3D v) {
   x += v.x;
   y += v.y;
   z += v.z;
 }

 /**
  * Subtract a vector from this vector
  * @param      v the vector to be subtracted  
  */
 public void sub(Vector3D v) {
   x -= v.x;
   y -= v.y;
   z -= v.z;
 }

 /**
  * Multiply this vector by a scalar
  * @param      n the value to multiply by
  */
 public void mult(float n) {
   x *= n;
   y *= n;
   z *= n;
 }

 /**
  * Divide this vector by a scalar
  * @param      n the value to divide by
  */
 public void div(float n) {
   x /= n;
   y /= n;
   z /= n;
 }


 /**
  * Calculate the dot product with another vector
  * @return  the dot product
  */
 public float dot(Vector3D v) {
   float dot = x*v.x + y*v.y + z*v.z;
   return dot;
 }

 /**
  * Calculate the cross product with another vector
  * @return  the cross product
  */
 public Vector3D cross(Vector3D v) {
   float crossX = y * v.z - v.y * z;
   float crossY = z * v.x - v.z * x;
   float crossZ = x * v.y - v.x * y;
   return(new Vector3D(crossX,crossY,crossZ));
 }

 /**
  * Normalize the vector to length 1 (make it a unit vector)
  */
 public void normalize() {
   float m = magnitude();
   if (m > 0) {
     div(m);
   }
 }

 /**
  * Limit the magnitude of this vector
  * @param max the maximum length to limit this vector
  */
 public void limit(float max) {
   if (magnitude() > max) {
     normalize();
     mult(max);
   }
 }

 /**
  * Calculate the angle of rotation for this vector (only 2D vectors)
  * @return the angle of rotation
  */
 public float heading2D() {
   float angle = (float) Math.atan2(-y, x);
   return -1*angle;
 }

 /**
  * Rotates a 2D Vector
  * @param theta, angle in radians to rotate vector
  */
 public void rotate2D(float theta) {
   float currentTheta = heading2D();
   float mag = magnitude();
   currentTheta += theta;
   x = (float) (mag*Math.cos(currentTheta));
   y = (float) (mag*Math.sin(currentTheta));
 }


 /**
  * Add two vectors
  * @param      v1 a vector
  * @param v2 another vector  
  * @return a new vector that is the sum of v1 and v2  
  */
 public static Vector3D add(Vector3D v1, Vector3D v2) {
   Vector3D v = new Vector3D(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z);
   return v;
 }

 /**
  * Subtract one vector from another
  * @param      v1 a vector
  * @param v2 another vector  
  * @return a new vector that is v1 - v2
  */
 public static Vector3D sub(Vector3D v1, Vector3D v2) {
   Vector3D v = new Vector3D(v1.x - v2.x,v1.y - v2.y,v1.z - v2.z);
   return v;
 }

 /**
  * Divide a vector by a scalar
  * @param      v1 a vector
  * @param n scalar
  * @return a new vector that is v1 / n
  */
 public static Vector3D div(Vector3D v1, float n) {
   Vector3D v = new Vector3D(v1.x/n,v1.y/n,v1.z/n);
   return v;
 }

 /*
 public static Vector3D div(Vector3D v1, Vector3D v2) {
  Vector3D v = new Vector3D(v1.x/v2.x,v1.y/v2.y,v1.z/v2.z);
  return v;
  }
  */

 /**
  * Multiply a vector by a scalar
  * @param      v1 a vector
  * @param n scalar
  * @return a new vector that is v1 * n
  */
 public static Vector3D mult(Vector3D v1, float n) {
   Vector3D v = new Vector3D(v1.x*n,v1.y*n,v1.z*n);
   return v;
 }
angle between 2 vectors (code part 4)
Reply #4 - Jun 3rd, 2008, 8:52pm
 
/**
  * Rotates a 2D Vector
  * @param theta, angle in radians to rotate vector
  * @return a new Vector object, rotated by theta
  */
 public static Vector3D rotate2D(Vector3D v, float theta) {
   // What is my current heading
   float currentTheta = v.heading2D();
   // What is my current speed
   float mag = v.magnitude();
   // Turn me
   currentTheta += theta;
   // Look, polar coordinates to cartesian!!
   Vector3D newV = new Vector3D((float) (mag*Math.cos(currentTheta)),(float) (mag*Math.cos(currentTheta)));
   return  newV;
 }

 /**
  * Calculate the Euclidean distance between two points (considering a point as a vector object)
  * @param      v1 a vector
  * @param v2 another vector
  * @return the Euclidean distance between v1 and v2
  */
 public static float distance (Vector3D v1, Vector3D v2) {
   float dx = v1.x - v2.x;
   float dy = v1.y - v2.y;
   float dz = v1.z - v2.z;
   return (float) Math.sqrt(dx*dx + dy*dy + dz*dz);
 }

 /**
  * Calculate the angle between two vectors, using the dot product
  * @param      v1 a vector
  * @param v2 another vector
  * @return the angle between the vectors
  */
 public static float angleBetween(Vector3D v1, Vector3D v2) {
   float dot = v1.dot(v2);
   float theta = (float) Math.acos(dot / (v1.magnitude() * v2.magnitude()));
   return theta;
 }

 /**
  * Calculate the angle between two vectors dependant to origin 0,1,0
  *
  *
  *
  */
 public static Vector3D angleBetween3D(Vector3D v, Vector3D w){

   Vector3D v1 = new Vector3D(v);
   Vector3D v2 = new Vector3D(w);
   Vector3D v3 = new Vector3D( Vector3D.add(v,w) );

   // v1.normalize();
   // v2.normalize();
   v3.normalize();
   return v3;

   //float betrag = v3.magnitude();
   // Vector3D r = Vector3D.div(Vector3D.add(v1,v2), betrag);

   // return r;

 }

 /**
  * Returning the angle between coordinate system axis' and a vector
  *
  *
  *
  */
 public float getAngleX() {
   return (float)  Math.acos(x/Math.sqrt(Math.pow(x-1,2)+Math.pow(y,2)+Math.pow(z,2)));
 }
 public float getAngleY() {
   return (float)  Math.acos(y/Math.sqrt(Math.pow(x,2)+Math.pow(y-1,2)+Math.pow(z,2)));
 }
 public float getAngleZ() {
   return (float)  Math.acos(z/Math.sqrt(Math.pow(x,2)+Math.pow(y,2)+Math.pow(z-1,2)));
 }
}
angle between 2 vectors (1st solution)
Reply #5 - Jun 4th, 2008, 5:15pm
 
ok. now heres an answer. basically it is a simple thing to do to get a plane that bisects the angle between two vectors. the tricky part would have been for me to figure out how to get actually the rotation as three values for that plane/matrix so i can use it onwards. so this is it, i guess - get the rotation of a plane..

now heres a solution: given two vectors, you can get the angle bisector by simple addition of their normalized copies. that is the first axis you need. the second one is the cross product, getting a perpendicular vector to the plane those two basic vectors create. you can then just normalize the two new vectors (angle bisector and perpendicular vector) and multiply and offset them, so you end up with that plane bisecting the two vectors (i did not post the vector class again):

import processing.opengl.*;

Vector3D v0;
Vector3D v1;
Vector3D v2;
Vector3D v3;
Vector3D v4;
Vector3D v5;
Vector3D v6;

float dx;
float dy;
float rx;
float ry;

float ax;
float ay;
float az;


void setup(){

 size(800, 600, OPENGL);
 smooth();
 rectMode(CENTER);

 float r1 = random(300);
 float r2 = random(300);
 float r3 = random(300);
 
 v0 = new Vector3D(1,1,1);
 
 v1 = new Vector3D(r1, r2, 10);
 v2 = new Vector3D(r1, 10, r3);
 
 Vector3D tv1 = v1.copy();
 tv1.normalize();
 
 Vector3D tv2 = v2.copy();
 tv2.normalize();
 
 v3 = Vector3D.add(tv1, tv2);
 v3.normalize();
 v3.mult(100);
 
 v4 = v1.cross(v2);
 v4.normalize();
 v4.mult(100);
 
}

void draw(){

 background(255);

 pushMatrix();
 translate(width/2, height/2, 0);
 rotation();
 
 stroke(0);
 line(0,0,0, v1.x, v1.y, v1.z);
 line(0,0,0, v2.x, v2.y, v2.z);
 
 /*
 
 // angle bisector
 stroke(200,0,0);
 line(0,0,0, v3.x, v3.y, v3.z);
 
 // lotrechte
 stroke(0,200,0);
 line(0,0,0, v4.x,v4.y,v4.z);
 
 */
 
 // lotrechte und winkelhalbierende geben die beidengeraden
 // des winkelhalbierenden rechtecks:
 pushMatrix();
 drawRect(v3, v4, true);
 popMatrix();
 
 popMatrix();

}

void drawRect(Vector3D v1, Vector3D v2, boolean centered){
 
 float offsetx, offsety, offsetz;
 offsetx = 0; offsety = 0; offsetz = 0;
 if(centered){
   offsetx = -(v1.x+v2.x)/2;
   offsety = -(v1.y+v2.y)/2;
   offsetz = -(v1.z+v2.z)/2;
 }
 
 beginShape();
 vertex(offsetx,offsety,offsetz);
 vertex(v1.x+offsetx, v1.y+offsety, v1.z+offsetz);
 vertex(v2.x+v1.x+offsetx, v2.y+v1.y+offsety, v2.z+v1.z+offsetz);
 vertex(v2.x+offsetx, v2.y+offsety, v2.z+offsetz);
 vertex(offsetx,offsety,offsetz);
 endShape();  
 
}

void rotation(){

 dx = (mouseY - height/2) * 0.01;
 dy = (mouseX - width/2) * 0.01;  

 rx+=(dx-rx) * 0.1;
 ry+=(dy-ry) * 0.1;  

 rotateY(rx);
 rotateZ(ry);
}

Page Index Toggle Pages: 1