Я пытаюсь рассчитать столкновение двух шаров одинаковой массы, предполагая, что столкновение абсолютно упругое, для моделирования компьютерной физики. Зная координаты обоих шаров и их начальные скорости в момент столкновения, я хочу рассчитать конечные скорости. Я некоторое время искал в Интернете и нашел несколько разных веб-сайтов, которые дают формулу для этого. Проблема в том, что при запуске симуляции казалось, что кинетическая энергия не сохраняется должным образом (некоторые столкновения прибавляют энергию, что вообще не имеет смысла, некоторые теряют ее). Итак, мой вопрос: что-то не так с этим методом? Вот псевдокод метода:
function manage_bounce(ball, ball2) {
dx = ball._x-ball2._x;
dy = ball._y-ball2._y;
collisionision_angle = Math.atan2(dy, dx);
magnitude_1 = Math.sqrt(ball.xspeed*ball.xspeed+ball.yspeed*ball.yspeed);
magnitude_2 = Math.sqrt(ball2.xspeed*ball2.xspeed+ball2.yspeed*ball2.yspeed);
direction_1 = Math.atan2(ball.yspeed, ball.xspeed);
direction_2 = Math.atan2(ball2.yspeed, ball2.xspeed);
new_xspeed_1 = magnitude_1*Math.cos(direction_1-collisionision_angle);
new_yspeed_1 = magnitude_1*Math.sin(direction_1-collisionision_angle);
new_xspeed_2 = magnitude_2*Math.cos(direction_2-collisionision_angle);
new_yspeed_2 = magnitude_2*Math.sin(direction_2-collisionision_angle);
final_xspeed_1 = ((ball.mass-ball2.mass)*new_xspeed_1+(ball2.mass+ball2.mass)*new_xspeed_2)/(ball.mass+ball2.mass);
final_xspeed_2 = ((ball.mass+ball.mass)*new_xspeed_1+(ball2.mass-ball.mass)*new_xspeed_2)/(ball.mass+ball2.mass);
final_yspeed_1 = new_yspeed_1;
final_yspeed_2 = new_yspeed_2;
ball.xspeed = Math.cos(collisionision_angle)*final_xspeed_1+Math.cos(collisionision_angle+Math.PI/2)*final_yspeed_1;
ball.yspeed = Math.sin(collisionision_angle)*final_xspeed_1+Math.sin(collisionision_angle+Math.PI/2)*final_yspeed_1;
ball2.xspeed = Math.cos(collisionision_angle)*final_xspeed_2+Math.cos(collisionision_angle+Math.PI/2)*final_yspeed_2;
ball2.yspeed = Math.sin(collisionision_angle)*final_xspeed_2+Math.sin(collisionision_angle+Math.PI/2)*final_yspeed_2;
}
Я упростил ваш код, используя тождества триггеров и тот факт, что массы шаров равны. Я также отформатировал код так, чтобы он выглядел как результат умножения матрицы вращения, и добавил комментарии, указывающие на то, что, по моему мнению, является целью каждого раздела.
function manage_bounce(ball, ball2) {
// determine direction of balls with ball2 at origin
dx = ball._x-ball2._x;
dy = ball._y-ball2._y;
collision_angle = Math.atan2(dy, dx);
c = Math.cos(collision_angle);
s = Math.sin(collision_angle);
// Rotate coordinate system by -collision_angle so
// x-axis aligns with line joining the balls' centers.
// Recalculate velocity components in new coordinate system.
new_xspeed_1 = c*ball.xspeed + s*ball.yspeed;
new_yspeed_1 = -s*ball.xspeed + c*ball.yspeed;
new_xspeed_2 = c*ball_2.xspeed + s*ball_2.yspeed;
new_yspeed_2 = -s*ball_2.xspeed + c*ball_2.yspeed;
// Exchange the velocities parallel to collision
// direction (xspeed) and rotate (+collision_angle)
// back to original coordinate system.
ball.xspeed = c*new_xspeed_2 - s*new_yspeed_1;
ball.yspeed = s*new_xspeed_2 + c*new_yspeed_1;
ball2.xspeed = c*new_xspeed_1 - s*new_yspeed_2;
ball2.yspeed = s*new_xspeed_1 + c*new_yspeed_2;
}
Это выглядит правильно. Поскольку массы шаров равны, результатом должен быть обмен скоростями, параллельный направлению столкновения, поскольку при этом сохраняется импульс. Кинетическая энергия должна сохраняться, так как
Если это псевдокод, попробуйте упростить ваш реальный код так же, как это сделал я, и посмотрите, не обнаружатся ли какие-либо ошибки.
Изменить: еще два математических упрощения:
r = Math.sqrt(dx*dx + dy*dy) // or r = Math.hypot(dx, dy) if available
c = dx/r // cos(collision_angle)
s = dy/r // sin(collision_angle)
Qмеханик