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

 void collision2D(char mode,double alpha,
       void collision2D(char mode,double alpha,
 double m1, double m2, double r1, double r2,
                 double m1, double m2, double r1, double r2,
 double& x1, double& y1, double& x2, double& y2,
                 double& x1, double& y1, double& x2, double& y2,
 double& vx1, double& vy1, double& vx2, double& vy2,
                 double& vx1, double& vy1, double& vx2, double& vy2,

 int& error )
                 int& error )      {
{

 double  r12,m21,d,gammav,gammaxy,dgamma,dr,dc,sqs,t,
       double  r12,m21,d,gammav,gammaxy,dgamma,dr,dc,sqs,t,
 dvx2,a,x21,y21,vx21,vy21,pi2;
               dvx2,a,x21,y21,vx21,vy21,pi2;

 //     ***initialize some variables ****
//     ***initialize some variables ****
 pi2=2*acos(-1.0E0);
       pi2=2*acos(-1.0E0);
 error=0;
       error=0;
 r12=r1+r2;
       r12=r1+r2;
 m21=m2/m1;
       m21=m2/m1;
 x21=x2-x1;
       x21=x2-x1;
 y21=y2-y1;
       y21=y2-y1;
 vx21=vx2-vx1;
       vx21=vx2-vx1;
 vy21=vy2-vy1;
       vy21=vy2-vy1;



 //     ****  return old positions and velocities if relative velocity =0 ****
//     ****  return old positions and velocities if relative velocity =0 ****

 if ( vx21==0 && vy21==0 )
       if ( vx21==0 && vy21==0 )  {error=1; return;}
{error=1; return;}


 //     *** calculate relative velocity angle
//     *** calculate relative velocity angle             
 gammav=atan2(-vy21,-vx21);
       gammav=atan2(-vy21,-vx21);




 //******** this block only if initial positions are given *********
//******** this block only if initial positions are given *********


 if (mode != 'f')
       if (mode != 'f')  {
{

 
       
 d=sqrt(x21*x21 +y21*y21);
       d=sqrt(x21*x21 +y21*y21);
 
       
 //     **** return if distance between balls smaller than sum of radii ***
//     **** return if distance between balls smaller than sum of radii ***

 if (d<r12)
       if (d<r12)  {error=2; return;}
{error=2; return;}

 //     *** calculate relative position angle and normalized impact parameter ***
//     *** calculate relative position angle and normalized impact parameter ***
 gammaxy=atan2(y21,x21);
       gammaxy=atan2(y21,x21);
 dgamma=gammaxy-gammav;
       dgamma=gammaxy-gammav;

 if (dgamma>pi2)
          if (dgamma>pi2)  {dgamma=dgamma-pi2;}
{dgamma=dgamma-pi2;}

 else if (dgamma<-pi2)
           else if (dgamma<-pi2)  {dgamma=dgamma+pi2;}
{dgamma=dgamma+pi2;}
 dr=d*sin(dgamma)/r12;
       dr=d*sin(dgamma)/r12;
 
       
 //     **** return old positions and velocities if balls do not collide ***
//     **** return old positions and velocities if balls do not collide ***
 if (  (fabs(dgamma)>pi2/4 && fabs(dgamma)<0.75*pi2) || fabs(dr)>1 )
       if (  (fabs(dgamma)>pi2/4 && fabs(dgamma)<0.75*pi2) || fabs(dr)>1 )   

 
            {error=1; return;}
{error=1; return;}


 //     **** calculate impact angle if balls do collide ***
//     **** calculate impact angle if balls do collide ***
 alpha=asin(dr);
       alpha=asin(dr);

 
       
 //     **** calculate time to collision ***
//     **** calculate time to collision ***
 dc=d*cos(dgamma);
       dc=d*cos(dgamma);

 if (dc>0)
       if (dc>0)  {sqs=1.0;} else
{sqs=1.0;} else  {sqs=-1.0;}
{sqs=-1.0;}
 t=(dc-sqs*r12*sqrt(1-dr*dr))/sqrt(vx21*vx21+ vy21*vy21);
       t=(dc-sqs*r12*sqrt(1-dr*dr))/sqrt(vx21*vx21+ vy21*vy21);
 //    **** update positions ***
//    **** update positions ***
 x1=x1+vx1*t;
       x1=x1+vx1*t;
 y1=y1+vy1*t;
       y1=y1+vy1*t;
 x2=x2+vx2*t;
       x2=x2+vx2*t;
 y2=y2+vy2*t;
       y2=y2+vy2*t;

 
       
 }
   }

 //******** END 'this block only if initial positions are given' *********
//******** END 'this block only if initial positions are given' *********
 
      
 
       
 
       
 //     ***  update velocities ***
//     ***  update velocities ***

 a=tan( gammav +alpha);
       a=tan( gammav +alpha);

 dvx2=-2*(vx21 +a*vy21) /((1+a*a)*(1+m21));
       dvx2=-2*(vx21 +a*vy21) /((1+a*a)*(1+m21));
 
       
 vx2=vx2+dvx2;
       vx2=vx2+dvx2;
 vy2=vy2+a*dvx2;
       vy2=vy2+a*dvx2;
 vx1=vx1-m21*dvx2;
       vx1=vx1-m21*dvx2;
 vy1=vy1-a*m21*dvx2;
       vy1=vy1-a*m21*dvx2;


 return;
       return;
 }
}



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


 void collision2Ds(double m1, double m2,
       void collision2Ds(double m1, double m2,
 double x1, double y1, double x2, double y2,
                 double x1, double y1, double x2, double y2,

 double& vx1, double& vy1, double& vx2, double& vy2)
                 double& vx1, double& vy1, double& vx2, double& vy2)      {
{

 double  m21,dvx2,a,x21,y21,vx21,vy21,fy21,sign;
       double  m21,dvx2,a,x21,y21,vx21,vy21,fy21,sign;


 m21=m2/m1;
       m21=m2/m1;
 x21=x2-x1;
       x21=x2-x1;
 y21=y2-y1;
       y21=y2-y1;
 vx21=vx2-vx1;
       vx21=vx2-vx1;
 vy21=vy2-vy1;
       vy21=vy2-vy1;



 //     *** I have inserted the following statements to avoid a zero divide;
//     *** I have inserted the following statements to avoid a zero divide; 
 //         (for single precision calculations,
//         (for single precision calculations, 
 //          1.0E-12 should be replaced by a larger value). **************
//          1.0E-12 should be replaced by a larger value). **************  
 
  
 fy21=1.0E-12*fabs(y21);
       fy21=1.0E-12*fabs(y21);                            

 if ( fabs(x21)<fy21 )
       if ( fabs(x21)<fy21 )  {
{  

 if (x21<0)
                   if (x21<0)  { sign=-1; } else
{ sign=-1; } else  { sign=1;}
{ sign=1;}  
 x21=fy21*sign;
                   x21=fy21*sign; 
 }
        } 

 //     ***  update velocities ***
//     ***  update velocities ***
 a=y21/x21;
       a=y21/x21;
 dvx2= -2*(vx21 +a*vy21)/((1+a*a)*(1+m21)) ;
       dvx2= -2*(vx21 +a*vy21)/((1+a*a)*(1+m21)) ;
 vx2=vx2+dvx2;
       vx2=vx2+dvx2;
 vy2=vy2+a*dvx2;
       vy2=vy2+a*dvx2;
 vx1=vx1-m21*dvx2;
       vx1=vx1-m21*dvx2;
 vy1=vy1-a*m21*dvx2;
       vy1=vy1-a*m21*dvx2;


 return;
       return;
 }
}
