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

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

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



// **** return old positions and velocities if relative velocity =0 ****
if ( vx21==0 && vy21==0 ) {error=1; return;}


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




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

if (mode != 'f') {

d=sqrt(x21*x21 +y21*y21);
// **** return if distance between balls smaller than sum of radii ***
if (d<r12) {error=2; return;}

// *** calculate relative position angle and normalized impact parameter ***
gammaxy=atan2(y21,x21);
dgamma=gammaxy-gammav;
if (dgamma>pi2) {dgamma=dgamma-pi2;}
else if (dgamma<-pi2) {dgamma=dgamma+pi2;}
dr=d*sin(dgamma)/r12;
// **** return old positions and velocities if balls do not collide ***
if ( (fabs(dgamma)>pi2/4 && fabs(dgamma)<0.75*pi2) || fabs(dr)>1 )
{error=1; return;}


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

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

}

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

a=tan( gammav +alpha);

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


return;
}



//
******************************************************************************
//
Simplified Version
//
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.
//
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
//
detection routine for whatever reason, below is a simplified version of the
//
code which just calculates the new velocities, assuming that the balls are
//
already touching and approaching each other (these two conditions are
//
important as otherwise the results will be incorrect)
//
****************************************************************************

void
collision2Ds(
double
m1,
double
m2,
double
x1,
double
y1,
double
x2,
double
y2,
double
&
vx1,
double
&
vy1,
double
&
vx2,
double
&
vy2)
{

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


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



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

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


return;
}
































































































































































































