关于对小球相互碰撞处理的研究
由于要写一个模拟多个小球相互碰撞的程序,所以我就研究了下两个小球相互碰撞之后的速度变化规律(理想环境下无摩擦无碰撞损耗等的完全弹性碰撞)。
?
我们都知道,两个小球如果是在同一条直线上相向而行,则我们可以通过能量守恒(动能守恒)和动量守恒来计算碰撞之后的速度,若两小球质量相等,则交换它们的速度。若质量不相等,则可以求出:
?
设两小球的质量为m1,m2,碰撞前速度为v1,v2,碰撞后速度为v'1,v'2。
则有以下两个公式同时成立:
m1 * v1 + m2 * v2 = m1 * v'1 + m2 * v'2 ---------------------------------(1)
1/2 * m1 * v1^2 + 1/2 * m2 * v2^2 = 1/2 * m1 * v'1^2 + 1/2 * m2 * v'2^2 -----------------------------(2)
?
(1)、(2)可化为:
m1 * v1 -?m1 * v'1?= m2 * v'2?-?m2 * v2?----------------------------------(3)
1/2 * m1 * v1^2 -?1/2 * m1 * v'1^2? = 1/2 * m2 * v'2^2 -?1/2 * m2 * v2^2?-----------------------------(4)
?
(4)/(3)得:
v1 + v'1 = v2 + v'2 -------------------------------------------------------------(5)
?
(1)、(5)可化为:
m2 * v'2 =?m1 * v1 + m2 * v2 - m1 * v'1 ---------------------------------(6)
v'2 =?v1 + v'1 - v2 --------------------------------------------------------------(7)
?
把(7)代入(6)得:
m2?*?v1 +?m2?*?v'1 -?m2?*?v2 =?m1 * v1 + m2 * v2 - m1 * v'1 -------------------------------------------(8)
?
由(8)化简得:
v'1 = [ 2 * m2 * v2 + ( m1 - m2 ) * v1 ] / ( m1 + m2 )
同理可得:
v'2 = [ 2 * m1 * v1 + ( m2 - m1 ) * v2 ] / ( m1 + m2 )
?
这样就计算出碰撞后两小球的速度了。
?
但是,两小球能在同一直线上相向而行的概率基本为零,最常发生的碰撞则是这样的:

?
?
所以,我们得想办法把这样的碰撞情况转化为我们会处理的情况,加以计算。
?
那么我们来分析一下:
两小球的碰撞点在两球心的连线上,那么在理想状态下,两小球的相互作用力应该是沿着两球心的连线方向的。
根据牛顿第一定律,力是改变屋里运动状态的唯一原因,既然在垂直于两球心的连线的方向上没有力的作用,那么两小球在垂直于两球心的连线的方向上的分运动是不变的。
这样的话,两小球在垂直于两球心的连线的方向上的速度是不变的,那么同样这个方向上的动量和动能也是不变的。
那么,两小球在两球心的连线方向的分运动也遵循动量守恒和动能守恒。
?
这样,我们就能把一般碰撞事件转化为我们可以解决的在同一条直线上相向而行的碰撞事件来进行计算了。
?
现在,我们来分析一下分速度应该如何计算。

设小球速度为a,两球心连线为b,小球速度在两球心连线方向上的分速度为c,小球速度在垂直于两球心连线的方向上的分速度为d。
那么a??b?= (?c?+?d?) ?b?=?c??b?+?d??b。
而d与b相互垂直,所以d??b = 0。
那么a??b?=?c??b。
?
设b的斜率为k,那么可以再设a?= ( x1, y1 ),b?= ( x2, k x2 ),c?= ( x, k x ),
那么代入得:
x1 x2 + y1 ( k x2 ) = x x2 + ( k x ) ( k x2 )。
x = ( x1 x2 + k y1 x2 ) / ( x2 + k^2 x2 )
x = ( x1 + k y1 ) / ( k^2 + 1 )
那么k x为:
k x = k ?( x1 + k y1 ) / ( k^2 + 1 )
k x = ?( x1 + k y1 ) / ( k + 1 / k )
?
现在回过头来,把这个公式代入小球的数据:
设碰撞时,小球1的速度为( v1x, v1y ),位置为( x1, y1 );小球2的速度为( v1x, v1y ),位置为( x2, y2 ),两球心连线方向的斜率为k。
?
那么小球1在两球心连线方向上的分速度v1_1,
它在x轴方向的分速度为:
v1_1x =?(?v1x?+ k ?v1y?) / (??k^2 + 1 )
它在x轴方向的分速度为:
v1_1y = k * v1_1x =?(?v1x?+ k ?v1y?) /?( k + 1 / k )
即:
v1_1 = (?(?v1x?+ k ?v1y?) / (??k^2 + 1 ),?(?v1x?+ k ?v1y?) /?( k + 1 / k )?)
?
那么小球1在垂直于两球心连线的方向上的分速度v1_0,
?
它在x轴方向的分速度为:
v1_0x = v1x - v1_1x =?v1x -?(?v1x?+ k ?v1y?) / (??k^2 + 1 )
它在x轴方向的分速度为:
v1_0y?= v1y - v1_1y?=?v1y -?(?v1x?+ k ?v1y?) /?( k + 1 / k )
即:
v1_0?= (?v1x -?(?v1x?+ k ?v1y?) / (??k^2 + 1 ),?v1y -?(?v1x?+ k ?v1y?) /?( k + 1 / k )?)
?
?
同理,小球2在两球心连线方向上的分速度为:
v2_1?= (?v2_1x,?v2_1y?) = (?(?v2x?+ k ?v2y?) / (??k^2 + 1 ),?(?v2x?+ k ?v2y?) /?( k + 1 / k )?)
小球2在垂直于两球心连线的方向上的分速度为:
v2_0?= (?v2_0x,?v2_0y?)?=?(?v2x -?(?v2x?+ k ?v2y?) / (??k^2 + 1 ),?v2y -?(?v2x?+ k ?v2y?) /?( k + 1 / k )?)
?
经过计算,我们可以得到碰撞后两小球在两球心连线方向上的分速度v_1_1,v_2_1。
那么碰撞后两小球的速度为v_1 = v1_0 +?v_1_1,v_2 = v2_0 + v_2_1。
?
当然,若写成代码则不需要那么麻烦,只要定义几个中间变量,这些结果都可以由计算机计算:
public void bumpEachother(Ball ball1, Ball ball2) {//获取两小球的质量float m1 = ball1.getM();float m2 = ball2.getM();//获取两小球的位置Point2D.Float position1 = ball1.getPosition();Point2D.Float position2 = ball2.getPosition();//获取两小球的速度Point2D.Float velocity1 = ball1.getVelocity();Point2D.Float velocity2 = ball2.getVelocity();//定义碰撞后两小球的速度Point2D.Float velocity_1 = new Point2D.Float();Point2D.Float velocity_2 = new Point2D.Float();//定义两小球在垂直于两球心连线的方向的速度Point2D.Float velocity1_0 = new Point2D.Float();Point2D.Float velocity2_0 = new Point2D.Float();//定义碰撞前两小球在两球心连线方向的速度Point2D.Float velocity1_1 = new Point2D.Float();Point2D.Float velocity2_1 = new Point2D.Float();//定义碰撞后两小球在两球心连线方向的速度Point2D.Float velocity_1_1 = new Point2D.Float();Point2D.Float velocity_2_1 = new Point2D.Float();//定义两球心连线的斜率为kfloat k = (position1.y - position2.y) / (position1.x - position2.x);//计算碰撞前两小球在两球心连线方向的速度velocity1_1.x = (velocity1.x + k * velocity1.y) / (1 + k * k);velocity1_1.y = k * velocity1_1.x;velocity2_1.x = (velocity2.x + k * velocity2.y) / (1 + k * k);velocity2_1.y = k * velocity2_1.x;//计算两小球在垂直于两球心连线的方向的速度velocity1_0.x = velocity1.x - velocity1_1.x;velocity1_0.y = velocity1.y - velocity1_1.y;velocity2_0.x = velocity2.x - velocity2_1.x;velocity2_0.y = velocity2.y - velocity2_1.y;//计算碰撞后两小球在两球心连线方向的速度velocity_1_1.x = (2 * m2 * velocity2_1.x + (m1 - m2) * velocity1_1.x) / (m1 + m2);velocity_1_1.y = (2 * m2 * velocity2_1.y + (m1 - m2) * velocity1_1.y) / (m1 + m2);velocity_2_1.x = (2 * m1 * velocity1_1.x + (m2 - m1) * velocity2_1.x) / (m1 + m2);velocity_2_1.y = (2 * m1 * velocity1_1.y + (m2 - m1) * velocity2_1.y) / (m1 + m2);//计算碰撞后两小球的速度velocity_1.x = velocity1_0.x + velocity_1_1.x;velocity_1.y = velocity1_0.y + velocity_1_1.y;velocity_2.x = velocity2_0.x + velocity_2_1.x;velocity_2.y = velocity2_0.y + velocity_2_1.y;//重设两小球速度ball1.setVelocity(velocity_1);ball2.setVelocity(velocity_2);}?
?
好了,这样的话,两小球之间的相互碰撞事件的处理就完成啦,只要判断出两小球相撞,就可以调用这个类来改变小球速度啦~~
?