For each quadrant, I need to find a neat way of calculating the deflection angle for a small circular object striking a circle, as shown in the diagram.

Quadrants for Defection

  • Angles a and b are already known.
  • Angle a is always relative to 0 degrees position.
  • Angle b is relative to the quadrant.
  • The initial angle can also be greater than 180, when coming from the other direction, as shown in the diagram the right.

For quadrant 2, in the following snippet from my code, dy and dx represent the x and y coordinates of a point on the circle:

intersectAngle = atan(dy/dx);

Initial angle is calculated from velocity vectors:

pAngle = PI - (atan2(pVel.x, pVel.y));

For quadrant 0, I came up with this for the rebound angle:

pAngle = pAngle - 2 *(pAngle - tangentAngle);

Where tangentAngel is just the intersect angle with half PI added. Thsi worked for a ball from any direction.

Moving onto quadrant 1, this works for pAngles of less than 90 deg, but not for pAngles from the other direction:

pAngle = pAngle + 0.5 * PI - intersectAngle;

Feels like I shouldn't be writing all this code and that there is a more efficient way. I realise this is an elementary question but I'm studying this so it's all new to me. Please be gentle.


1 Answer 1


It seems like you are just reflecting the vector and it would be easier to do so, as such, than manually fiddle with quadrant math. I think you have access to vectors but, if it's a project constraint, I can modify this to use only basic scientific calculator functions. V1 relates to angle a and V2 relates to angle b. All vectors should be normalized.

This works for any vector, in any quadrant:

enter image description here

  1. I believe V1 is pVel, normalized.
  2. I believe V2 is {dx, dy}, normalized.
  3. V3.Dot(V2) == -V1.Dot(V2)
  4. The angle between V3 and V2 is acos(-V1.Dot(V2))
  5. The angle between V3 and '0' is acos(-V1.Dot(V2)) + b
  6. Post-collision velocity is V3 * the original magnitude of V1

This could happen if you detect the wrong collision first (very little implementation detail included):

enter image description here

Leave a comment if you need help with it.

  • \$\begingroup\$ Thanks, and yes, I am reflecting the vector. Could you clarify what you mean by "normalised"? \$\endgroup\$
    – Jason210
    Mar 12, 2016 at 9:45
  • \$\begingroup\$ @Jason210, the entirety of trig happens on the unit-circle (radius 1, shown dashed in white). For example, to normalize the vector {10, 0} (solid green + purple), you divide by it's length, 10, to get {1, 0} (dashed green), a unit-vector pointing in the same direction. \$\endgroup\$
    – Jon
    Mar 12, 2016 at 10:52
  • \$\begingroup\$ @Jason210, before normalizing, V1 includes the purple extension beyond the unit-circle; after normalizing it becomes unit-length (solid green), but we shift it to X0 (dashed green). Also, .Dot() refers to the dot-product and is the red leg of the dashed triangle. V1.Dot(V2) is the "magnitude of V1 in the V2 direction" and will range from -1 to +1 if all inputs are normalized. \$\endgroup\$
    – Jon
    Mar 12, 2016 at 10:52
  • \$\begingroup\$ Thanks. There are some new and valuable concepts for me here. I'm going to try to implement your suggestion... \$\endgroup\$
    – Jason210
    Mar 12, 2016 at 10:56
  • \$\begingroup\$ @Jason210, I notice pVel has x and y components, so if that's an actual vector class, it's probably got built-in methods for all of this (possibly even .Reflect()); you weren't specific about language or development environment. I'm going to step-by-step the first diagram tomorrow and can add code if you get stuck. \$\endgroup\$
    – Jon
    Mar 12, 2016 at 11:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .