collision response between circles is not working in javascript

Asked

Viewed 50 times

-3

I’m trying to implement the equations for the two-circle collision response in a program of mine, but all of them either made the ball speed incredibly high or only works 50% of the time (in the other 50 balls just wanted to go further towards each other instead of colliding) someone can say what is wrong or simply pass an implementation of the equations for me to adapt to my program?

the code I’m using (which works 50% of the time):

var v1 = Math.hypot(vx1, vy1);
var v2 = Math.hypot(vx2, vy2);
var theta1 = v1 === 0 ? 0 : vy1 >= 0 ? Math.acos(vx1 / v1) : 3 * Math.PI / 2 + Math.asin(vx1 / v1);
var theta2 = v2 === 0 ? 0 : vy2 >= 0 ? Math.acos(vx2 / v2) : 3 * Math.PI / 2 + Math.asin(vx2 / v2);
var phi = y1 - y2 >= 0 ? Math.acos((x1 - x2) / v2) : 3 * Math.PI / 2 + Math.asin((x1 - x2) / v2);
var termo1 = (v1 * Math.cos(theta1 - phi) * (m1 - m2) + 2 * m2 * v2 * Math.cos(theta2 - phi)) / (m1 + m2);
proximo_vx1 = termo1 * Math.cos(phi) + v1 * Math.sin(theta1 - phi) * Math.cos(phi + Math.PI / 2);
proximo_vy1 = termo1 * Math.sin(phi) + v1 * Math.sin(theta1 - phi) * Math.sin(phi + Math.PI / 2);

the first equation is the one used above (50% of the times), the second equation is the one that accelerates the balls too

screenshot of Wikipedia (https://en.wikipedia.org/wiki/Elastic_collision, section on collisions between sieves):

  • 1

    Please reduce your question to a Javascript code issue. For example, why a certain expression (simpler than the ones you asked) that should result in a certain value is giving another value that was not expected. There will probably be an answer here on the site.

1 answer

-1

Well, first some care must be taken:

Suppose a circle has a velocity in x much higher than y (small angle) and both velocities are positive. In this case, it is better to make the sine arch (not the cosine arch). This is because the cosine of this very small angle is very close to 1 (0.9999...) which is not a good approximation to be used, due to the type of data Number be of format Double. The sine of this angle is a good approximation for it. Therefore, making the sine arc is a better approximation of the true angle than the cosine arc.

Another caution is the quadrant in which this angle is. Yeah cos(x) = cos(-x) and sin(π/2 + x) = sin(π/2 - x). That is, two angles can generate the same sine/cosine value. The method Math.asin() (source) returns a value between -π/2 and π/2. The method Math.acos() (source) returns between 0 and π.

If you want, you can continue with this care. But, for your case, there is an easier way to deal with them: use the method Math.atan2() (source). In this method you enter two values (of the two categories), instead of the tangent value of the angle (as is the method Math.atan()), and it returns the angle between -π and π.

var theta1 = atan2(vy1, vx1);
var theta2 = atan2(vy2, vx2);

I used the reference indicated by Wikipedia to find the value of φ:

var phi = Math.atan2(y2 - y1, x2 - x1);

Finally, just do the final speed calculations as indicated: Cálculo das velocidades finais

Observing: Of website which is a reference for Wikipedia, if θ2 is as shown in the image: Colisão de dois círculos, observação quanto ao θ2

then in fact its value is:

var theta2 = Math.PI - atan2(vy2, vx2);

When you say:

the balls just wanted to go further towards each other instead of colliding

you mean one crosses the other?

If so, you should compare the distance between the centers of the circles. If it is less than the sum of its rays, then it is crossing. If not, then you haven’t crashed yet.

if(Math.hypot(x2-x1, y2-y1) <= raio1 + raio2){
    // colidiu
}
  • thanks for understanding, and for what I understood and implemented, the calculations of the angles were correct (I like to make the formulas myself, so it was the equivalent of atan2), and I think it is not by the crash test that they cross each other (so much so that I already do this test, I just didn’t show there to not give too much visual pollution), I think identifies the collision but the speeds for some reason are calculated in the wrong way, but it’s just what I think. if you want I can show more code, just ask

  • I understand that you like to generate your own formulas, but I still recommend using atan2 to generate and propagate fewer errors. There may be several factors: try reducing the magnitude of the speed of the balls and see if the problem continues. After crashing, does he calculate only once the new speeds or does he continue to calculate while in the collision area? (State machine: before collision -> during collision (calculates only one new speed) -> after collision (exited collision area))

  • I used atan2 and it did not give visual difference, so it should not be that, but I will keep atan2, as for the speed of the balls, it is low, and after entering in collision he continues calculating while it is in the collision area

  • Good. So that’s it! You have to calculate only once... If you keep calculating it’s like you’re crashing more than once. Use a flag: If you are in the collision area && this flag for true, Then calculate new speeds and change the flag for false. Then just return it to true when outside the collision area. Thus, the new speed will only be calculated once.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.