# determine collision angle on a rotating body

update: new diagram and updated description

I have a contact listener set up to try and determine the side that a collision happened at relative to the a bodies rotation. One way to solve this is to find the value of the yellow angle between the red and blue vectors drawn above. The angle can be found by taking the arc cosine of the dot product of the two vectors (Evan pointed this out). One of my points of confusion is the difference in domain of the atan2 function html canvas coordinates and the Box2d rotation information. I know I have to account for this somehow... SS below

questions:

• Does Box2D provide these angles more directly in the collision information?
• Am I even on the right track? If so, any hints?

I have the following javascript so far:

Ship.prototype.onCollide = function (other_ent,cx,cy) {

var pos = this.body.GetPosition();

//collision position relative to body
var d_cx = pos.x - cx;
var d_cy = pos.y - cy;

//length of initial vector
var len = Math.sqrt(Math.pow(pos.x -cx,2) + Math.pow(pos.y-cy,2));

//body angle - can over rotate hence mod 2*Pi
var ang = this.body.GetAngle() % (Math.PI * 2);

//vector representing body's angle - same magnitude as the first
var b_vx = len * Math.cos(ang);
var b_vy = len * Math.sin(ang);

//dot product of the two vectors
var dot_prod = d_cx * b_vx + d_cy * b_vy;

//new calculation of difference in angle - NOT WORKING!
var d_ang = Math.acos(dot_prod);

var side;
if (Math.abs(d_ang) < Math.PI/2 )
side = "front";
else
side = "back";

console.log("length",len);
console.log("pos:",pos.x,pos.y);
console.log("offs:",d_cx,d_cy);
console.log("body vec",b_vx,b_vy);
console.log("body angle:",ang);
console.log("dot product",dot_prod);
console.log("result:",d_ang);
console.log("side",side);
console.log("------------------------");

}

• acos of the dot product of a vector passing through the point of collision, and your objects facing vector. This will allow you to efficiently get the angle between these two vectors. – Evan May 6 '14 at 14:47
• thx for the tip! now.. if i can just figure out how to determine the objects facing vector properly. I updated the code above to reflect what i have so far.. seems like there is still something missing. – jorb May 7 '14 at 4:56
• I’m afraid I don’t understand the drawings. What is the blue rectangle? The blue line? The black circle? The two black lines? The red line? What is actually colliding with what? For this answer to be useful to other people, it should be a bit more clear what you are asking. – sam hocevar May 7 '14 at 10:14
• updated diagram and description @SamHocevar – jorb May 7 '14 at 23:15

I have a result that works. Some things that I didn't get right initially..

• efficient formula (thx user Evan)
• possible negative body rotation
• extra 90° where Box2D and html canvas rotation begins

Ship.prototype.onCollide = function (other_ent,cx,cy) {

var pos = this.body.GetPosition();

//collision position relative to body
var d_cx = pos.x - cx;
var d_cy = pos.y - cy;

//length of initial vector
var len = Math.sqrt(Math.pow(pos.x -cx,2) + Math.pow(pos.y-cy,2));

//body angle - can over rotate hence mod 2*Pi
var ang = this.body.GetAngle() % (Math.PI * 2);

if (ang < 0) { ang = (Math.PI * 2) + ang; }

//vector representing body's angle - same magnitude as the first
var b_vx = Math.cos(ang- Math.PI/2);
var b_vy = Math.sin(ang- Math.PI/2);

//dot product of the two vectors
var dot_prod = d_cx * b_vx + d_cy * b_vy;
dot_prod /= len;

//resulting angle
var d_ang = Math.acos(dot_prod);

var side;
if (Math.abs(d_ang) > Math.PI/2 )
side = "front";
else
side = "back";

}

• One more small change I'd make is to calculate Math.PI/2 once and save the result. This will reduce the number of costly floating point divisions. (The same can be done for Math.PI * 2 too, but the divisions are by far the more costly). – DFreeman May 9 '14 at 9:36
• good point @DFreeman thx. lead me to search the box2dweb code to see that it had at least done that also :) – jorb May 9 '14 at 11:13