C++ Program Code for 2D Elastic Collision of 2 Balls

// ******************************************************************************
None.gif
//    This program is a 'remote' 2D-collision detector for two balls on linear
None.gif
//    trajectories and returns, if applicable, the location of the collision for 
None.gif
//    both balls as well as the new velocity vectors (assuming a fully elastic
None.gif
//    collision).
None.gif
//    In  'f' (free) mode no positions but only the initial velocities
None.gif
//    and an impact angle are required.
None.gif
//    All variables apart from 'mode' and 'error' are of Double Precision
None.gif
//    Floating Point type.
None.gif
//
None.gif
//    The Parameters are:
None.gif
//
None.gif
//     mode  (char) (if='f' alpha must be supplied; otherwise arbitrary)
None.gif
//     alpha (impact angle) only required in mode='f'; 
None.gif
//                      should be between -PI/2 and PI/2 (0 = head-on collision))
None.gif
//     m1   (mass of ball 1)
None.gif
//     m2   (mass of ball 2)
None.gif
//     r1   (radius of ball 1)        not needed for 'f' mode
None.gif
//     r2   (radius of ball 2)                "
None.gif
//   & x1   (x-coordinate of ball 1)          "
None.gif
//   & y1   (y-coordinate of ball 1)          "
None.gif
//   & x2   (x-coordinate of ball 2)          "
None.gif
//   & y2   (y-coordinate of ball 2)          "
None.gif
//   & vx1  (velocity x-component of ball 1) 
None.gif
//   & vy1  (velocity y-component of ball 1)         
None.gif
//   & vx2  (velocity x-component of ball 2)         
None.gif
//   & vy2  (velocity y-component of ball 2)
None.gif
//   & error (int)  (0: no error
None.gif
//                   1: balls do not collide
None.gif
//                   2: initial positions impossible (balls overlap))
None.gif
//
None.gif
//    Note that the parameters with an ampersand (&) are passed by reference,
None.gif
//    i.e. the corresponding arguments in the calling program will be updated;
None.gif
//    however, the coordinates and velocities will only be updated if 'error'=0.
None.gif
//
None.gif
//    All variables should have the same data types in the calling program
None.gif
//    and all should be initialized before calling the function even if
None.gif
//    not required in the particular mode.
None.gif
//
None.gif
//    This program is free to use for everybody. However, you use it at your own
None.gif
//    risk and I do not accept any liability resulting from incorrect behaviour.
None.gif
//    I have tested the program for numerous cases and I could not see anything 
None.gif
//    wrong with it but I can not guarantee that it is bug-free under any 
None.gif
//    circumstances.
None.gif
//
None.gif
//    I would appreciate if you could report any problems to me
None.gif
//    (for contact details see   http://www.plasmaphysics.org.uk/feedback.htm  ).
None.gif
//
None.gif
//    Thomas Smid, January  2004
None.gif
//                 December 2005 (corrected faulty collision detection; 
None.gif
//                                a few minor changes to improve speed;
None.gif
//                                added simplified code without collision detection)
None.gif
// *********************************************************************************
None.gif

