Praud
Praud

Reputation: 297

How to find angle between two vectors on canvas?

I need to find the angle between two vectors on my canvas. I have attached some examples below: enter image description here

enter image description here

Could you advise me some formula? I have problems with school math :)

Upvotes: 1

Views: 8155

Answers (4)

raksa
raksa

Reputation: 938

Old question. But I found good solution. Let say we have 4 points form 2 vectors. Points (P0, P1, P2, P3), then the angle of P0P1 and P2P3 is:

function angle2Vectors(ps) {
  const v1 = { x: ps[1].x - ps[0].x, y: ps[1].y - ps[0].y };
  const v2 = { x: ps[3].x - ps[2].x, y: ps[3].y - ps[2].y };
  const l1_l2 = len(ps[1], ps[0]) * len(ps[3], ps[2]);
  const v1_v2 = v1.x * v2.x + v1.y * v2.y;
  const cos = v1_v2 / (len(ps[1], ps[0]) * len(ps[3], ps[2]));
  const angCos = Math.acos(cos) * (180 / Math.PI);
  const _v1_v2_ = v1.x * v2.y - v2.x * v1.y;
  const sin = _v1_v2_ / l1_l2;
  const angSin = Math.asin(sin) * (180 / Math.PI);
  return angCos * Math.sign(angSin);
}

Upvotes: 1

Exodus 4D
Exodus 4D

Reputation: 2822

If you need 2D (z=0) and 3D support, you could use the Dot product

const dot = (p1, p2) => p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;

With a square magnitude (magSq), we can calc the magnitude: mag = Math.sqrt(magSq)

const magSq = ({x, y, z}) => x ** 2 + y ** 2 + z ** 2;
const mag = Math.sqrt(magSq(p));

Now we can calc the Dot product and "normalize" it afterwards. Now use acos() to get the angle:

const angle = Math.acos(dot(p1, p2) / Math.sqrt(magSq(p1) * magSq(p2)));

We could also use Math.hypot(), a dedicated JS function for mag:

const mag = (p) => Math.hypot(p.x, p.y, p.z);

… and get the angle:

const angle = Math.acos(dot(p1, p2) / (mag(p1) * mag(p2)));

Example:

let a = {x: 0, y: -6, z: 0};
let b = {x: 5, y: 2, z: 0}; // set z != 0 for 3D

let dot = (p1, p2)=>  p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
let magSq = ({x, y, z}) => x ** 2 + y ** 2 + z ** 2;

let angle1 = Math.acos(dot(a, b) / Math.sqrt(magSq(a) * magSq(b)));
console.log('1. Angle:', angle1);                                        // 1.9513027

// ... or
let mag = ({x, y, z}) => Math.hypot(x, y, z);

let angle2 = Math.acos(dot(a, b) / (mag(a) * mag(b)))
console.log('2. Angle:', angle2);                                        // 1.9513027

Upvotes: 3

obscure
obscure

Reputation: 12891

Basically you need to make the point which connects your two vectors the origin, where x=0 and y=0.

Take a look at this picture:

Now we can say that the x and y values of the points A, B and C are:

  • A = 0|0
  • B = 0|-6
  • C = 5|2

To calculate the arctangent of both we can utilize the Math.atan2() function. Please note that the first parameter for atan2 must be the y value.

var firstAngle = Math.atan2(-6, 0);
var secondAngle = Math.atan2(2, 5);

and get the difference of them by subtraction

var angle = secondAngle - firstAngle;

This will return a radian value you can convert to degrees like this:

angle = angle * 180 / Math.PI;

Upvotes: 7

Nik Vinter
Nik Vinter

Reputation: 145

First you'll need to normalize the two vectors.

Once that's done you can do

angle = arcos(v1•v2)

where "angle" is the angle you want to find, "arcos" is the inverse of cosine function and the "•" is the dot product operator

Be careful, this will return only the relative and raw angle. You won't be able to know which vector is on the left and which one is on the right.

Upvotes: 2

Related Questions