None.gif       
void  collision2D( char  mode, double  alpha,
None.gif                 
double  m1,  double  m2,  double  r1,  double  r2,
None.gif                 
double &  x1,  double &  y1,  double &  x2,  double &  y2,
None.gif                 
double &  vx1,  double &  vy1,  double &  vx2,  double &  vy2,
ExpandedBlockStart.gif                 
int &  error )      {
InBlock.gif
InBlock.gif       double  r12,m21,d,gammav,gammaxy,dgamma,dr,dc,sqs,t,
InBlock.gif               dvx2,a,x21,y21,vx21,vy21,pi2;
InBlock.gif
InBlock.gif//     ***initialize some variables ****
InBlock.gif
       pi2=2*acos(-1.0E0);
InBlock.gif       error=0;
InBlock.gif       r12=r1+r2;
InBlock.gif       m21=m2/m1;
InBlock.gif       x21=x2-x1;
InBlock.gif       y21=y2-y1;
InBlock.gif       vx21=vx2-vx1;
InBlock.gif       vy21=vy2-vy1;
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif//     ****  return old positions and velocities if relative velocity =0 ****
ExpandedSubBlockStart.gif
       if ( vx21==0 && vy21==0 ) {error=1; return;}
InBlock.gif
InBlock.gif
InBlock.gif//     *** calculate relative velocity angle             
InBlock.gif
       gammav=atan2(-vy21,-vx21);
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif//******** this block only if initial positions are given *********
InBlock.gif

ExpandedSubBlockStart.gif       if (mode != 'f') {
InBlock.gif
InBlock.gif       
InBlock.gif       d=sqrt(x21*x21 +y21*y21);
InBlock.gif       
InBlock.gif//     **** return if distance between balls smaller than sum of radii ***
ExpandedSubBlockStart.gif
       if (d<r12) {error=2; return;}
InBlock.gif
InBlock.gif//     *** calculate relative position angle and normalized impact parameter ***
InBlock.gif
       gammaxy=atan2(y21,x21);
InBlock.gif       dgamma=gammaxy-gammav;
ExpandedSubBlockStart.gif          if (dgamma>pi2) {dgamma=dgamma-pi2;}
ExpandedSubBlockStart.gif           else if (dgamma<-pi2) {dgamma=dgamma+pi2;}
InBlock.gif       dr=d*sin(dgamma)/r12;
InBlock.gif       
InBlock.gif//     **** return old positions and velocities if balls do not collide ***
InBlock.gif
       if (  (fabs(dgamma)>pi2/4 && fabs(dgamma)<0.75*pi2) || fabs(dr)>1 )   
ExpandedSubBlockStart.gif           {error=1; return;}
InBlock.gif
InBlock.gif
InBlock.gif//     **** calculate impact angle if balls do collide ***
InBlock.gif
       alpha=asin(dr);
InBlock.gif
InBlock.gif       
InBlock.gif//     **** calculate time to collision ***
InBlock.gif
       dc=d*cos(dgamma);
ExpandedSubBlockStart.gif       if (dc>0) {sqs=1.0;} else {sqs=-1.0;}
InBlock.gif       t=(dc-sqs*r12*sqrt(1-dr*dr))/sqrt(vx21*vx21+ vy21*vy21);
InBlock.gif//    **** update positions ***
InBlock.gif
       x1=x1+vx1*t;
InBlock.gif       y1=y1+vy1*t;
InBlock.gif       x2=x2+vx2*t;
InBlock.gif       y2=y2+vy2*t;
InBlock.gif
InBlock.gif       
ExpandedSubBlockEnd.gif   }
InBlock.gif
InBlock.gif//******** END 'this block only if initial positions are given' *********
InBlock.gif      
InBlock.gif       
InBlock.gif       
InBlock.gif
//     ***  update velocities ***
InBlock.gif

InBlock.gif       a=tan( gammav +alpha);
InBlock.gif
InBlock.gif       dvx2=-2*(vx21 +a*vy21) /((1+a*a)*(1+m21));
InBlock.gif       
InBlock.gif       vx2=vx2+dvx2;
InBlock.gif       vy2=vy2+a*dvx2;
InBlock.gif       vx1=vx1-m21*dvx2;
InBlock.gif       vy1=vy1-a*m21*dvx2;
InBlock.gif
InBlock.gif
InBlock.gif       return;
ExpandedBlockEnd.gif}

None.gif
None.gif
None.gif
None.gif
// ******************************************************************************
None.gif
//   Simplified Version
None.gif
//   The advantage of the 'remote' collision detection in the program above is 
None.gif
//   that one does not have to continuously track the balls to detect a collision. 
None.gif
//   The program needs only to be called once for any two balls unless their 
None.gif
//   velocity changes. However, if somebody wants to use a separate collision 
None.gif
//   detection routine for whatever reason, below is a simplified version of the 
None.gif
//   code which just calculates the new velocities, assuming that the balls are 
None.gif
//   already touching and approaching each other (these two conditions are 
None.gif
//   important as otherwise the results will be incorrect)
None.gif
// ****************************************************************************
None.gif

None.gif
None.gif       
void  collision2Ds( double  m1,  double  m2,
None.gif                 
double  x1,  double  y1,  double  x2,  double  y2,
ExpandedBlockStart.gif                 
double &  vx1,  double &  vy1,  double &  vx2,  double &  vy2)      {
InBlock.gif
InBlock.gif       double  m21,dvx2,a,x21,y21,vx21,vy21,fy21,sign;
InBlock.gif
InBlock.gif
InBlock.gif       m21=m2/m1;
InBlock.gif       x21=x2-x1;
InBlock.gif       y21=y2-y1;
InBlock.gif       vx21=vx2-vx1;
InBlock.gif       vy21=vy2-vy1;
InBlock.gif
InBlock.gif
InBlock.gif
InBlock.gif//     *** I have inserted the following statements to avoid a zero divide; 
InBlock.gif
//         (for single precision calculations, 
InBlock.gif
//          1.0E-12 should be replaced by a larger value). **************  
InBlock.gif
  
InBlock.gif       fy21=1.0E-12*fabs(y21);                            
ExpandedSubBlockStart.gif       if ( fabs(x21)<fy21 ) {  
ExpandedSubBlockStart.gif                   if (x21<0) { sign=-1; } else { sign=1;}  
InBlock.gif                   x21=fy21*sign; 
ExpandedSubBlockEnd.gif        } 
InBlock.gif
InBlock.gif//     ***  update velocities ***
InBlock.gif
       a=y21/x21;
InBlock.gif       dvx2= -2*(vx21 +a*vy21)/((1+a*a)*(1+m21)) ;
InBlock.gif       vx2=vx2+dvx2;
InBlock.gif       vy2=vy2+a*dvx2;
InBlock.gif       vx1=vx1-m21*dvx2;
InBlock.gif       vy1=vy1-a*m21*dvx2;
InBlock.gif
InBlock.gif
InBlock.gif       return;
ExpandedBlockEnd.gif}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值