NTNUJAVA Virtual Physics Laboratory
Enjoy the fun of physics with simulations!
Backup site http://enjoy.phy.ntnu.edu.tw/ntnujava/

JDK1.0.2 simulations (1996-2001) => Dynamics => Topic started by: Fu-Kwun Hwang on January 29, 2004, 04:08:42 pm



Title: 2D Collision
Post by: Fu-Kwun Hwang on January 29, 2004, 04:08:42 pm
Due to so many requests from the users, source code for this applet is distributed with the ZIP files you will receive if you click get file for offline use button. Please do not ask me to send you the source code again!

You are welcomed to check out another Collision 2D (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=120.0) created with EJS.



 Please check out latest 2D collision created with EJS (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=120.0)

Let's consider collisions in two dimension:
Press Start to begin the animation.
    Two circular objects will move with pre-defined velocity (yellow arrow).
    Click left mouse button to suspend the animation. Now, you can
      Click near the tip of the velocity vector and drag the mouse button
       left/right to change its value (the initial velocity of that object).
      Click near the circular boundary and drag the mouse button to change its radius.

      Right Click near the boundary of the circle to change it's size (also change it's mass, at the same time).

      Click near the center of the circle and drag the mouse to change its location.

    Click the mouse button again to resume the animation. When the two objects collide, the animation will be suspend.
      Press the mouse button ( Do not release it) to see the velocity vectors just after the collision.

    Press Reset button to reset parameters to default values.
      eta is the coefficient of restitution eat Vf/Vi Vf=relative velocity just after collision
       Vi=relative velocity just before collision
       for elastic collision eta=1.
       for perfectly inelastic collision eta=0.

    You can select different frame of reference to view the relative motion of all the objects.
      lab is a laboratory inertial frame. m1, m2 and CM are frame of reference with respect to
        left circular object m1, right circular object m2 and center of mass for m1 and m2.

    View collision in 1 dimension.


    At the moment when they collide, the force between the two circle objects is along the line which connect the center of the two objects.

    Now we have 1-D collision problem:
    two object move in the direction along the line connect between their center, with velocitys along this directions. (Red vectors)

    The vector perpendicular to the above components (green vectors) will not changed after collision.
    (If there is no friction force between the two objects)

    Please check out Rigid Body Collisions (http://www.myphysicslab.com/collision.html) for 2D collision between rectangle shape objects.


Title: How to convert 2D collision into 1D
Post by: Fu-Kwun Hwang on October 28, 2004, 02:19:44 pm
(http://www.phy.ntnu.edu.tw/demolab/phpBB/pics/2_2_collision2d.png)

1. Find the time when two ball collide : D= R1+ R2
 where D=Distance between center of two balls , and   R1/R2  is radius of each balls

2.  Find the line connect center of  two balls. and calculate the component of the velocitry for each ball  alone the line connect those two balls.
 For example : Velocity for each ball is Va and Vb (before collision)
  Calculate Vap and Vbp. (and another normal component Van,Vbn)
3. It is become a 1D collision problem: ball A with velocity Vap collide with ball B with velocity Vbp . You should be able to calculate velocity after collision for each ball.
   for example:  
  Vap2=((m1-m2)/(m1+m2))vap+ (2m2/(m1+m2))Vbp and
  Vbp2=(2 m1/(m1+m2))Vap+((m2-m1)/(m2+m1))Vbp
  The tangential component is not changed Van2=Van, and Vbn2=Vbn
4. Calculate the vector sum for velocity of each ball after collision
  Va2=Vap2+Van2 and Vb2=Vb2p+Vbn2 (vector summation)


Title: topic4
Post by: siput_tiung on March 12, 2005, 11:41:59 am
hi,
is there any difference between balls or humans when collision occur?
i am trying to write a human model for collision cases... and still trying very2 hard to make it in realistic way. your applet seems like good for me and i'm impressed with it... perhaps it would be good to be applied to my project.. can u explain it in detail how's the calculation for it? dividing it into 3 condition,(1.before,2. during..,3.after.. )would be really2 great... thanks..

ref: http://www.phy.ntnu.edu.tw/ntnujava/viewtopic.php?t=19

Regards,
Bazli Karim
siput_tiung@yahoo.com


Title: topic4
Post by: Fu-Kwun Hwang on March 12, 2005, 02:20:41 pm
The above calculation assume it is an elastic collision between two balls.
i.e. No energy is loss during the collision.
And the ball would not change shape.

For collision betwen two human, we will change our body movment.

Would you explain in more detail why you need to calculate collision between human?
While two persons are walking or ...?


Title: topic4
Post by: siput_tiung on March 14, 2005, 10:07:58 am
let's see... here i'm trying to do collision avoidance among human...

for example... human A is trying to go to point 1... and if there is another human blocking his way... then.. the human A must avoid it.. by changing to other direction and then, go to point 1..
here... i can detect the collision if there is human blocking another human.. but, i have problem with changing direction... to make it realistic..


Title: topic4
Post by: Fu-Kwun Hwang on March 14, 2005, 02:33:38 pm
Because you want to avoid collision among human.
So there is no collision among human.

You can check the velocity vector, if it is pointing to another person. Then someone is blocking his way.
Provide the horizontal displayment, you can calculate the least change of the velocity.
The person can change direction right at that point or change velocity gradually.


Title: topic4
Post by: siput_tiung on March 16, 2005, 02:41:52 pm
thanks.. i got the idea now..


Title: Java Code for collision in 2D
Post by: Fu-Kwun Hwang on May 11, 2005, 07:03:51 am
Due to so many email questions asking for help. I re-wrote this post to include more detail calculation steps:

Assume the radius for two ball are r1 and r2, and the coordinates are (x1,y1) and (x2,y2).
Usually, we calculate the distance between two balls d=sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

The collision should have occurred if d equal r1+r2; // if(d==r1+r2)

However, there is a finite time step dt in the simulation calculation,so most often we would not be able to find the above condition (exact time when two ball real occurred).
So we check if d<= r1+r2; Then we know the collision should have occurred.

The real collision should have occurred before you detected that the distance between two center of the balls d is less than the sum of those two balls r1+r2. (d< r1+r2)

The correct way is to find the time when the two ball really collide with each other.
Suppose the center of those two ball are x1,y2 and x2,y2
dx=x2-x1, dy=y2-y1; d=sqrt(dx*dx+dy*dy);

First calculate the component of velocity in the direction of (dx,dy)
vp1= vx1 *dx/d+vy1*dy/d;
vp2= vx2*dx/d+vy2*dy/d;

Collision should have happened dt before you have detected r1+r2 and dt =(r1+r2-d)/(vp1-vp2);
 and dt =(r1+r2-d)/(vp1-vp2);// the collision should have occurred at t-dt (Actually this is also an approximation).

So you should move those two ball backward
 x1-= vx1*dt;
 y2 -= vy1*dt;
 x2-=vx2*dt;
 y2-=vy2*dt;

Now the distance between center of the two balls is d'=r1+r2;

The following code take care of collision:

double dx = x2-x1, dy = y2-y1;
// where x1,y1 are center of ball1, and x2,y2 are center of ball2
double distance = Math.sqrt(dx*dx+dy*dy);
// Unit vector in the direction of the collision
double ax=dx/distance, ay=dy/distance;
// Projection of the velocities in these axes
double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);
// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+ed)*(va2-va1)/(1+mass1/mass2);
double vaP2=va2 + (1+ed)*(va1-va2)/(1+mass2/mass1);
// Undo the projections
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision

Quote
(ax,ay)  is the unit vector in the direction connected two objects.
draw a line connect two object, assign the angle between this line and x-axis is θ,
then  cosθ=ax, sin θ=ay
So vap1*ax=vap1*cosθ give x-component of vap1, and vap1*ay give y-component of vap1

Because vb1 and vb2 is in the direction perpendicular to the (ax,ay)
,then the angle between vb1 and x-axis is φ=θ+π/2
so cos φ=cos(θ+π/2)=-sinθ=-ay, sinφ=sin(θ+π/2)=cosθ=ax
to calculate x-component of vb1 we need to calculate vb1*cos φ=vb1*(-ay)=-vb1*ay
,and (y-component of vb1) = vb1*sinφ=vb1*ax

Because we have move time backward dt, we need to move time forward dt.
so
  x1+= vx1'*dt;
  y1+=vy1'*dt;
  x2+=vx2'*dt;
  y2+=vy2'*dt;

Now the distance between two ball will be larger than r1+r2.

If you did not correct the time dt (before you have found collision occurred, you will find balls clutch together. and they don't even let go.



Title: topic4
Post by: rsnd on August 13, 2005, 10:33:14 am
sorry for bothering :) Its probably a 3 year old thread!!!

Just wondering...what does vx0 represent in your code?


Thanks
Rsnd


Title: 2D and 3D Elastic Collision Solutions
Post by: Thomas on September 17, 2005, 10:27:54 pm
Anybody looking into the physics of 2D and 3D- elastic collisions may also be interested in my pages http://www.plasmaphysics.org.uk/collision2d.htm and http://www.plasmaphysics.org.uk/collision3d.htm which represent direct and general solutions of the problems. I have also written corresponding Fortran and C++ codes for this ( see http://www.plasmaphysics.org.uk/programs/coll2d_for.htm , http://www.plasmaphysics.org.uk/programs/coll2d_cpp.htm , http://www.plasmaphysics.org.uk/programs/coll3d_for.htm , http://www.plasmaphysics.org.uk/programs/coll3d_cpp.htm ) which are free to use for everybody.

**************
Note that there was a bug in the collision detection routine of the 2D-versions of my programs (this led in certain cases to collisions being detected when in fact there were none). I have corrected this now. I have also made minor changes to the code in order to improve speed. Furthermore I have added a simplified version to the 2D-routines that does not not contain the collision detection routine but just returns the new velocities assuming that the input coordinates are already those of the collision.

Thomas, 11.Dec.05
*******************


Title: topic4
Post by: Fu-Kwun Hwang on September 21, 2005, 07:30:44 am
Is there a vx0 posted in this forum messages! Please explain what do you mean?


Title: DYNAMICS APPLET
Post by: Janus20 on September 29, 2005, 09:56:41 am
You have missed the spin component caused by the collision.

It may have been there before collision occured.

The spin neglect is an ENORMOUS ERROR. The information is dangerous due to its over simplification.


Title: topic4
Post by: Fu-Kwun Hwang on October 18, 2005, 09:17:59 am
Yes, the ball will also rotate if there are friction force between balls when collide.
This is just an applet try to help student to understand basic physics (how to transform a 2D problem into two 1D problem).


Title: 2-D collision for circular discs
Post by: sujitkane on October 19, 2005, 06:01:46 pm
Hello Professor Hwang

I have been following these pages since its publication in january 2004, just happened to register today. I wonder how different will it be if we consider that the two colliding bodies are two circular discs. You might have heard of a board game called carrom , its very popular in India. Do take a look at it. Now we have tried to emulate the example you have put up here and applied it to the emulation of carrom. There are  a few rough edges, but still the difference is not very clear. What changes will be necessary to make it work realistically?

Regards
Sujit Kane


Title: topic4
Post by: Fu-Kwun Hwang on October 20, 2005, 08:06:24 am
I do not know anything about carrom. Is there a URL for that?

To add a rotation effect due to friction between two disks,  the mathematics become more comples.

The friction between two disks is proportional to the normal force when two disks collide.
F(friction) = mu * F(normal)

The normal force is the rate of change of momentum (in the direction between two centers) when two disks collide.

The friction force might change the tangential component of the velocity if the friction force is not large enough ( sliding occurs)

The torque due to the friction will change the angular momentum for those two disks.

In 2D collision: vx,vy and w (angular momentum) are changed due to collision for each ball.
There are 6 variables need to be update for two balls, so you need to solve 6 equations.


Title: topic4
Post by: pleasedontgocrazy on October 23, 2005, 10:42:16 pm
what if the collision isnt perfectly inelastic/ elastic


Title: topic4
Post by: Fu-Kwun Hwang on October 24, 2005, 07:45:39 am
You just need to solve the problem differently for non- perfect elastic collision.

Momentum is still conserved. But the energy is not conserved.


Title: topic4
Post by: pleasedontgocrazy on October 25, 2005, 05:39:17 pm
I keep trying to prove your equation by using the assumption that kinetic energy is not lost and momentum is not lost but I keep getting a different answer to yours. Could you give me some pointers about how to do solve it. SOLVED!

Im doing this experiment for my A level coursework and I found that typically 90% of the mommentum is lost. Have I made a mistake?


Title: topic4
Post by: pleasedontgocrazy on October 25, 2005, 06:56:26 pm
Yes! Ive solved it (and got the correct answer)

But this is for an elastic collision. For an partial inelastic collision which equation do I use for kinetic energy? Do you lose a certain amount of energy or is it a percentage of energy lost?


Title: Sticky Balls
Post by: SIBUK on November 28, 2005, 05:52:53 am
Hi Professor Hwang,

This article is fantastic and has helped me a lot, but I am wondering if you might be able to help me out with a problem I have. I have made a program where I have multiple balls on the screen, each moving at a random velocity and in a random direction.

 The problem I have is that when 2 balls collide, they will often stick to each other (especially when ed is < 1) and spin around orbiting each other. Each of the balls has a radius of 15, and so my collision detection is very simple, when the distance between two balls is <= 30 then there has been a collision. So, the problem is that when the distance is less than 30, (say 25), then they are overlaping by 5, when I next update the positions of the balls, if they havnt moved more than a distance of 5 away from each other since the last update, then they are still overlapping and the collision is still true. So, what I need to do is before the next update, I need to move the balls appart from each other a distance of 5 in the new direction after the impact. But I cant seem to figure out the maths to do it.

Also, I have implemented a bit of code to help handle when 3 or more balls collide at the same time, but it doesnt quite seem to work right. Do you have any tips for this?


Title: topic4
Post by: Fu-Kwun Hwang on April 15, 2006, 02:11:56 pm
The real collision should have occured before you detected that the distance between two center of the balls d is less than the sum of those two balls r1+r2.

The correct way is to find the time when the two ball real collide with each other.
Suppose the center of those two ball are x1,y2 and x2,y2
dx=x2-x1, dy=y2-y1;  d=sqrt(dx*dx+dy*dy);

First calculate the component of velocity in the direction of (dx,dy)
vp1= vx1 *dx/d+vy1*dy/d;
vp2= vx2*dx+vy2*dy/d;

Collision should have happened dt before you have detected r1+r2<d;

 and  dt =(r1+r2-d)/(vp1+vp2);

So you should move those two ball backward
 x1-= vx1*dt;
 y2 -= vy1*dt;
 x2-=vx2*dt;
 y2-=vy2*dtl

Now the distance between center of the two balls is d'=r1+r2;

Apply the collision to calculate new velocity for those two balls after collision.
Support new velocity are vx1' , vy1', vx2',vy2'

You need to move time dt forward
so

  x1+= vx1'*dt;
  y1+=vy1'*dt;
  x2+=vx2'*dt;
  y2+=vy2'*dt;


You can check out another simulation created with EJS (http://www.phy.ntnu.edu.tw/ntnujava/viewtopic.php?t=173) and find out how I did it with EJS.


Title: Re: 2D Collision
Post by: druidbartek on February 21, 2007, 03:49:40 am
hi
sorry for bumping this old thread but ive some problems with ball collision (in C)
the - the conservation of kinetic energy is property but not the conservation of momentum :(
it's the simple ball collision 2D for old nokia mobiles
Code:
static void redraw_screen(void)
{
   /* ... */
   ball_collision(&app.ball_a, &app.ball_b);
   <redraw_screen>
}
Code:
static void ball_collision(struct ball *ball_a, struct ball *ball_b)
{
   float dx = ball_b->x - ball_a->x;
   float dy = ball_b->y - ball_a->y;
   float d = sqrt(dx*dx+dy*dy);

   if(d<=(float)bmap_ball.height) // r1+r2 = bmap_ball.height
   {
      // first we calculate the velocity in the direction of (dx,dy)
      float vp_a = (ball_a->vx*dx + ball_a->vy*dy)/d;
      float vp_b = (ball_b->vx*dx + ball_b->vy*dy)/d;

      // collision should have happened dt before
      float dt =((float)bmap_ball.height-d)/(vp_a-vp_b);

      // we should move those ball backward
      ball_a->x -= ball_a->vx*dt;
      ball_a->y -= ball_a->vy*dt;
      ball_b->x -= ball_b->vx*dt;
      ball_b->y -= ball_b->vy*dt;

      dx = ball_b->x - ball_a->x;
      dy = ball_b->y - ball_a->y;
      d = sqrt(dx*dx+dy*dy);

      // calculate the components of velocity
      float ap = dx/d;
      float an = dy/d;

      vp_a = ball_a->vx*ap + ball_a->vy*an;
      float vn_a = ball_a->vx*an - ball_a->vy*ap;

      vp_b = ball_b->vx*ap + ball_b->vy*an;
      float vn_b = ball_b->vx*an - ball_b->vy*ap;
     
      // calculate new velocity for those balls after collision
      ball_a->vx = vp_b*ap + vn_a*an;
      ball_a->vy = vp_b*an - vn_a*ap;
      ball_b->vx = vp_a*ap + vn_b*an;
      ball_b->vy = vp_a*an - vn_b*ap;

      // now we need to move time dt forward
      ball_a->x += ball_a->vx*dt;
      ball_a->y += ball_a->vy*dt;
      ball_b->x += ball_b->vx*dt;
      ball_b->y += ball_b->vy*dt;
   }
}

and im stuck  ???

regards,
Bartek


oh, and mass1 = mass2 and eta =1


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on February 22, 2007, 04:48:24 pm
This is the java code I use in my simulation:
Code:
        r12=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
cs=(x2-x1)/r12; sc=(y2-y1)/r12;
vp1=vx1*cs+vy1*sc;
vp2=vx2*cs+vy2*sc;
// back to collision time
ddt=(dmin-r12)/(vp1-vp2);
if(ddt>dt)ddt=0.;
x1-=vx1*ddt; y1-=vy1*ddt;
x2-=vx2*ddt; y2-=vy2*ddt;
r12=Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
//calculate component of velocity
cs=(x2-x1)/r12; sc=(y2-y1)/r12;
vp1=vx1*cs+vy1*sc;
vp2=vx2*cs+vy2*sc;
//  normal components do not change
vn1=vx1*sc-vy1*cs;
vn2=vx2*sc-vy2*cs;
       //calculate component of velocity in original X,Y coordinate
px1=vp1*cs; py1=vp1*sc;
px2=vp2*cs; py2=vp2*sc;
nx1=vn1*sc; ny1=-vn1*cs;
nx2=vn2*sc; ny2=-vn2*cs;
}


Title: Re: 2D Collision
Post by: solashok on February 28, 2007, 09:22:43 am
Respected Sir,
  when two atoms collide using Conservation of Momentum and Energy we get expression for E2 = 4M1M2 cos square phi E0/(M1 + M2)square. Can U suggest me how this has come.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on February 28, 2007, 10:15:32 am
What is the situation you want to discuss about? There is no way to discuss if question is not well defined!
What are the meaning for E0,E2 and what is the formula you want to show?
And how did you get that formula? ???
 


Title: Re: 2D Collision
Post by: mrsdost on April 18, 2007, 11:13:41 pm
Hello Professor,
I am currently working on the following question and was wondering if you could offer any help. I'm just not sure how to factor in the 30 degrees. this is of course a completely elastic collision. any help would be great.
Thanks,
mrsdost

Two pool balls are rolling along a pool table. The red pool ball has a velocity of 10 cm/s west and the blue ball a velocity of 10 cm/s north 30° east. What are the velocities of the balls after the collision?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on April 19, 2007, 01:01:41 am
You can find out the answer easily.
Just use mouse to drag the velocity vector for each ball in the simulation (conditions match with your problem) and find out the answer by yourself!


Title: Re: 2D Collision
Post by: mrsdost on April 19, 2007, 09:55:36 pm
Thank you Professor,
but i need to learn how to do the calculations myself.
So if you could help me with some formulas that include the vectors of the balls that would be great.
Thank you,
Mrsdost


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on April 19, 2007, 10:09:51 pm
Please look at all the forum messages in this topic carefully,  all the steps (in detail) have been posted (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg15#msg15).
I guess you did not read this forum messages carefully.
If you did read it and still did not understand it. Please at least indicate where you did not get it. ::)


Title: Re: 2D Collision
Post by: arthurprs on July 22, 2007, 01:41:57 am
Hi professor, sorry to bother you, but im having some dificult here to make your code work  ???

This is my code in OPascal
not much dif from java
Code:
        dx := ball[i].cx - ball[n].cx;
        dy := ball[i].cy - ball[n].cy;
        dist := Sqrt(Power(dx, 2) + Power(dy, 2));
        if dist <= (ball[i].raio + ball[n].raio) then
        begin
          ax := dx / dist;
          ay := dy / dist;
          vp_n := (ball[n].vx * ax) + (ball[n].vy * ay);
          vp_i := (ball[i].vx * dx) + (ball[i].vy * ay);
          dt := ((ball[i].raio + ball[n].raio) - dist) / (vp_n + vp_i);
          ball[n].x := ball[n].x - (ball[n].vx * dt);
          ball[n].y := ball[n].y - (ball[n].vy * dt);
          ball[i].x := ball[i].x - (ball[i].vx * dt);
          ball[i].y := ball[i].y - (ball[i].vy * dt);

You can see something wrong ?

*sorry my bad english, im from brazil

EDIT: If u can send me the source code to my email it will be helpfull too


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 23, 2007, 03:35:51 pm
You can find out the code related to what you need from previous messages.
You are not following the same steps I did.
Please read it more carefully.



Title: Re: 2D Collision
Post by: arthurprs on July 24, 2007, 01:29:19 am
You can find out the code related what you need from previous messages.
You are not following the same steps I did.
Please read it more carefully.
ok.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 24, 2007, 03:04:13 pm
Please following the code I did in my previous messages.
Post the code again if you still have the problem.


Title: Re: 2D Collision
Post by: arthurprs on July 26, 2007, 09:44:45 am
Please following the code I did in my previous messages.
Post the code again if you still have the problem.

Hey professor i did it, but somethimes the balls don't colide right  ???

anything wrong with my code ?

Code:
  for n := 0 to Length(ball)-1 do
  begin // n = currentball

  // wall hit
    //x
    if (ball[n].x <= 0)
      or (ball[n].x2 >= Form1.ClientWidth) then
    begin
      ball[n].vx := -ball[n].vx {* 0.9};
    end;
    //y
    if (ball[n].y <= 0)
      or (ball[n].y2 >= Form1.ClientHeight) then
    begin
      ball[n].vy := -ball[n].vy {* 0.9};
    end;

  // other balls hit
    for i := 0 to Length(ball)-1 do // i = other ball
      if ((i <> n) and (not (ball[i].colided)) and (not (ball[n].colided))) then
      begin
        dx := ball[i].cx - ball[n].cx;
        dy := ball[i].cy - ball[n].cy;
        dist := Sqrt(Power(dx, 2) + Power(dy, 2));
        if dist <= (ball[i].raio + ball[n].raio) then
        begin
          //
          ax := dx / dist;
          ay := dy / dist;
          vp_n := (ball[n].vx * ax) + (ball[n].vy * ay);
          vp_i := (ball[i].vx * dx) + (ball[i].vy * ay);
          dt := ((ball[i].raio + ball[n].raio) - dist) / (vp_n + vp_i);
          ball[n].x := ball[n].x - (ball[n].vx * dt);
          ball[n].y := ball[n].y - (ball[n].vy * dt);
          ball[i].x := ball[i].x - (ball[i].vx * dt);
          ball[i].y := ball[i].y - (ball[i].vy * dt);
          ball[n].Refresh;
          ball[i].Refresh;
          //
          dx := ball[i].cx - ball[n].cx;
          dy := ball[i].cy - ball[n].cy;
          dist := Sqrt(Power(dx, 2) + Power(dy, 2));
          ax := dx / dist;
          ay := dy / dist;
          vp_n := ball[n].vx * ax + ball[n].vy * ay;
          vp_i := ball[i].vx * ax + ball[i].vy * ay;
          vn_n := ball[n].vy * ay - ball[n].vy * ax;
          vn_i := ball[i].vy * ay - ball[i].vy * ax;
          vn:= vp_n + (1+ed)*(vp_i - vp_n)/(1+ball[n].mass/ball[i].mass);
          vi:= vp_i + (1+ed)*(vp_n - vp_i)/(1+ball[i].mass/ball[n].mass);
          ball[n].vx:= vn*ax-vn_n*ay;
          ball[n].vy:= vn*ay+vn_n*ax;
          ball[i].vx:= vi*ax-vn_i*ay;
          ball[i].vy:= vi*ay+vn_i*ax;
          ball[n].Refresh;
          ball[i].Refresh;
          ball[n].colided:=True;
          ball[i].colided:=True;
        end;
      end;
  end;

  for n := 0 to Length(ball) - 1 do
  begin
    ball[n].Move;
  end;
end;

2 balls
both mass = 1 and ed = 1


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 26, 2007, 10:43:11 am
You did not read my post carefully.
You did not do the following steps:

First calculate the component of velocity in the direction of (dx,dy)
vp1= vx1 *dx/d+vy1*dy/d;
vp2= vx2*dx+vy2*dy/d;

Collision should have happened dt before you have detected r1+r2

 and dt =(r1+r2-d)/(vp1+vp2);// the collision should have occurred at t-dt (Actually this is also an approximation).

So you should move those two ball backward
 x1-= vx1*dt;
 y2 -= vy1*dt;
 x2-=vx2*dt;
 y2-=vy2*dt;

Next : do the collision parts. as the normal case.

And move the time forward:

Because we have move time backward dt, we need to move time forward dt.
so
  x1+= vx1'*dt;
  y1+=vy1'*dt;
  x2+=vx2'*dt;
  y2+=vy2'*dt;

Now the distance between two ball will be larger than r1+r2.

Please read the following post carefully and follow all the steps.

http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg15#msg15


Title: Re: 2D Collision
Post by: estruiz on July 27, 2007, 05:30:46 am
Hi Professor

My name is Esteban and I need some help.  I do not know much about physics, but this past year i've been trying to solve a head on collision between a 98 Dodge ram 1500 quad cab 4x4 (5251 lbs.) and a Pontiac Grand AM 4 door sedan (3650 lbs.).  The pontiac is heading south and the dodge is heading north.  The speed of the car is unknown and the speed of the truck is 43 mph +-.  No breaks where applied to neither vehicles.  The friction of the road is 0.565.  The car heading south crossed over the centerline at an angle of 14 degrees and when realized they where in the oncoming lane they tried to steer to their right which sent their car out of control and made their tail end slide sideways.  the car is still heading in the same 14 degrees, but now going sideway almost at 90 degrees to the 14 degree direction.  Both truck and car impact on the left front bumpers (driver side).  Both left front tires from each vehicle are locked.  The truck is sent backwards about 19 feet and its final resting position is facing east.  The car is sent east of the impact about 18 feet and about 8 feet north of the impact with the car facing south.  the dimensions of the road are 28 feet from edge of pavement to edge of pavement so 14 feet from centerline to EOP. The slope of the road heading south is S=1.45% south and the entire road slopes to the east at 2.75%. 

What I need to know if this is possible and if it is, at what speed does the car need to be traveling to be able to push back the truck?  Please email me if you need any more information at estruiz@msn.com


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 27, 2007, 09:20:00 am
"the car is still heading in the same 14 degrees, but now going sideway almost at 90 degrees to the 14 degree direction."

I do not quite understand the above situation? And is it happened before the collision?

"The slope of the road heading south is S=1.45% south and the entire road slopes to the east at 2.75%.  "
I did not understand the above statement,either!

The car is sent east of the impact about 18 feet, But from center to edge of pavement is 14 feet, so the car is out of the pavement?

Without consider the above parameters. From the impact distance in the north-south direction.
I try to estimate the speed right after the impact for both car:
Assume the stopping distance are all due to friction of the road (which might not be true if car was flying after the impact)
The following are very rough estimation and base on  the above assumption:
acceleration for both car assume to be the same: a=-0.565*9.8=5.537 m/s^2

v=sqrt(2*a*s)=sqrt(2*9.8*0.565*s)
19 feet=5.79 m so the speed is about 8 m/s  So it took 1.4 s to fully stopped after the collision.
8 feet=2.43m so the speed is about 5.2m/s  So it took 0.9s to fully stopped after the collision.

Initial speed for the truck is 43mph=69km/hr=19.2m/s

Assume conservation of momentum during collision
3650*(v+5.2)=5251*(19.2+8) so v=33.9m/s = 122 km/hr= 75.9 mph (estimated speed for the car)

Because the mass for the car is smaller than the truck and the bounce off distance for the car is less than the truck, so the speed of the car is larger than the truck.
However, the above estimate are based on very simple model. I believe local police agent should have gather more data to provide a better estimation.


Title: Re: 2D Collision
Post by: arthurprs on July 28, 2007, 12:50:27 pm
You did not read my post carefully.
You did not do the following steps:

First calculate the component of velocity in the direction of (dx,dy)
vp1= vx1 *dx/d+vy1*dy/d;
vp2= vx2*dx+vy2*dy/d;

Collision should have happened dt before you have detected r1+r2

 and dt =(r1+r2-d)/(vp1+vp2);// the collision should have occurred at t-dt (Actually this is also an approximation).

So you should move those two ball backward
 x1-= vx1*dt;
 y2 -= vy1*dt;
 x2-=vx2*dt;
 y2-=vy2*dt;

Next : do the collision parts. as the normal case.

And move the time forward:

Because we have move time backward dt, we need to move time forward dt.
so
  x1+= vx1'*dt;
  y1+=vy1'*dt;
  x2+=vx2'*dt;
  y2+=vy2'*dt;

Now the distance between two ball will be larger than r1+r2.

Please read the following post carefully and follow all the steps.

http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg15#msg15


yes i did it in lines 30 and 31 =/


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 28, 2007, 08:39:48 pm
You are checking collision between n particles
with loop like
for(int i=0;i for(j=0;j }
}
In the above case, collision between particles might be processed twice.
You can change the loop to
for(int i=0;i for(j=0;j   if(i!=j){// particle can not collide with itself
   }
 }

And I did not fully understand what do you mean by
"somethimes the balls don't colide right  Huh"!
You only tell me you think there is something wrong, But I did not know what is wrong!


}


Title: Re: 2D Collision
Post by: arthurprs on July 29, 2007, 02:49:09 pm
You are checking collision between n particles
with loop like
for(int i=0;i<n;i++){
 for(j=0;j<n;j++){
 }
}
In the above case, collision between particles might be processed twice.
You can change the loop to
for(int i=0;i<n;i++){
 for(j=0;j<i;j++){
   if(i!=j){// particle can not collide with itself
   }
 }

And I did not fully understand what do you mean by
"somethimes the balls don't colide right  Huh"!
You only tell me you think there is something wrong, But I did not know what is wrong!


}


the problem is that in 10% of colisions the backtime to make (distance = r1 + r2) does not work right and the ball keep inside the other one


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 29, 2007, 09:11:46 pm
It is always difficult and take time to find out the bug, especially you are working with another language.

Did you change the setting in the loop for your code?
Did you make sure all the particles are not overlap with each other in the initial state?
If you can run  your code step by step, you might be able to find out bugs in your code.
I was assuming the distance moved between each time step is smaller than the size of the particle.
It might be your time step is too large or the velocity is too big. In that case, try to use a smaller time step.

The original source code for this java applet is attached.


Title: Re: 2D Collision
Post by: arthurprs on July 30, 2007, 08:27:32 am
It is always difficult and take time to find out the bug, especially you are working with another language.

Did you change the setting in the loop for your code?
Did you make sure all the particles are not overlap with each other in the initial state?
If you can run  your code step by step, you might be able to find out bugs in your code.
I was assuming the distance moved between each time step is smaller than the size of the particle.
It might be your time step is too large or the velocity is too big. In that case, try to use a smaller time step.

The original source code for this java applet is attached.

ohh i thinks is the velocity its 1.5 in one ball and 1.3 on another  ???

i will try ;)


Title: Re: 2D Collision
Post by: estruiz on July 31, 2007, 01:19:32 am
From what I know the car went off the road and tried to get back on to his lane.  This caused the car to get out of control and went sideways at a 14 degree direction before the collision. 

yes the slope of the street heading south is S=1.45% down and the cross slope of the street is actually S=2.86% to the east from the west edge of pavment.

yes the car went outside of the pavment onto dirt shoulder which has a slope of around S=13% EAST


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 31, 2007, 09:07:57 am
I did not take into account the slope of the road in my previous estimation. Since the car went outside the pavement and onto dirt shoulder which has a slope. The velocity of the car might be less than the estimated velocity.  However, it was a very rough estimation from the information I knew.


Title: Re: 2D Collision
Post by: tedhuntington on August 31, 2007, 12:14:14 am
The 2d collision description is easy to understand, thanks. What needs to be done to make it 3D? Is that a major difference? Do we just need to figure out the projection, perpendicular and one other component then?

thanks
Ted


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on August 31, 2007, 10:40:17 pm
You can solve equations for the conservation of momentum and conservation of energy for 3D, and you will find out new relations (This will give you complicate equations).
However, for 2 particles collide, you can always define a 2D coordinate system (the plane formed by v1Xv2).
So it is always a 2D problem. You just need to find the projection of the 2D plane into 3D coordinate.(And this is the easiest way to do.)

Just like this 2D collision simulation. I transfered the problem into a two 1D problem. And it is make the problem simpler. (I did not solve the 2D problem directly.)

How to transfer a complicated problem into a simpler one, is one of the purpose for learning physics. ;)


Title: Re: 2D Collision
Post by: Collidin Ideas on October 08, 2007, 10:57:42 pm
Hello Professor Fu-Kwun Hwang

I m currently developing a game JOGL(java opengl) in which multiple balls are present on the board n a striker is present using which we have to pot those other coins (Circular Disks) we have uptill now created the board n discs but we are stuck at collision detection part coz there are multiple discs involved

i have thought of creating an event which would detect collisions can u help us with how to go about it with multiple disks involved

thanking you in advance


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 09, 2007, 12:37:43 am
If you have n balls, you need to set up two level loops to check if they are collide with each other
code might be similar to the following:
for(int i=0;i for(int j=i;j  check_collision(i,j,x,y);
 }
}


Title: Re: 2D Collision
Post by: pepsicoder on October 25, 2007, 10:15:57 pm
Hi can you please help me my balls get pushed away abrubtly when colliding sometimes,im keeping my velocities less than my ball radiuses so it can not be that i have done loads of experimentation but no joy.   (cr=0.4;   mass=1;) 

please check my following code written in flash cs3 thankyou in advance.

for (var i1:uint=0;i1<BALLTOTAL-1;i1++) {
    for (var i2:uint=i1+1;i2<BALLTOTALL;i2++) {

        var dx:Number=cararray[i1].x-cararray[i2].x,
             dy:Number=cararray[i1].y-cararray[i2].y,
     d:Number=Math.sqrt(dx*dx+dy*dy),
    r1:Number=19,
    r2:Number=r1;
                        
        if (d<=(r1+r2)) {
                  
            // component of velocity in the direction (dx,dy)
           var vp1:Number=cararray[i1].velx*dx/d+cararray[i1].vely*dy/d,
                vp2:Number=cararray[i2].velx*dx/d+cararray[i2].vely*dy/d, // << corrected this line >>
        dt:Number=(r1+r2-d)/(vp1+vp2);
                     
            // move back
           cararray[i1].x-=cararray[i1].velx*dt;
           cararray[i1].y-=cararray[i1].vely*dt;
           cararray[i2].x-=cararray[i2].velx*dt;
           cararray[i2].y-=cararray[i2].vely*dt;
                  
           dx=cararray[i1].x-cararray[i2].x;
           dy=cararray[i1].y-cararray[i2].y;
            d=Math.sqrt(dx*dx+dy*dy);
                                 
           // unit vector in the direction of the collision           
           var ax:Number=dx/d , ay:Number=dy/d;
                                    
           // projection of the velocities
           var va1:Number=( cararray[i1].velx*ax+cararray[i1].vely*ay),
                vb1:Number=(-cararray[i1].velx*ay+cararray[i1].vely*ax),
      va2:Number=( cararray[i2].velx*ax+cararray[i2].vely*ay),
      vb2:Number=(-cararray[i2].velx*ay+cararray[i2].vely*ax);
                                 
           // new velocities after collisions 
           var vap1:Number=va1+(1+cr)*(va2-va1)/(1+cararray[i1].mass/cararray[i2].mass),
           vap2:Number=va2+(1+cr)*(va1-va2)/(1+cararray[i2].mass/cararray[i1].mass);
                           
           // undo the projections (new velocities after collision)
           cararray[i1].velx=vap1*ax-vb1*ay;
           cararray[i1].vely=vap1*ay+vb1*ax;
           cararray[i2].velx=vap2*ax-vb2*ay;
           cararray[i2].vely=vap2*ay+vb2*ax;
                  
           // move forward
           cararray[i1].x+=cararray[i1].velx*dt;
           cararray[i1].y+=cararray[i1].vely*dt;
           cararray[i2].x+=cararray[i2].velx*dt;
           cararray[i2].y+=cararray[i2].vely*dt;
       }
   }
}


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 26, 2007, 05:10:04 pm
I am not familiar with the syntax in your code.
var i2:uint=i1+1;// Does it mean i2=i1+1;??? I wrote some action code in flash before, but it was almost the same as java-script.

But the problem only occurred for some occasional case, so most part of the code should be all right.
When the ball was pushed away, is it with a much larger velocity?
If this is the case, you can add some code to print out related information when such case happened, in order to find out what went wrong.


Title: Re: 2D Collision
Post by: Manav on October 31, 2007, 10:09:20 am
Hello Professor Hwang,

     You might have guessed my name, it's Manav. In my class we have been creating a class to emulate the physics aspect for a bouncing ball in C++ and using the glut class from OpenGL to show the ball. So far in our class we have many balls that can bounce and slow down due to gravity. I wanted to do more since I am a little bored and so I've been trying to mold your 2D collision of balls for my 3D collision for my balls. Since I registered with the forum just now (which by the way was very helpful for me to get started) I am having troubles. I am stuck at trying to do the part where you calculated the projection velocities, since I have to deal with 3 dimensional vectors. Help would be greatly appreciated. The following is the code for my collision procedure in my C++ class:

Code:
void BallObject::Collision(BallObject ball){
double r1 = diameter / 2; //first ball's radius
double r2 = ball.diameter / 2; //second ball' radius

double dx = ball.position[0] - position[0];
double dy = ball.position[1] - position[1];
double dz = ball.position[2] - position[2];

double d = sqrt((dx*dx) + (dy*dy) + (dz*dz));
double dt;

double vp1 = (velocity[0]*(dx/d)) + (velocity[1]*(dy/d)) + (velocity[2]*(dz/d));
double vp2 = (ball.velocity[0]*(dx/d)) + (ball.velocity[1]*(dy/d)) + (ball.velocity[2]*(dz/d));

if(r1 + r2 < d){
dt =(r1+r2-d)/(vp1+vp2);

position[0] -= velocity[0]*dt;
position[1] -= velocity[1]*dt;
position[2] -= velocity[2]*dt;

ball.position[0] -= ball.velocity[0]*dt;
ball.position[1] -= ball.velocity[1]*dt;
ball.position[2] -= ball.velocity[2]*dt;
         }


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 31, 2007, 07:38:53 pm
For the code in the previous message, you just move those two ball back to the point where the collision occurred.
(The above solution is an approximation, it is not an exact solution. But it should work fine when the velocity*dt << size of the ball).
I do not know what can I help.


Title: Re: 2D Collision
Post by: Manav on November 01, 2007, 01:12:19 am
Hi, its me again and the problem I'm having with is converting the following part for a 3 dimensional ball:

// Unit vector in the direction of the collision
double ax=dx/distance, ay=dy/distance;
// Projection of the velocities in these axes
double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);
// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+ed)*(va2-va1)/(1+mass1/mass2);
double vaP2=va2 + (1+ed)*(va1-va2)/(1+mass2/mass1);
// Undo the projections
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision

In the above code you only deal with x, and y direction, but i want to try to also include a z direction as well and
I do not know how to do the calculation with x, y, and z direction since the ball I'm working on has an x, y, and z position vector.
 


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on November 01, 2007, 04:32:00 pm
I am going to assume you fully understand vector and the inner product between two vectors.

If there are vector A and another vector B. (use bold face to represent vector)

Let the unit vector of A is a=A/|A|, and b=B/|B|, where |A|, |B| are the length of A,B

You can calculate the projection of vector A in the direction of B with AB/|B| =Ab : where • mean inner product
In 2D, ax=dx/distance, ay=dy/distance so (ax,ay) is the unit vector in the direction between center of those two balls.
So the projection of velocity(vx,vy)  in the direction of (ax,ay) is  vx*ax+vy*ay
For the code:
ouble va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);

Now, you know why va1,va2 can be calculated with the above formula.
vb1,vb2 are the normal components -- perpendicular to the (vx,vy)
So the unit vector is (-ay, ax)  -- (ax,ay)•(-ay,ax)=0 so those two vectors are perpendicular to each other.

For the 3D case, you just need to add another component (z) and calculate it in the same way.

I hope you can understand it. If not, let me know and I will try to explain it in more detail.
However,  I want you to understand it, so you will be able to solve similar problem next time. That is why I do not want to give you the exact solution. And you will be more confident when you can solve it by yourself.  You will enjoy the fun of learning this way,too!  ;)


Title: Re: 2D Collision
Post by: Manav on November 02, 2007, 01:03:21 am
Thanks a lot professor Hwang,
    I finally incorporated the z axis into the calculation, but i have one final question. Could
you tell the reason for having dt and what it is doing to the balls in the program. And once again
THANK-YOU very much.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on November 02, 2007, 09:09:03 am
It was explained in the previous message.
In the simulation (or computer programming), the time step is a finite step.
The collision should have happened (It should occurred when R1+R2=d),
before the program detect those two ball collided ( R1+R2 > d, where d is the distance between two balls, and R1,R2 are the radius).
So we calculate the relative velocity in the direction between center of two balld, and estimate the time collision should have happened (dt). So we move the ball back to the moment when the collision should have occurred (let the time move backward by dt, or let particle move backward by v*dt !). Do the calculation for collision, and move time step dt forward again .


Title: Re: 2D Collision
Post by: Manav on November 02, 2007, 10:35:35 am
wow :o, so dt meant the time for the ball to have collided, I'm sorry i was confusing dt with
some sort of distance :-[. Professor Hwang you have been an amazing teacher.
Thank-You   ;D

Also I was wondering should I post how i did the calculation for finding the final velocities of the two ball in
Three-dimension?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on November 02, 2007, 09:46:30 pm
You can decide it by yourself. It's all depend on what the purpose for the posting.
You can post it so that the other user can copy it for similar work, or you want other to do the calculation by herself/himself.


Title: Re: 2D Collision
Post by: Manav on November 02, 2007, 10:21:29 pm
I guess I'll let people do the calculations by themselves since it turned out to be really
easy, but I'll give the other people a hint: When you calculate for a 2-d collision
you calculate for the normal vector and a tangent vector like how Professor Hwang
had done "Va1 and Va2 were calculated using the normal vector and Vb1 and Vb2
were calculated using". When you are calculating for a 3-d collision you have to
find i second tangent vector and just adjust the equations professor has to inclue
the z direction in (x, y, z). If you require more detail for an elastic 2-d collision
equations use the following site: http://www.geocities.com/vobarian/2dcollisions/2dcollisions.pdf (http://www.geocities.com/vobarian/2dcollisions/2dcollisions.pdf)

Please correct me if I am wrong and than-you.
 


Title: Re: 2D Collision
Post by: Manav on November 02, 2007, 10:24:16 pm
I am really sorry people the following sentence from above should look like this:
"Va1 and Va2 were calculated using the normal vector and Vb1 and Vb2
were calculated using the tangent vector".

Once again I am sorry this is my first forum visit ever.


Title: Re: 2D Collision
Post by: sabeeh on November 16, 2007, 04:49:44 am
Thank you very much for this effort in order to benefit from the computer and the Internet in the area of knowledge transfer


Title: Re: 2D Collision
Post by: vanmobi on December 19, 2007, 03:52:44 am
Hello professor,

I am trying to implement the algorithm you described with a small difference: my speed is constantly slowly decreasing so my balls will come to a stop after a while. In your explanation, the speeds are constant. 

Can you please let me know what needs to be changed to implement my deceleration? Detecting the time the collision will take place is tricky. I guess I need to introduce the notion of acceleration (negative in my case).

Thank you!


Title: Re: 2D Collision
Post by: colos on December 19, 2007, 07:20:11 am
The easier way is to introduce a drag force which is proportional to velocity.

F= -b*V , b and initial velocity will determine how far the ball stop.


Title: Re: 2D Collision
Post by: vanmobi on December 19, 2007, 08:56:58 pm
Thank you. Yes, this seems like the right way of doing it.

But I have no idea how to apply this to the existing formulas?

1. What is the impact on the calculation of the component of velocity in the direction of (dx,dy)
vp1= vx1 *dx/d+vy1*dy/d;
vp2= vx2*dx+vy2*dy/d;

2. How do I compute the collision time?
dt =(r1+r2-d)/(vp1+vp2);// the collision should have occurred at t-dt

Thank you for your help!
Vanessa





Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on December 19, 2007, 10:51:52 pm
Sorry! I mis-understood your question
Quote
I am trying to implement the algorithm you described with a small difference: my speed is constantly slowly decreasing so my balls will come to a stop after a while. In your explanation, the speeds are constant.

I did not look at your previous message carefully. I thought in my case, the total energy of those balls should be constant (energy is conserver) and you want the ball to slow down.
It is the opposite.  You much have done something wrong so those balls are slowing down.

You need to write down how you did it. Otherwise, there is no way I can find out why it is so.

For computer code, the time is increases a finite amount. So the ball will change position a finite distance for each time step. At the time you found those two ball collide (d(At the time two ball collide, d is equal to r1+r2).
So we need to move the time backward a little so we can find out when those two ball really collide.
I use an approximation to find the time dt. (r1+r2-d2) is the differences, and vp1,vp2 are velocity almost along the line between center of two ball. So dt=(r1+r2-d2)/(vp1+vp2) will move the ball back to the time those two ball just collide.

But your problem has nothing to do with the above miner correction.  You must have use the wrong formula for the collision so the speed is decreasing.



Title: Re: 2D Collision
Post by: vanmobi on December 20, 2007, 01:05:28 am
Actually, they currently are not slowing down, but I want them to. Just like in a billiard game, after a while, the balls will stop rolling. That's the behavior I am try to implement.

So if I introduce a friction of some sort, what is the implication on the formulas?

Thank you,
Vanessa


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on December 21, 2007, 03:20:16 pm
O.K. So yo do want to add a friction effect.
A simple model: F= m*g*u,  which is a constant for each ball.
So the distance for a ball to stop will proportional to it's kinetic energy K=(1/2)m*v2
This could be a good model for your case.


Title: Re: 2D Collision
Post by: pepsicoder on January 26, 2008, 01:40:38 pm
vp1= vx1*dx/d+vy1*dy/d;
vp2= vx2*dx+vy2*dy/d; // << Is this line a wrong.

Should this code be :-

vp1= vx1*dx/d+vy1*dy/d;
vp2= vx2*dx/d+vy2*dy/d;


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 28, 2008, 11:55:35 pm
Yes. It should be
vp1= vx1*dx/d+vy1*dy/d;
vp2= vx2*dx/d+vy2*dy/d;
or
vp1= (vx1*dx/d+vy1*dy)/d;
vp2= (vx2*dx+vy2*dy)/d;

It is an inner product between two vector (vx,vy) and (dx/d,dy/d)


Title: Re: 2D Collision
Post by: acw on April 20, 2008, 03:29:38 am
thanks for a really nice site, helped me a lot=)
got a few questions:
1. how can i get a applet to work for other regular geometric figures like an rectangle. i cant go with the distance/pythagoras there since the corners will then be ignored.
also could you tell me how this is done for iregular figures in short words. (just wanna know basic theori how this is done since this is way over my level).
2. i was able to implement parts of your code into my own applet to make it more realistic, however sometimes the objects get stuck in each other or in the borders.
althougth you were very clear in your instructions i wasnt able to fully understand how to keep them from doing that. (something with moving them one step away from each other in the if statement i think?)
Code:
for(int i = 0;i < 3;i++){
for(int j = i+1;j<4;j++){
if(Math.sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))<=30){
int dx=x[j]-x[i];
int dy=y[j]-y[i];
double d = Math.sqrt(dx*dx+dy*dy);
double ax=dx/d, ay=dy/d;
double va1=(vx[i]*ax+vy[i]*ay), vb1=(-vx[i]*ay+vy[i]*ax);
double va2=(vx[j]*ax+vy[j]*ay), vb2=(-vx[j]*ay+vy[j]*ax);
vx[i]=va2*ax-vb1*ay; 
vy[i]=va2*ay+vb1*ax;
vx[j]=va1*ax-vb2*ay; 
vy[j]=va1*ay+vb2*ax;
}
}
}

also would be nice if you could give the physic formula for these lines. i ingnored mass and some other factors that didnt matter in my program since same size on all objects, but would like them in the formula aswell.
   
Code:
double ax=dx/d, ay=dy/d;
double va1=(vx[i]*ax+vy[i]*ay), vb1=(-vx[i]*ay+vy[i]*ax);
double va2=(vx[j]*ax+vy[j]*ay), vb2=(-vx[j]*ay+vy[j]*ax);

Thanks


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on April 20, 2008, 08:48:39 am
1. The boundary of any shape is just connected lines (polygon). You need to check if any two lines from different object connected(in contact) with each other.
You can check out ParticlesAndWalls (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=164.0) applet: you can draw any shape and particle will be bounded in the region you have created. (Click Usage link under applet to see flash demo). You can check out our EJS code and find out how it was implemented.

2. You should write down formulas for your code. Your code should be based on your equations.


Title: Re: 2D Collision
Post by: amol on May 07, 2008, 12:42:17 pm
Hi professor,
grt site.....
i really like ur work and the way u r carrying it..
thanx and good luck..

also looking forward  for the  post for gaming people



Title: Re: 2D Collision
Post by: amol on May 07, 2008, 11:29:46 pm
Hello sir,
i have tried to make the collision of two balls.
I have followed the steps u have written in some previous post.

in my case i have kept one ball at rest, and other moving.
But after collision the behaviour of both the ball is weired.

here is my code

   int dx = ball[1].x - ball[0].x;
   int dy = ball[1].y - ball[0].y;
   
   double dist = MathHelper::sqrt(dx*dx + dy*dy);

   //Unit vector in the direction of collision

   double ax = dx /dist;
   double ay = dy/dist;
if(dist < 10) // (actually r1+r2 = 10)
{
   // Projection of the velocities in these axes
   double va1=(ball[0].vx*ax+ball[0].vy*ay), vb1=(-ball[0].vy*ay+ball[0].vy*ax);
   double va2=(ball[1].vx*ax+ball[1].vy*ay), vb2=(-ball[1].vx*ay+ball[1].vy*ax);

   // New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+1)*(va2-va1)/(1+1);
double vaP2=va2 + (1+1)*(va1-va2)/(1+1);

// Undo the projections
ball[0].vx=(int)(vaP1*ax-vb1*ay);  ball[0].vy=(int)(vaP1*ay+vb1*ax);// new vx,vy for ball 1 after collision
ball[1].vx=(int)(vaP2*ax-vb2*ay);  ball[1].vy=(int)(vaP2*ay+vb2*ax);// new vx,vy for ball 2 after collision
}

Please comment on this. thanx.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on May 08, 2008, 12:04:09 am
I would suggest you check the momentum and energy just before and right after the collision.
If it is the same, then there is nothing wrong with the collision.
After the collision the behavior of both balls are wired, may be it is not due to collision , it is due to some other code. And what do you mean by wired? There is no way to help without detail information.


Title: Re: 2D Collision
Post by: amol on May 08, 2008, 02:38:01 am
Hello sir,
The motion of two ball is weired means they stick each other and after that there is no movement for both the ball.
Sometimes after hitting one ball stops  and other keep moving.

when they stop moving at that time velocities i got for ball in x and y directions are 0 and ball stops.

// Projection of the velocities in these axes
double va1=(ball[0].vx*ax+ball[0].vy*ay), vb1=(-ball[0].vy*ay+ball[0].vy*ax);
double va2=(ball[1].vx*ax+ball[1].vy*ay), vb2=(-ball[1].vx*ay+ball[1].vy*ax);

// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+1)*(va2-va1)/(1+1);
double vaP2=va2 + (1+1)*(va1-va2)/(1+1);

// Undo the projections
ball[0].vx=(int)(vaP1*ax-vb1*ay);
ball[0].vy=(int)(vaP1*ay+vb1*ax);// new vx,vy for ball 1 after collision
ball[1].vx=(int)(vaP2*ax-vb2*ay); 
ball[1].vy=(int)(vaP2*ay+vb2*ax);// new vx,vy for ball 2 after collision

Here i got the veocities 0 and ball stops.
But rest of the time collision is perfect.

Thank you.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on May 08, 2008, 11:17:30 pm
(From the information you have provided in the above message).
I think your problem is due to you did not correct the small time different between collision real happened and the time your program detect the collision.

The condition used to detect the collision in your code is dist< r1+r2
However, collision occurred when dist==r1+r2. So there is a small error. If the time step is small enough, the error can be ignored.
The problem is worse for programming in flash actionscript(because the time step is too large, 12fps?)

Please check out another message at this topic: http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg15#msg15
and you will find out how to correct it (another approximation!).


Title: Re: 2D Collision
Post by: ObsessedOne on May 18, 2008, 01:59:02 am
Hello Professor Hwang

I have been working on this simulation for quite a while now. I feel that I am very, very close. I still have the time error where they clutch together but they aren't completely stuck. Most of the time they bounce, but other times they do not. Do you see anything wrong with what I have now? I assure you it's very readable.

Note: In this case each orb is completely responsible for itself only so infinitely many orbs can be added. There are other methods and classes which I have not shown for sake of space and simplicity.


    public void draw(Graphics gBuffer, Graphics g, Image vm)
    {
        gBuffer.setColor(color);
        gBuffer.fillOval(x - velocity, y - velocity, 40, 40);
        gBuffer.setColor(Color.black);
        gBuffer.drawOval(x - velocity, y - velocity, 40, 40);
        gBuffer.drawImage(vm,0,0,this);

                // Here is one point I am wondering about
                long startTime = 0, lastTime;
                long delay=50, delta;
                lastTime = startTime = System.currentTimeMillis();
                collision = false;


        orbPhysics();
        space.repaint();
    }

    public void orbPhysics()
    {
                // Here is another point I am unsure of
                delay = 1;
                delta = System.currentTimeMillis()-lastTime;
                lastTime+=delta;
                collisionPhysics(delta/1000);
                startTime+=delay;


        bouncePhysics(); // edge of screen bouncing method (not shown)
    }
     
    // variables not shown

    public void collisionPhysics(double dt)
    {
        ArrayList<Orb> orbs = Space.orbList;
        el = 1;
        for(Orb orb : orbs)
        {
            r1 = radius;
            m1 = radius * radius;
            x1 = x + diameter/2;
            y1 = y + diameter/2;
            vx1 = xv;
            vy1 = yv;
         
            Orb other = orb;   
            r2 = other.getRadius();
            m2 = other.getRadius() * other.getRadius();
            x2 = other.getX() + other.getDiameter()/2;
            y2 = other.getY() + other.getDiameter()/2;
            vy2 = other.getVelocityY();
         
         if(x1!=x2 && y1!=y2)    // I don't know if there is a better way to test orbs for equality
         {
            dx = x1-x2;
            dy = y1-y2;
                     d = (Math.sqrt(dx*dx+dy*dy));
             
                     if(d < r1+r2)
                     {
                       vp1 = vx1*dx/d + vy1*dy/d;
                       vp2 = vx2*dx/d + vy2*dy/d;

                                       // Here is another point I am unsure of
                                       ddt = (r1+r2)/(vp1+vp2);      
                                       if(ddt > dt)
                                              ddt = 0;
                                       x1-=vx1*ddt;
                                       y1-=vy1*ddt;
                                       x2-=vx2*ddt;
                                       y2-=vy2*ddt;


                                   vp1 = vx1*dx/d + vy1*dy/d;
                                   vp2 = vx2*dx/d + vy2*dy/d;
                                   collision = true;
                                   otherOrb = other;
                     }

                                if(collision)
                     {
                                   ax = dx/d;
                                   ay = dy/d;

                                   va1 = vx1*ax + vy1*ay;
                                   vb1 = -vx1*ay + vy1*ax;
                                   va2 = vx2*ax + vy2*ay;
                                   vb2 = -vx2*ay + vy2*ax;

                                   vaP1 = va1 + (1+el)*(va2-va1)/(1+m1/m2);
                                   vaP2 = va2 + (1+el)*(va1-va2)/(1+m2/m1);

                                   vx1 = vaP1*ax-vb1*ay;
                                   vy1 = vaP1*ay+vb1*ax;
                                   vx2 = vaP2*ax-vb2*ay;
                                   vy2 = vaP2*ay+vb2*ax;

                                   xv = vx1;
                                   yv = vy1;
                                   otherOrb.setVelocityX();
                                   otherOrb.setVelocityY();
                                   collision = false;
            }
         }
      }
   }


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on May 18, 2008, 10:09:32 pm
dt =(r1+r2-d)/(vp1+vp2);// the collision should have occurred at t-dt (Actually this is also an approximation).

However, your formula is ddt=(r1+r2)/(vp1+vp2);
Please check out http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg15#msg15
------------------------------------------------------------------------------------------------------------------

I did not write java code directly since I knew about EJS. Because I use it to create java simulation (It will save me a lot of time).

I am going to show you the way I used to create java simulation:
public class javafilename extends java.applet.Applet implements Runnable{
...
   public void start(){
      //Start animating!
      if (animThread == null) {
         animThread = new Thread(this);
         animThread.start();
      }
      //Remember the starting time. of thread
      lastTime=startTime = System.currentTimeMillis();
   }
    public void stop() {
      //Stop the animating thread.
      animThread = null;
      running=false;
   }

   public void run() {
      //Just to be nice, lower this thread's priority
      Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
      //This is the animation loop.
      while (Thread.currentThread() == animThread) {
         //Advance the animation frame. with delta time
         delta=System.currentTimeMillis()-lastTime;
         lastTime+=delta;
         if(running)advanced(delta/1000.);
         startTime+=delay;
         try {
            animThread.sleep(Math.max(0,startTime-System.currentTimeMillis()));
         } catch (InterruptedException e) {
            break;
         }
      }
   }
   void advanced(double dt){// code to move particle from t to t+dt
         ...
        }
...
}



Title: Re: 2D Collision
Post by: ObsessedOne on May 21, 2008, 09:37:16 am
Hello again,

I have been trying to understand your code, but I know very little since I'm just a first year Computer Science student. I have read all your messages but my greatest problem is understanding the identifiers. I have tried your time change methods and they no longer clutch, but they still aren't colliding well.

What is vx0/vy0?
How does the variable "time" affect the program?
What is the difference between dt and ddt?
Why is delta divided by 1000 when it is passed?
Does pauseID being equal to 1 indicate a collision?
How is vn1/vn2 used?
What is eta? (elasticity/energy?)

Here is my program since the last post:

    public Orb(Space s, int orbX, int orbY, int diameter, int speed)
    {
       space = s;
       x = orbX;
       y = orbY;
       radius = diameter/2;
       velocity = speed;
       xMax = space.getAppletWidth()-diameter;
       yMax = space.getAppletHeight()-diameter;

     // This is not updated. I'm assuming it's supposed to only initialize.
         time = 0;
        delay = 50;
        startTime = 0;
        lastTime = startTime = System.currentTimeMillis();

    }
   
    public void draw(Graphics gBuffer, Image vm)
    {
         // This is updated every time the ball moves. I'm assuming this is correct.
                  delta = System.currentTimeMillis()-lastTime;
          lastTime += delta;
          orbPhysics(delta);
          startTime += delay;

        space.repaint();
    }

     public void orbPhysics(double dt)
   {
               dt/=1000;
               ArrayList<Orb> orbs = space.getOrbList();
      el = 1;
      
      for(Orb orb : orbs)
      {      
         Orb other = orb;
         
         if(x1!=x2 && y1!=y2)
         {   
            dx = x1-x2;
            dy = y1-y2;
                     d = (Math.sqrt(dx*dx+dy*dy));
             
             if(d < r1+r2)
             {
                vp1 = vx1*dx/d + vy1*dy/d;
                vp2 = vx2*dx/d + vy2*dy/d;

                 // I'm not sure if this is the way to move the particles. I use x and y for their coordinates
                                ddt = (r1+r2-d)/(vp1+vp2);
                if(ddt > dt)
                   ddt = 0;
                x1-=vx1*ddt;
                y1-=vy1*ddt;
                x2-=vx2*ddt;
                y2-=vy2*ddt;
                x = (int)x1-radius;
                y = (int)y1-radius;
                other.setX((int)x2-other.getRadius());
                other.setY((int)y2-other.getRadius());

                
                collision = true;
            otherOrb = other;
             }
             
             if(collision)
         {
            ax = dx/d;
            ay = dy/d;
            va1 = vx1*ax + vy1*ay;
            vb1 = -vx1*ay + vy1*ax;
            va2 = vx2*ax + vy2*ay;
            vb2 = -vx2*ay + vy2*ax;
            vaP1 = va1 + (1+el)*(va2-va1)/(1+m1/m2);
            vaP2 = va2 + (1+el)*(va1-va2)/(1+m2/m1);
            vx1 = vaP1*ax - vb1*ay;
            vy1 = vaP1*ay + vb1*ax;
            vx2 = vaP2*ax - vb2*ay;
            vy2 = vaP2*ay + vb2*ax;

                                // I think they should be moved forward in time here.

            xv = vx1;
            yv = vy1;
            otherOrb.setVelocityX(vx2);
            otherOrb.setVelocityY(vy2);

            collision = false;
         }
      }
   }
 }


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on May 21, 2008, 05:11:44 pm
What is vx0/vy0?
Because user can change the coordinate system, vx0,vy0 is the offset when changing the system. In your case, both of them will be 0.

How does the variable "time" affect the program?
 time stored the real time value in second. it will starts to count when you click Start button.

What is the difference between dt and ddt?
dt is the time step in second.
ddt is used for correct the time step, because when you detect two particle collide (d12We need to move time backward to d12==r1+r2 and ddt is the time needed to move particle backward.
Did you read the posted message I have suggested ?

Why is delta divided by 1000 when it is passed?
delta is the time in milli-second (ms).

Does pauseID being equal to 1 indicate a collision?
If the checkbox cont. is not checked, the simulation will paused when collision occurred.

How is vn1/vn2 used?
Calculate the normal components of the velocity.

What is eta? (elasticity/energy?)
Yes. for in-elastic collision. it can be ranged between 0-1.

The way you are coding is not the standard way. You should used the method I have suggested (which will give you almost the same simulation regarding different computer speed).


Title: Re: 2D Collision
Post by: ObsessedOne on May 22, 2008, 10:25:33 am
Yes! I have it!
Once I understood what the difference between dt and ddt was I understood everything perfectly. Now I will concentrate on efficiency over readability.

Thank you very much Professor Hwang!


Title: Re: 2D Collision
Post by: ObsessedOne on May 26, 2008, 04:53:10 am
Sorry to ask a non-physics related question, but how did you set the coordinates for your Choice menus? Mine default to the top center of my applet.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on May 26, 2008, 08:47:54 am
You need to set the LAYOUT for the applet. Please search with "applet layout".


Title: Re: 2D Collision
Post by: gap89 on June 10, 2008, 04:16:41 pm
Hello Professor.

Normally we are calculating the resultant vector from the initial velocity. Is it possible to do it the inverse way? assuming that the second object is stationary. Which just means I am trying to calculate the vector needed to collide with a stationary object to push the second object in a specific direction.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on June 10, 2008, 11:55:37 pm
Yes. You can!
Write down the equation for conservation of momentum and conservation of energy, then solve it!


Title: Re: 2D Collision
Post by: gap89 on June 11, 2008, 02:13:07 pm
Hmm.. I am still quite lost.

I tried doing the inverse way by using the equations you have given, as I am using it for programming too, but it was hard to get the answer.

Since object 2 is stationary, va2 and vb2 should be 0.

Assuming I know what is the final vx2 and vx1, and also getting vap1 = 0.05*va1 ( ed = 0.9 ), vap2 = 0.95 * va1, so how do I continue from here? Or I can't do it this way?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on June 11, 2008, 05:06:44 pm
You should derive new equations instead of working from the equations in the current simulation.
It is a different problem and the equations will be different.

Please try to derive the equation from conservation of momentum and conservation of energy.
And solve the combined equations.

If your condition is push the second into a specific direction and no more, there are many possible solution (not just one).
Because for 2D case, you only have 3 equations. But you have 5 unknown variables.


Title: Re: 2D Collision
Post by: HaydenG on June 18, 2008, 01:11:51 pm
Hi, Im sorry to bother you buy could you please tell me what is wrong with this equation
I apologize im not very good at programming

Public Type PhysObj
    X As Double
    Y As Double
    Xv As Double
    Yv As Double
    m As Integer 'mass
    r As Integer 'radius
End Type

Public Function BallTouch(a As PhysObj, b As PhysObj, ed As Integer)
    Dim dx As Double
    Dim dy As Double
    Dim d As Double
    Dim ax As Double
    Dim ay As Double
    Dim ava As Double
    Dim avb As Double
    Dim bva As Double
    Dim bvb As Double
    Dim vapa As Double
    Dim vapb As Double
    Dim vpa As Double
    Dim vpb As Double
    Dim dt As Double
    dx = a.X - b.X
    dy = a.Y - b.Y
    d = Sqr((dx * dx) + (dy * dy))
    ax = dx / d
    ay = dy / 2
    ava = (a.Xv * ax) + (b.Yv * ay)
     avb = (-a.Xv * ay) + (a.Yv * ax)
     bva = (b.Xv * ax) + (b.Yv * ay)
     bvb = (-b.Xv * ay) + (b.Yv * ax)
     vapa = ava + (1 + ed) * (bva - ava) / (1 + (a.m / b.m))
     vapb = bva + (1 + ed) * (ava - bva) / (1 + (b.m / a.m))
     vpa = (a.Xv * dx) / d + (a.Yv * dy) / d
     vpb = (b.Xv * dx) / d + (b.Yv * dy) / d
     dt = (a.r + b.r - d) / (vpa + vpb)
     
    If d < a.r Then
     a.X = a.X - (a.Xv * dt)
     b.X = b.X - (b.Xv * dt)
     a.Y = a.Y - (a.Yv * dt)
     b.Y = b.Y - (b.Yv * dt)
     a.Xv = vapa * ax - avb * ay
     a.Yv = vapa * ay + avb * ax
     b.Xv = vapb * ax - bvb * ay
     b.Yv = vapb * ay + bvb * ax
     a.X = a.X + (a.Xv * dt)
     b.X = b.X + (b.Xv * dt)
     a.Y = a.Y + (a.Yv * dt)
     b.Y = b.Y + (b.Yv * dt)
    End If
       
End Function

Thank you ;D


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on June 18, 2008, 07:31:06 pm
Why ay = dy / 2 ???


Title: Re: 2D Collision
Post by: saeky123 on July 19, 2008, 06:24:28 pm
Hi professor, and thanks for your help...
I have followed your post. But I have a question, have you ever worked on  collision in 2d with 3 or more balls. I means that collision with more than 2 balls. In this case, I can't use d for distance between 2 balls. I wondered if I use a matrix that store all the boundary of the balls. So that, when the balls collide, the matrix will meet together. Or, maybe, I have to store many d for distance between balls. For example, if I have 3 balls, I use d1 for distance between ball 1 and 2, d2( for ball 2 and 3) and d3(of course, distance between ball 1 and 3).

Can you give me any suggestions?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 19, 2008, 11:04:43 pm
There are several examples of many particles collide with each other at this web site. You can check out those EJS examples and find out how I did it.
Besically, it can be done in the following way:
Suppose you have defined a function to take care collision between two particles:

public function collision(int i,int j, double m[],double x[],double y[], double vx[],double vy[]){
// the code should take care of the collision between particle i, and particle j
}

Then for collision between n particles : you can have the following loops to deal with all the collisions
for(int i=0;i<n;i++){
 for(int j=i+1;j<n;j++){
   collision(i,j,m,x,y,vx,vy);
 }
}


Title: Re: 2D Collision
Post by: venice on August 27, 2008, 11:23:32 am
great article ..

but there is a error in post 7..where this statement
dt =(r1+r2-d)/(vp1+vp2) should be as dt =(r1+r2-d)/(vp1-vp2)...

and i wonder if it's possible to do this without using double..
instead just use integer..??

many calculation like division in this method come out many double typed value..

coz i intend to do this collision method in my mobile phone game


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on August 27, 2008, 04:35:20 pm
The equation is corrected. Thank you!
It is possible to find way to work with integer only but the result will has some error.
It it true that there is no double type in programming for mobile device? How could that be ???


Title: Re: 2D Collision
Post by: ArdTraveller on January 12, 2009, 12:12:23 pm
Sir, like how you've provided the complete and runnable source code for this 2D collision can u pleaz provide the similar type of code for the 2D Collision the new one, thx


Title: Re: 2D Collision
Post by: amol on January 13, 2009, 09:16:30 pm
Hi professor,

Can u please elaborate these two lines with respect to ur post#7:


// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+ed)*(va2-va1)/(1+mass1/mass2);
double vaP2=va2 + (1+ed)*(va1-va2)/(1+mass2/mass1);
// Undo the projections
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 13, 2009, 09:43:54 pm
I hope you understand that we have transfer 2D collisions to two 1D collision.
Do you fully understand the above part?

// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+ed)*(va2-va1)/(1+mass1/mass2);
double vaP2=va2 + (1+ed)*(va1-va2)/(1+mass2/mass1);

The above equations calculate velocity for those two particle just after the collision.

Do you konw/unstand how to calculate 1D elastic collision problem?
If you set ed=1, the above equation will be the same as equations for 1D elastic collision.

Then,we need to move back to our original x-y coordinate.
// Undo the projections
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision


Please write down the physics you know about collision in detail, so that we can focus on your problem!


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 14, 2009, 04:46:44 pm
Due to so many requests from the users, source code for this applet is distributed with the ZIP files you will receive if you click get file for offline use button.


Title: Re: 2D Collision
Post by: Question on January 15, 2009, 09:54:38 am
Sir was this applet created using EJS?


Title: Re: 2D Collision
Post by: Question on January 15, 2009, 10:00:33 am
Sir, thx for the code for this applet, could u help me sir, at what part of the could can i change so that there is a slider in order ro change the mass and velocity of the balls and what code to enable me to drag the ball and change the direction of the ball,similar to the Collision 2D or the latest one u created,thx :)


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 15, 2009, 10:52:19 am
This topic is under JDK1.0.2 simulations (1996-2001) (http://www.phy.ntnu.edu.tw/ntnujava/index.php#2) board.
Please check out Easy Java Simulations (2001- ) (http://www.phy.ntnu.edu.tw/ntnujava/index.php#3) board for simulations created with EJS.

If you just need collison 2D, please check out  EJS version cololision2D (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=120.0)


Title: Re: 2D Collision
Post by: slenzi on January 28, 2009, 04:47:37 am
I'm finding that when the velocity of the two balls in the Y axis is 0 (the balls collide head on) they stick together. I'm just using your code and don't have a full understanding of it. Basically just checking to see if I'm doing something wrong. It works just fine if the balls are moving in both axis.

I'm finding that ddt = 0 in this case and its messing it up.

Code:

// Velocity of ball b1 in direction of ball b2
double vab1 = (b1.getVelocityX() * (dx/distance)) + (b1.getVelocityY() * (dy/distance));
// Velocity of ball b2 in direction of ball b1
double vab2 = (b2.getVelocityX() * (dx/distance)) + (b2.getVelocityY() * (dy/distance));
// The collision will have actually happened at ddt before we detect
// distance <= (r1 + r2) collision.
double ddt = (r1 + r2 - distance) / (vab1 - vab2);


// using ddt, move the balls backwards so they don't overlap. Now the distance
// between the two balls should be r1 + r2.
b1.setLocation(b1.x -= (b1.velocityX * ddt), b1.y -= (b1.velocityY * ddt));
b2.setLocation(b2.x -= (b2.velocityX * ddt), b2.y -= (b2.velocityY * ddt));

// Unit vector in the direction of the collision
double ax = dx / distance;
double ay = dy / distance;

// Projection of the velocities in these axes
double va1 = b1.velocityX * ax + b1.velocityY * ay;
double vb1 = -b1.velocityX * ay + b1.velocityY * ax;
double va2 = b2.velocityX * ax + b2.velocityY * ay;
double vb2 = -b2.velocityX * ay + b2.velocityY * ax;

// ed=1 for elastic collision, ed<1 for inelastic (material of ball absorbs some energy)
double ed = 1;

// new velocities in these axes (after collision)
double vaP1 = (va1 + (1 + ed ) * (va2 - va1)) / (1 + ((b1.getMass() / b2.getMass())));
double vaP2 = (va2 + (1 + ed ) * (va1 - va2)) / (1 + ((b2.getMass() / b1.getMass())));

// undo projections
b1.setVelocityX((vaP1*ax)-(vb1*ay)); b1.setVelocityY((vaP1*ay)+(vb1*ax));
b2.setVelocityX((vaP2*ax)-(vb2*ay)); b2.setVelocityY((vaP2*ay)+(vb2*ax));

// earlier we moved time backwards one unit, so now we move time forward one unit.
b1.setLocation(b1.x += b1.getVelocityX() * ddt, b1.y += b1.getVelocityY() * ddt);
b2.setLocation(b2.x += b2.getVelocityX() * ddt, b2.y += b2.getVelocityY() * ddt);
);


Title: Re: 2D Collision
Post by: slenzi on January 28, 2009, 05:02:58 am

OK, since ddt was 0 I did this and that seems to have corrected the problem. 


Code:

if(ddt > 0.0){
b1.setLocation(b1.x -= (b1.velocityX * ddt), b1.y -= (b1.velocityY * ddt));
b2.setLocation(b2.x -= (b2.velocityX * ddt), b2.y -= (b2.velocityY * ddt));
}else{
b1.setLocation(b1.x -= (b1.velocityX), b1.y -= (b1.velocityY));
b2.setLocation(b2.x -= (b2.velocityX), b2.y -= (b2.velocityY));
}



Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 28, 2009, 10:51:17 am
You did not really solve the problem. You just ignore it.

latest 2D collision created with EJS (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=120.0)
starts with head on collision and it work fine.

I think the problem might be due to the condition you check for the collision occurred.
May be you have some other bug in the code.

P.S. The above code you copy from was not my original code.
Please check out my original message (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg15#msg15)



Title: Re: 2D Collision
Post by: slenzi on January 29, 2009, 12:15:05 am
Thanks for the reply. I think I found the problem. I removed the if ddt > 0 and it seems to work.


You did not really solve the problem. You just ignore it.

latest 2D collision created with EJS (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=120.0)
starts with head on collision and it work fine.

I think the problem might be due to the condition you check for the collision occurred.
May be you have some other bug in the code.

P.S. The above code you copy from was not my original code.
Please check out my original message (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg15#msg15)




Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 29, 2009, 08:05:11 am
You can change it to if(ddt>=0)


Title: Re: Java Code for collision in 2D
Post by: ashmpatel on April 28, 2009, 09:40:53 pm
Hi,

I wonder if someone can help with the bit below that I do not understand.
In the bit of the code that works out the velocities ,what is the reason for vb1, vb2.
I can see in the code that it is used to undo the projections but these vb1 & vb2 do not looks like
va1 and va2 -
so for example va1 has vx1*ax and vb1 has -vx1*ay , why ay and not ax as surely you want the reverse of the x velocity but why is ay being used.

Is it possible to have some pics attached to these calculations so I can see what is being worked out ?

Also, in the java code, the method called "advance" is called to work out the new positions.
where in this method is the bit that updates the vecloty of x1 and x2 after a collision has been detected ?
I can see the code works as I have compiled and run it but I do NOT see where the velocities have been set after the collision detection stuff.




double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);

Due to so many email questions asking for help. I re-wrote this post to include more detail calculation steps:

Assume the radius for two ball are r1 and r2, and the coordinates are (x1,y1) and (x2,y2).
Usually, we calculate the distance between two balls d=sqrt( (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));

The collision should have occurred if d equal r1+r2; // if(d==r1+r2)

However, there is a finite time step dt in the simulation calculation,so most often we would not be able to find the above condition (exact time when two ball real occurred).
So we check if d<= r1+r2; Then we know the collision should have occurred.

The real collision should have occurred before you detected that the distance between two center of the balls d is less than the sum of those two balls r1+r2. (d< r1+r2)

The correct way is to find the time when the two ball really collide with each other.
Suppose the center of those two ball are x1,y2 and x2,y2
dx=x2-x1, dy=y2-y1; d=sqrt(dx*dx+dy*dy);

First calculate the component of velocity in the direction of (dx,dy)
vp1= vx1 *dx/d+vy1*dy/d;
vp2= vx2*dx/d+vy2*dy/d;

Collision should have happened dt before you have detected r1+r2<d;
 and dt =(r1+r2-d)/(vp1-vp2);
 and dt =(r1+r2-d)/(vp1-vp2);// the collision should have occurred at t-dt (Actually this is also an approximation).

So you should move those two ball backward
 x1-= vx1*dt;
 y2 -= vy1*dt;
 x2-=vx2*dt;
 y2-=vy2*dt;

Now the distance between center of the two balls is d'=r1+r2;

The following code take care of collision:

double dx = x2-x1, dy = y2-y1;
// where x1,y1 are center of ball1, and x2,y2 are center of ball2
double distance = Math.sqrt(dx*dx+dy*dy);
// Unit vector in the direction of the collision
double ax=dx/distance, ay=dy/distance;
// Projection of the velocities in these axes
double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);
// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+ed)*(va2-va1)/(1+mass1/mass2);
double vaP2=va2 + (1+ed)*(va1-va2)/(1+mass2/mass1);
// Undo the projections
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision

Because we have move time backward dt, we need to move time forward dt.
so
  x1+= vx1'*dt;
  y1+=vy1'*dt;
  x2+=vx2'*dt;
  y2+=vy2'*dt;

Now the distance between two ball will be larger than r1+r2.

If you did not correct the time dt (before you have found collision occurred, you will find balls clutch together. and they don't even let go.




Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on April 29, 2009, 12:29:44 am
Before collision:
va1, va2 are velocity components in the direction of the line connected between two center of the collided objects.
vb1, vb2 are velocity components in the direction perpendicular to the above line.
after collision:
vap1, vap2 are velocity components in the direction of the line connected between two center of the collided objects.
vb1, vb2 are velocity components in the direction perpendicular to the above line. (if there is no fricion force between collision objects, vb1,vb2 did not change during the collision.)

and the following equation calculate the x,y component for the above vectors
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision

You need to understand the meaning of inner product in order to understand the above equations.
Please check out scalar product between two vectors (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=51.msg2572#msg2572)


Title: Re: 2D Collision
Post by: seenu on May 01, 2009, 02:21:28 am
Hi professor Fu-kwun Hwang,

Firstly i would like to thank you for all your help, this is an excellent place to learn physics.
i have gone through the code and understand most of it.

i have good understand of dot product (scalar product), and its application to find projection of one vector onto the other.
but i am having problem understanding the undo projections
// Undo the projections
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision

after breaking up the velocity into 2 components ( one onto the direct line of contact of balls , and other as a perpendicular )

How did u arrive at the formula to combine the new velocity with the velocities in perpendicular direction
to arrive at the new vx1 and vy1 for the ball ?
Can you please explain this in detail.

thank you  :)


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on May 01, 2009, 08:05:02 am
The vector sum of vap1+vb1 is the velocity for particle/circle 1 after collision, and the sum of vap2+vb2 is the velocity for particle/circle 2 after collision.
We need to break the above vectors into x-component and y-component to add them directly.

(ax,ay)  is the unit vector in the direction connected two objects.
draw a line connect two object, assign the angle between this line and x-axis is θ,
then  cosθ=ax, sin θ=ay
So vap1*ax=vap1*cosθ give x-component of vap1, and vap1*ay give y-component of vap1

Because vb1 and vb2 is in the direction perpendicular to the (ax,ay)
,then the angle between vb1 and x-axis is φ=θ+π/2
so cos φ=cos(θ+π/2)=-sinθ=-ay, sinφ=sin(θ+π/2)=cosθ=ax
to calculate x-component of vb1 we need to calculate vb1*cos φ=vb1*(-ay)=-vb1*ay
,and (y-component of vb1) = vb1*sinφ=vb1*ax


Title: Re: 2D Collision
Post by: seenu on May 01, 2009, 06:15:09 pm
Hi again,

 ;D Now i understand how this is done.
in order to get the resultant new velocity for each ball , we add the new velocity vector to the perpendicular vector.
I am working on a demo applet to demonstrate this with many balls. I will post it once it is done.

Thank you  :)


Title: Re: 2D Collision
Post by: jesims on May 06, 2009, 10:06:16 pm
cool post! very interesting!
-*-


Title: Re: 2D Collision
Post by: batman009 on June 05, 2009, 04:04:39 pm
wonderful! thanks for the info..


Title: Re: 2D Collision
Post by: thegimel on June 09, 2009, 04:33:42 am
excellent job breaking the physics/code down into easy bits and pieces!

i only have one question regarding the first part of the collision, where you take them back time dt so they exactly touch and don't overlap.

when you calculate the time you want to "playback" the system you use this formula: dt =(r1+r2-d)/(vp1-vp2).

then you take back the x,y coordinates by -vx/vy*dt

but what happens if (vp1-vp2) is negative, then the whole "dt" value is negative? after all, vp1 and vp2 are the values of the velocities, and it is possible that (vp1-vp2) is negative, no?



Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on June 09, 2009, 08:18:06 am
Good question.

dx=x2-x1, dy=y2-y1; $d=\sqrt{dx^2+dy^2}$;
vp1= vx1 *dx/d+vy1*dy/d;
vp2= vx2*dx/d+vy2*dy/d;
dt =(r1+r2-d)/(vp1-vp2);

The above equation using vector form (inner product).
$\hat{d}=\frac{\vec{x_2}-\vec{x_1}}{|\vec{x_2}-\vec{x_1}|}$, i.e. (dx/d,dy/d), is a unit vector.
$v_{p1}=\vec{v_1}\cdot \hat{d}$ and $v_{p2}=\vec{v_2}\cdot \hat{d}$ are results of inner product, both of them can be either positive or negative.

if (vp1-vp2) is negative, then the collision should not have happened.
For example: assume vy1=vy2=0 to make it simple to be understood.
dx coulbe be positive or negative:
1. if dx>0, i.e. x2>x1: it will require vx1>vx2 for collision to happened.
2. if dx<0, i.e. x2<x1: it will requires vx1<vx2 for collision to happened.
(vx1 and vx2 can be positive or negative for the above two cases)

That is the beauty of using vector to process the problem.


Title: Re: 2D Collision
Post by: thegimel on June 09, 2009, 08:23:57 pm
Got it!

Thanks alot :)


Title: Re: 2D Collision
Post by: rahulpawar on June 28, 2009, 04:25:27 am
Hello prof.
   i've problem. In this i want to simulate collision of 2 round pieces basically the same problem for which u have given the code. But in my case i "want" these to have reducing velocity, a deacceleration due to frictional force due to surface on which the pieces are sliding. Can u explain how this can be achived programatically ? A source code will be very helpful ?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on June 28, 2009, 08:26:42 am
Those two particles move with the same velocity when there is no collision.
For example: x+= vx*dt;

To change the velocity, it means that acceleration is not zero.
$\vec{a}=\tfrac{d\vec{v}}{dt}$
If acceleration is in the same direction as velocity, then the velocity will increase, otherwise it will decrease.
There are many way you can slow download the particle: you need to add a acceleration depend on what kind of situation need to be simulated.

For slidding friction: The friction force is $\mu N$, where N is the normal force (N=mg if it is a horizontal surface).
But you need to take care it is always in the opposition direction of the velocity.
And when it is stopped, the friction should disappear (You need to check this,too!).
I will leave it as an exercise for you.
Please try out to solve it by yourself. If you still can not solve it, write down what you did and what is the problem.
I will try to help after you have tried to help yourself.  You will enjoy the fun when you solve it by yourself. :-)



Title: Re: 2D Collision
Post by: rahulpawar on June 29, 2009, 06:22:52 pm
hello prof.
      i went through the collision2D.java file there some variables are present within comment to implement "friction". Now the piece do slow down but they keep moving with small velocity after many collision. How do i go around ? The code is same as collision2D.java with comments removed. Also in my case i need the x,y cords & velocity of piece [ 1)initially, 2)at time of impact & 3)final position when velocity become 0] before actual display of pieces begin. That mean total algo is of 2 parts 1)calulation of cords & velocity and storing them in a array or struct(linkedlist) 2)displaying of pieces usinig that stored values. As u can see this is diff than what your applet does both at the same time. How to seperate them ?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on June 30, 2009, 12:26:14 pm
The friction was not implemented properly in the code and it was not needed so it was commented out.
You need to determined what kind of friction you want to implemented.
Is it a constant friction force or a friction force which is proportional to velocity(e.g. particle moving in water)or event proportional to velocity square (small particle moving in air).

Change velocity as time move and check if velocity change sign to stop it (this is the point object fully stopped).

You can add code to disable display the view if you just want to stored all the data first without display it.
Then you need to add code to show the the drawing from the stored data. You need to allocate enough array to stored all the position (x,y) for each time steps.

Actually, you can calculate the time/position when/where two balls collide with each other and calculate how long the ball will move after collision. It can be done but you need to write down equations and solve it.
For example: if the velocity after collision is v. If the friction is F, then the longest distance traveled is d=mv2/2a

May I know what is the reason for your design? What is the purpose? May be there are better way to do it.


Title: Re: 2D Collision
Post by: rahulpawar on June 30, 2009, 05:11:45 pm
hello Prof,
             i have attached a doc file it contain a detail info about the problem to be solved.

                                               thnx.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 01, 2009, 09:33:27 am
I created the following applet. It is similar to what you want.
You can change initial positions with different initialization code and add rules for your game.

You can drag from the center of the blue particle to change it's velocity when it is in paused state.
The blue particle will start to move when you release the mouse.
You can change the friction coefficient mu and elastic coefficient k.
k=1 means elastic collision without energy. k<1 then energy is loss due to collision.

Because the particle move in the same direction when there is no collision.
The friction force $F=\mu N= \mu m g$, from $F=ma$
The energy loss is $\vec{F}\cdot d\vec{s}= F d$ where d is the distance traveled.
d can be calculated between each time step.
And kinetic energy will be loss due to friction.  $\tfrac{1}{2}mv'^2=\tfrac{1}{2}mv^2- F d$
So I re-calculate velocity after each time step.
And if the right hand side become smaller than zero, it means that the particle should have been stopped.
(So velocity has to be set to zero).

I think I should only help you from the physics point of view.
The rest work should be your job, waiting for you to finish it.

I will be glad to help you if you have questions related to physics!


Title: Re: 2D Collision
Post by: rahulpawar on July 01, 2009, 05:32:39 pm
hello prof,
          Thank you for your help and guidance. I'll soon complete the project and inform you.
          Thank you again !


Title: Re: 2D Collision
Post by: PrabhuKumar on July 17, 2009, 10:21:07 pm
Hello Professor!

Thank you for all that you have shared and helped people understand these concepts with more clarity. I recently started looking into graphics on Windows Mobile phones and thanks to you I was able to come up with a colliding marbles program pretty quickly. If you are interested here is the link:

http://geekswithblogs.net/TechTwaddle/archive/2009/07/16/bouncingcolliding-marbles-directdraw-part-7.aspx

Sometimes there is a problem with the program. The balls will stick or completely disappear from the screen. But it happens very rarely, maybe around 1 in 30 times. I haven't yet looked deeply into the problem. Well, that is my next task (:

Thank you again and I really appreciate your work.
Prabhu


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on July 18, 2009, 08:30:02 am
There is an assumption for all the above discussion:
The time step dt need to be smaller enough (which is depend on velocity V and diameter of the ball R).
V*dt<< R ( dt<0.1*R/V should be fine).

If V*dt ≒ R , the approximation used in the calculation (finding the time collision really occurred) is not valid.

So you should adjust time step (or set maximum value for V) to satisfy the above condition.


Title: Re: 2D Collision
Post by: vanmobi on September 03, 2009, 10:04:16 am
When m1 = m2, is it normal that the sum of the speed of the 2 balls does not remain constant over time?



Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on September 03, 2009, 11:36:13 am
Conservation of momentum require
$m_1 \vec{v_1}+m_2\vec{v_2}=m_1 \vec{v_1}'+m_2\vec{v_2}'$
If $m_1=m_2$, it reduced to
$ \vec{v_1}+\vec{v_2}= \vec{v_1}'+\vec{v_2}'$

Velocity is a vector which is not the same a speed!
You can check that the sum of x (or y) component of velocity should be the same before and after collision (when $m_1=m_2$)


Title: Re: 2D and 3D Elastic Collision Solutions
Post by: Thomas on January 01, 2010, 11:50:19 pm
Anybody looking into the physics of 2D and 3D- elastic collisions may also be interested in my pages http://www.plasmaphysics.org.uk/collision2d.htm and http://www.plasmaphysics.org.uk/collision3d.htm which represent direct and general solutions of the problems. I have also written corresponding Fortran and C++ codes for this ( see http://www.plasmaphysics.org.uk/programs/coll2d_for.htm , http://www.plasmaphysics.org.uk/programs/coll2d_cpp.htm , http://www.plasmaphysics.org.uk/programs/coll3d_for.htm , http://www.plasmaphysics.org.uk/programs/coll3d_cpp.htm ) which are free to use for everybody.

**************
Note that there was a bug in the collision detection routine of the 2D-versions of my programs (this led in certain cases to collisions being detected when in fact there were none). I have corrected this now. I have also made minor changes to the code in order to improve speed. Furthermore I have added a simplified version to the 2D-routines that does not not contain the collision detection routine but just returns the new velocities assuming that the input coordinates are already those of the collision.

Thomas, 11.Dec.05
*******************

Please note that I modified the code in my routines now such as to work for (partially) inelastic collisions as well. This was simply achieved by subtracting the velocity of the center of mass from the final velocities for the elastic collision case, multiplying this by the restitution coefficient (which is an additional input parameter) and adding the velocity of the center of mass on again.

Thomas


Title: Re: 2D Collision
Post by: mubbashar on January 05, 2010, 02:14:51 am
hello professor
i read your equations about 2d collision but did not understand these steps

// Projection of the velocities in these axes
double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);
// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
double vaP1=va1 + (1+ed)*(va2-va1)/(1+mass1/mass2);
double vaP2=va2 + (1+ed)*(va1-va2)/(1+mass2/mass1);
// Undo the projections
vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision

why we need vb1 and vb2 ?? and also what is your means by undo projection..
actually sir i am doing work on molecular dynamics in gas and when particals are collide we use your model of 2d collision is this correct for us to use these equations at the time of collision ??


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 05, 2010, 10:20:56 pm
In the real world, time move continuously.
However, we can not do the calculation continuously. It is always a finite time step (no matter how small it might be).

The time step dt is the same during the simulation.
However, collision often occurred in between time steps (between time t to t+dt).

We tried to detect if two object overlap each to know colllision should have occurred.
Then, we need to find the exact time when collision occurred.
If this 2D collision, we use an approximation method to find the time when collision occurred.
Support the rasius of two particles are r1 and r2, and the distance between two center is d.
And the relative velocity along two center is vp,
then we move back time step ddt=(d-(r1+r2))/vp to find the time collision occurred.
(The above approximation is only good if the relative velocity is small enrough, i.e. vp*dt<
After we take care of collision, we need to move time forward ddt again.


Title: Re: 2D Collision
Post by: lookang on January 05, 2010, 10:28:56 pm
The time step dt is the same during the simulation.
However, collision often occurred in between time steps (between time t to t+dt).

We tried to detect if two object overlap each to know collision should have occurred.
Then, we need to find the exact time when collision occurred.
If this 2D collision, we use an approximation method to find the time when collision occurred.
Support the radius of two particles are r1 and r2, and the distance between two center is d.
And the relative velocity along two center is vp,
then we move back time step ddt=(d-(r1+r2))/vp to find the time collision occurred.
(The above approximation is only good if the relative velocity is small enough, i.e. vp*dt<
After we take care of collision, we need to move time forward ddt again.

This is a computational logic that i only appreciated and understood after using Ejs to make simulations, because i was trying to do the same thing. "detect if two object overlap each to know collision should have occurred."

In Ejs i think it is called Event Handlers.
Thanks!
it is good explanation.


Title: Re: 2D Collision
Post by: hellmaster on March 20, 2010, 11:44:11 am
This is helpful, keep learning. Thanks


Title: Re: 2D Collision
Post by: jenny.smith on July 23, 2010, 08:07:04 pm
If you do not believe that the bounding box collision would be good for your preflight you should try the circle of its bounding box .. then it really does not matter. Check two circles overlap is much easier to see, too, at least in my opinion.


Title: Re: 2D Collision
Post by: ursan on September 05, 2010, 03:40:54 am
Hi all.
collision is a problem when I do the formula and the balls is stopped. do not understand why they stopped. I have the following code.


      double  x1=ball.center.x,  y1=ball.center.y,  x2=balltwo.center.x,  y2=balltwo.center.y,
      vx1=ballspeedx,  vy1=ballspeedy,  vx2=balltwospeedx,  vy2=balltwospeedy;
       
      
      double dx = x2-x1, dy = y2-y1;
      // where x1,y1 are center of ball1, and x2,y2 are center of ball2
      double distance = sqrt(dx*dx+dy*dy);
      // Unit vector in the direction of the collision
      double ax=dx/distance, ay=dy/distance;
      // Projection of the velocities in these axes
      double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
      double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);
      // New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
      double vaP1=va1 + (1+1)*(va2-va1)/(1+1);
      double vaP2=va2 + (1+1)*(va1-va2)/(1+1);
      // Undo the projections
      vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
      vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision
      
       ballspeedx =  vx1;
      ballspeedy =  vy1;
      balltwospeedx =  vx2;
      balltwospeedy =  vx2;
      
      ball.center = CGPointMake(ball.center.x + ballspeedx, ball.center.y + ballspeedy);
      balltwo.center = CGPointMake(topbir.center.x + balltwospeedx, topbir.center.y + balltwospeedy);
or


      double  x1=ball.center.x,  y1=ball.center.y,  x2=balltwo.center.x,  y2=balltwo.center.y,
      vx1=ballspeedx,  vy1=ballspeedy,  vx2=balltwospeedx,  vy2=balltwospeedy;
       
      
      double dx = x2-x1, dy = y2-y1;
      // where x1,y1 are center of ball1, and x2,y2 are center of ball2
      double distance = sqrt(dx*dx+dy*dy);
      // Unit vector in the direction of the collision
      double ax=dx/distance, ay=dy/distance;
      // Projection of the velocities in these axes
      double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
      double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);
      // New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
      double vaP1=va1 + (1+1)*(va2-va1)/(1+1);
      double vaP2=va2 + (1+1)*(va1-va2)/(1+1);
      // Undo the projections
      vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
      vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision
      
       ballspeedx =  vx1;
      ballspeedy =  vy1;
      balltwospeedx =  vx2;
      balltwospeedy =  vx2;

       dx=x2-x1, dy=y2-y1; d=sqrt(dx*dx+dy*dy);
      
       double vp1= vx1 *dx/d+vy1*dy/d;
      double vp2= vx2*dx+vy2*dy/d;
       double dt =(r1+r2-d)/(vp1+vp2);
      
       x1-= vx1*dt;
      y1 -= vy1*dt;
      x2-=vx2*dt;
      y2-=vy2*dt;
      
      ball.center = CGPointMake(x1, y1);
      balltwo.center = CGPointMake(x2, y2);

       x1+= vx1*dt;
      y1+=vy1*dt;
      x2+=vx2*dt;
      y2+=vy2*dt;
      
      ball.center = CGPointMake(x1, y1);
      balltwo.center = CGPointMake(x2, y2);

       ball.center = CGPointMake(ball.center.x + ballspeedx, ball.center.y + ballspeedy);
      balltwo.center = CGPointMake(topbir.center.x + balltwospeedx, topbir.center.y + balltwospeedy);


the same in both programs. example:
     ballspeedx=0;ballspeedy=4;balltwospeedx=0;balltwospeedy=-4;

3. After the collision the ball is stopped and disappear from the screen. vx1 ,vy1,vx2,vy2 values is -2145444...
please help me, collision problems like this a month to go before me...


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on September 05, 2010, 09:45:39 pm
The above code works under the following assumption: v*dt<< R, where R is the radius of the ball.
It means that the time step need to be chose properly.


Title: Re: 2D Collision
Post by: ursan on September 06, 2010, 01:15:28 am
I'm sorry I did not understand. v What is the speed of the ball. vx1,vx2,vy1 or vy2.  complate code is;

-(void) tophareket {
    ballspeedx=0; ballspeedy=4; balltwospeedx=0; balltwospeedy=-4;
   
   // top top1'e değerse
   if(sqrt(pow((balltwo.center.x-ball.center.x),2)+pow((balltwo.center.y-ball.center.y),2))<38)
   {   
      double  r1=19, r2=19, m1=1, m2=1, x1=ball.center.x,  y1=ball.center.y,  x2=balltwo.center.x,  y2=balltwo.center.y,
      vx1=ballspeedx,  vy1=ballspeedy,  vx2=balltwospeedx,  vy2=balltwospeedy;
      
      
      double dx = x2-x1, dy = y2-y1;
      // where x1,y1 are center of ball1, and x2,y2 are center of ball2
      double distance = sqrt(dx*dx+dy*dy);
      // Unit vector in the direction of the collision
      double ax=dx/distance, ay=dy/distance;
      // Projection of the velocities in these axes
      double va1=(vx1*ax+vy1*ay), vb1=(-vx1*ay+vy1*ax);
      double va2=(vx2*ax+vy2*ay), vb2=(-vx2*ay+vy2*ax);
      // New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
      double vaP1=va1 + (1+1)*(va2-va1)/(1+1);
      double vaP2=va2 + (1+1)*(va1-va2)/(1+1);
      // Undo the projections
      vx1=vaP1*ax-vb1*ay;  vy1=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
      vx2=vaP2*ax-vb2*ay;  vy2=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision
      
      ballspeedx =  vx1;
      ballspeedy =  vy1;
      balltwospeedx =  vx2;
      balltwospeedy =  vx2;
      
      dx=x2-x1, dy=y2-y1; d=sqrt(dx*dx+dy*dy);
      
      double vp1= vx1 *dx/d+vy1*dy/d;
      double vp2= vx2*dx+vy2*dy/d;
      double dt =(r1+r2-d)/(vp1+vp2);
      
      x1-= vx1*dt;
      y1 -= vy1*dt;
      x2-=vx2*dt;
      y2-=vy2*dt;
      
      ball.center = CGPointMake(x1, y1);
      balltwo.center = CGPointMake(x2, y2);
      
      x1+= vx1*dt;
      y1+=vy1*dt;
      x2+=vx2*dt;
      y2+=vy2*dt;
      
      ball.center = CGPointMake(x1, y1);
      balltwo.center = CGPointMake(x2, y2);
      
      ball.center = CGPointMake(ball.center.x + ballspeedx, ball.center.y + ballspeedy);
      balltwo.center = CGPointMake(topbir.center.x + balltwospeedx, topbir.center.y + balltwospeedy);
    }

and I tried the java programs you provide, tenth the collision happened. I wonder where I made a mistake?


-(void) tophareket {
   
    // top top1'e değerse
   if(sqrt(pow((topbir.center.x-top.center.x),2)+pow((topbir.center.y-top.center.y),2))<41)
   {   
        double alpha,   m1=1,  m2=1,  r1=19,  r2=19,
      x1=top.center.x,  y1=top.center.y,  x2=topbir.center.x,  y2=topbir.center.y,
      vx1=topspeedx,  vy1=topspeedy,  vx2=topbirspeedx,  vy2=topbirspeedy,;
         
      double r12=sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
      double cs=(x2-x1)/r12;   double sc=(y2-y1)/r12;
      double vp1=vx1*cs+vy1*sc;
      double vp2=vx2*cs+vy2*sc;
      // back to collision time
      double ddt=(r1+r2-r12)/(vp1-vp2);
      if(ddt>0)ddt=0.;

       x1-=vx1*ddt;   y1-=vy1*ddt;
      x2-=vx2*ddt;   y2-=vy2*ddt;
      r12= sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
      //calculate component of velocity
      cs=(x2-x1)/r12;   sc=(y2-y1)/r12;
      vp1=vx1*cs+vy1*sc;
      vp2=vx2*cs+vy2*sc;
      //  normal components do not change
      double vn1=vx1*sc-vy1*cs;
      double vn2=vx2*sc-vy2*cs;
      //calculate component of velocity in original X,Y coordinate
      double px1=vp1*cs; double py1=vp1*sc;
      double px2=vp2*cs; double py2=vp2*sc;
      double nx1=vn1*sc; double ny1=-vn1*cs;
      double nx2=vn2*sc; double ny2=-vn2*cs;
      
      topspeedx =  px1+nx1;
      topspeedy =  py1+ny1;
      topbirspeedx =  px2+nx2;
      topbirspeedy =  py2+ny2;
      
       
       int i=2;
      top.center = CGPointMake(top.center.x + i*topspeedx, top.center.y + i*topspeedy);
      topbir.center = CGPointMake(topbir.center.x + i*topbirspeedx, topbir.center.y + i*topbirspeedy);
      
    }



Title: Re: 3D Collision
Post by: volpesfuggente on September 10, 2010, 05:40:28 pm
Hi!

I have some problems to manage 3D Collisions!!!
I try to transform this 2D collision detection into 3d collision detection, but I have some problems to compute the dt!!!

Sometimes, I have dt>>1.

Anyone has some simple ideas to transform this 2d collision to 3d collision detection?

Thanks to all.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on September 10, 2010, 08:57:42 pm
Please write down how you did it in detail so that we can discuss it base on your calculation.

The required condition is $v*dt< r$ where $r$ is the radius of the ball.


Title: Re: 2D Collision
Post by: volpesfuggente on September 10, 2010, 10:19:52 pm
Code:
                float[] center1=p1.getCenter();
        float[] center2=p2.getCenter();
        float[] velocity1=p1.getVelocity();
        float[] velocity2=p2.getVelocity();
        short r1=p1.getRadius();
        short r2=p2.getRadius();
        float modVelocity1=p1.getVelocityModule();
        float modVelocity2=p2.getVelocityModule();
       
       
            float dx21 = (center2[0]-center1[0]);
            float dy21 = (center2[1]-center1[1]);
            float dz21 = (center2[2]-center1[2]);
       
            float distance = (float) Math.sqrt(dx21*dx21+dy21*dy21+dz21*dz21);
           
            if (distance<((r1+r2))){
                       
                // Unit vector in the direction of the collision
                float ax=((dx21/distance)), ay=((dy21/distance)), az=((dz21/distance));

                float alfa=0;
               
               
                        BigDecimal bg = new BigDecimal((velocity1[0]*dx21+velocity1[1]*dy21+velocity1[2]*dz21)/(modVelocity1*distance));
                        bg = bg.setScale(3, BigDecimal.ROUND_HALF_UP);
                        alfa=(float) Math.acos(bg.doubleValue()); // angle between velocity vector and distance vector
                   
                 
   
               
                float alfaX1=(float) Math.acos((dx21)/(distance));
                float alfaY1=(float) Math.acos((dy21)/(distance));
                float alfaZ1=(float) Math.acos((dz21)/(distance));
               
                float modVa1=(float) (Math.abs(modVelocity1)*Math.cos(alfa));
                float vax1=(float) (Math.abs(modVa1)*Math.cos(alfaX1));
                float vay1=(float) (Math.abs(modVa1)*Math.cos(alfaY1));
                float vaz1=(float) (Math.abs(modVa1)*Math.cos(alfaZ1));
                           
               
                float vbx1=velocity1[0]-vax1;
                float vby1=velocity1[1]-vay1;
                float vbz1=velocity1[2]-vaz1;
               
                float beta=0;
               
                        BigDecimal bg = new BigDecimal((velocity2[0]*dx12+velocity2[1]*dy12+velocity2[2]*dz12)/(modVelocity2*distance));
                        bg = bg.setScale(3, BigDecimal.ROUND_HALF_UP);
                        beta=(float) Math.acos(bg.doubleValue()); // angle between velocity vector and distance vector
                   
               
                float alfaX2=(float) Math.acos((dx12)/(distance));
                float alfaY2=(float) Math.acos((dy12)/(distance));
                float alfaZ2=(float) Math.acos((dz12)/(distance));
               
                //Velocity component along the distance vector between the 2 balls
                float modVa2= (float) (Math.abs(modVelocity2)*Math.cos(beta));
                float vax2=(float) (Math.abs(modVa2)*Math.cos(alfaX2));
                float vay2=(float) (Math.abs(modVa2)*Math.cos(alfaY2));
                float vaz2=(float) (Math.abs(modVa2)*Math.cos(alfaZ2));
               
                float vbx2=velocity2[0]-vax2;
                float vby2=velocity2[1]-vay2;
                float vbz2=velocity2[2]-vaz2;

                float vxx21 =(vax2-vax1);
                float vyy21 =(vay2-vay1);
                float vzz21 =(vaz2-vaz1);
                float modDiffVelocity=(float) Math.sqrt(vxx21*vxx21+vyy21*vyy21+vzz21*vzz21);
               
                float va1t=(velocity1[0]*ax+velocity1[1]*ay+velocity1[2]*az);
                float va2t=(velocity2[0]*ax+velocity2[1]*ay+velocity2[2]*az);

                dt = ((r1+r2-distance)/modDiffVelocity);
            

I tryed to use the polar coordinates to manage this problem in 3D.
Any ideas?


Title: Re: 2D Collision
Post by: volpesfuggente on September 10, 2010, 10:22:42 pm
time_step = 1

v = 0.01

R=2

So, v*time_step<R1
 ???


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on September 10, 2010, 11:50:11 pm
I do not understand the way you defined those angle?
I would suggest you use (x,y,z) coordinate.
(http://www.phy.ntnu.edu.tw/demolab/phpBB/pics/2_2_collision2d.png)


Assume $\vec{r_a}$ and $\vec{r_b}$ are center of those two balls. And the radius are $R_a,R_b$.
Let $\vec{d}= \vec{r_a}-\vec{r_b}$ which is the relative vector between two centers.
Collision occurred if the length $|\vec{d}| The next step is to find two components of velocity vectors $\vec{V_a}=(V_{ax},V_{ay},V_{az}),\vec{V_b}=(V_{bx},V_{by},V_{bz})$:
  1. velocity components parallel to $\vec{d}=(d_x,d_y,d_z)$
  $\vec{V}_{ap}=\vec{V_a}\cdot \vec{d}/|\vec{d}|,\vec{V}_{bp}=\vec{V_b}\cdot \vec{d}/|\vec{d}|$
  The time step to move backward $dt=\frac{R_a+R_b-|\vec{d}|}{|\vec{V}_{ap}-\vec{V}_{bp}|}$

Hints: how to calculate inner product $\vec{V_a}\cdot \vec{d}=V_{ax}*d_x+ V_{ay}*d_y+V{az}*dz$
 
  2. velocity components perpendicular to $\vec{d}$
 $\vec{V_{an}}=\vec{V_a}-\vec{V_{ap}}, \vec{V_{bn}}=\vec{V_b}-\vec{V_{bp}}$
 The above two component will not change before and after collision


You can check out previous posted message. e.g. How to convert 2D collision into 1D (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg9#msg9)

Just add one more component (z) if you want to transfer from 2D(x,y)to 3D(x,y,z).

It will be much easier if understand the meaning of inner product between two vectors- Help you find out projection of one vector into another vector.


Title: Re: 2D Collision
Post by: volpesfuggente on September 14, 2010, 12:24:48 am
I do not understand the way you defined those angle?
I would suggest you use (x,y,z) coordinate.
(http://www.phy.ntnu.edu.tw/demolab/phpBB/pics/2_2_collision2d.png)


Assume $\vec{r_a}$ and $\vec{r_b}$ are center of those two balls. And the radius are $R_a,R_b$.
Let $\vec{d}= \vec{r_a}-\vec{r_b}$ which is the relative vector between two centers.
Collision occurred if the length $|\vec{d}|<R_a+R_b$:
 The next step is to find two components of velocity vectors $\vec{V_a}=(V_{ax},V_{ay},V_{az}),\vec{V_b}=(V_{bx},V_{by},V_{bz})$:
  1. velocity components parallel to $\vec{d}=(d_x,d_y,d_z)$
  $\vec{V}_{ap}=\vec{V_a}\cdot \vec{d}/|\vec{d}|,\vec{V}_{bp}=\vec{V_b}\cdot \vec{d}/|\vec{d}|$
  The time step to move backward $dt=\frac{R_a+R_b-|\vec{d}|}{|\vec{V}_{ap}-\vec{V}_{bp}|}$

Hints: how to calculate inner product $\vec{V_a}\cdot \vec{d}=V_{ax}*d_x+ V_{ay}*d_y+V{az}*dz$
 
  2. velocity components perpendicular to $\vec{d}$
 $\vec{V_{an}}=\vec{V_a}-\vec{V_{ap}}, \vec{V_{bn}}=\vec{V_b}-\vec{V_{bp}}$
 The above two component will not change before and after collision


You can check out previous posted message. e.g. How to convert 2D collision into 1D (http://www.phy.ntnu.edu.tw/ntnujava/index.php?topic=4.msg9#msg9)

Just add one more component (z) if you want to transfer from 2D(x,y)to 3D(x,y,z).

It will be much easier if understand the meaning of inner product between two vectors- Help you find out projection of one vector into another vector.


Thank you very much, but I still have a problem.
I'm not sure that the bounce is correct...

This is my code:
Code:
                float[] center1=p1.getCenter();
float[] center2=p2.getCenter();
float[] velocity1=p1.getVelocity();
float[] velocity2=p2.getVelocity();
short r1=p1.getRadius();
short r2=p2.getRadius();


float dx12 = (center1[0]-center2[0]);
float dy12 = (center1[1]-center2[1]);
float dz12 = (center1[2]-center2[2]);

float dx21 = (center2[0]-center1[0]);
float dy21 = (center2[1]-center1[1]);
float dz21 = (center2[2]-center1[2]);


float distance = (float) Math.sqrt(dx12*dx12+dy12*dy12+dz12*dz12);

if (distance<((r1+r2))){

float[] Va=p1.getVelocityComponent();
float[] Vb=p2.getVelocityComponent();

float[] D={dx12,dy12,dz12};
float[] Db={dx21,dy21,dz21};

float[] Vap= new float[3];
Vap[0]=Va[0]*D[0]/distance;
Vap[1]=Va[1]*D[1]/distance;
Vap[2]=Va[2]*D[2]/distance;


float[] Vbp= new float[3];
Vbp[0]=Vb[0]*Db[0]/distance;
Vbp[1]=Vb[1]*Db[1]/distance;
Vbp[2]=Vb[2]*Db[2]/distance;

float diff=(float) Math.sqrt((Vap[0]-Vbp[0])*(Vap[0]-Vbp[0])+(Vap[1]-Vbp[1])*(Vap[1]-Vbp[1])+(Vap[2]-Vbp[2])*(Vap[2]-Vbp[2]));


float dt=(r1+r2-distance)/(diff);


float[] Van = new float[3];
Van[0]=Va[0]-Vap[0];
Van[1]=Va[1]-Vap[1];
Van[2]=Va[2]-Vap[2];

float[] Vbn = new float[3];
Vbn[0]=Vb[0]-Vbp[0];
Vbn[1]=Vb[1]-Vbp[1];
Vbn[2]=Vb[2]-Vbp[2];


center1[0]-=Va[0]*dt;
center1[1]-=Va[1]*dt;
center1[2]-=Va[2]*dt;

center2[0]-=Vb[0]*dt;
center2[1]-=Vb[1]*dt;
center2[2]-=Vb[2]*dt;


dx12 = (center1[0]-center2[0]);
dy12 = (center1[1]-center2[1]);
dz12 = (center1[2]-center2[2]);

dx21 = (center2[0]-center1[0]);
dy21 = (center2[1]-center1[1]);
dz21 = (center2[2]-center1[2]);



distance = (float) Math.sqrt(dx12*dx12+dy12*dy12+dz12*dz12);
// Unit vector in the direction of the collision
double ax=dx12/distance, ay=dy12/distance, az=dz12/distance;


float[] Vap1= new float[3];
Vap1[0]=(float) (Va[0]*ax);
Vap1[1]=(float) (Va[1]*ay);
Vap1[2]=(float) (Va[2]*az);


float[] Vbp1= new float[3];
Vbp1[0]=(float) (Vb[0]*(-ax));
Vbp1[1]=(float) (Vb[1]*(-ay));
Vbp1[2]=(float) (Vb[2]*(-az));

float[] Van1 = new float[3];
Van1[0]=Va[0]-Vap1[0];
Van1[1]=Va[1]-Vap1[1];
Van1[2]=Va[2]-Vap1[2];

float[] Vbn1 = new float[3];
Vbn1[0]=Vb[0]-Vbp1[0];
Vbn1[1]=Vb[1]-Vbp1[1];
Vbn1[2]=Vb[2]-Vbp1[2];

float mass1=p1.getMass();
float mass2=p2.getMass();


float[] vaP1=new float[3];
vaP1[0]=(float) (Vap1[0] + (1+ed)*(Vbp1[0]-Vap1[0])/(1+mass1/mass2));
vaP1[1]=(float) (Vap1[1] + (1+ed)*(Vbp1[1]-Vap1[1])/(1+mass1/mass2));
vaP1[2]=(float) (Vap1[2] + (1+ed)*(Vbp1[2]-Vap1[2])/(1+mass1/mass2));

float[] vaP2=new float[3];
vaP2[0]=(float) (Vbp1[0] + (1+ed)*(Vap1[0]-Vbp1[0])/(1+mass2/mass1));
vaP2[1]=(float) (Vbp1[1] + (1+ed)*(Vap1[1]-Vbp1[1])/(1+mass2/mass1));
vaP2[2]=(float) (Vbp1[2] + (1+ed)*(Vap1[2]-Vbp1[2])/(1+mass2/mass1));

velocity1[0]=vaP1[0]-Van[0];
velocity1[1]=vaP1[1]-Van[1];
velocity1[2]=vaP1[2]-Van[2];

velocity2[0]=vaP2[0]-Vbn[0];
velocity2[1]=vaP2[1]-Vbn[1];
velocity2[2]=vaP2[2]-Vbn[2];


center1[0]+=velocity1[0]*dt;
center1[1]+=velocity1[1]*dt;
center1[2]+=velocity1[2]*dt;

center2[0]+=velocity2[0]*dt;
center2[1]+=velocity2[1]*dt;
center2[2]+=velocity2[2]*dt;


There is some problems with to compute the diff, because sometimes it is NaN...
There is any error in my code?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on September 14, 2010, 08:52:50 am
There must be some bug in your code:
Normally, NaN came from divided by zero or negative value inside sqrt root, etc.

The program should be able to provide the line number where the error occurs.
Find out the code which produce the error.


Title: Re: 2D Collision
Post by: zazz on September 24, 2010, 09:45:07 pm
Hi professor, quick question:

What dictates the direction of the normal vector? While i understand that it's perpendicular to the angle of collision(AoC), what determines whether its AoC+PI/2 or AoC-PI/2?

Thanks in advance


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on September 25, 2010, 12:12:00 am
It does not matter as long as you use the same vector to convert normal component and parallel component back to final velocity after collision.

That is the beauty of vector analysis!   

You can try it with either one, and you will find out that you will get the same result.


Title: Re: 2D Collision
Post by: lunayo on October 07, 2010, 12:35:22 pm
Sir, I'm implementing 2d collision on objective - c using opengl.
but it didn't work . if i didn't calculate and apply dt to ball 1 position (translation) , the ball is stuck together (but it is moving) .
but if i apply dt, the ball seems going messy when collideed. can you see what is going on with the code?
the variable dt can be minus when check through console, is it right?

Code:
BBPoint coliddeSpeed = [(BBStaticMarble*)sceneObject speed];
BBPoint collideeTranslation = [(BBStaticMarble*)sceneObject translation];

CGFloat r1,r2;
r1 = r2 = self.collider.maxRadius;
CGFloat dx=collideeTranslation.x-translation.x, dy=collideeTranslation.y-translation.y;
CGFloat d=sqrt(dx*dx+dy*dy);
//First calculate the component of velocity in the direction of (dx,dy)
CGFloat vp1= speed.x*dx/d+speed.y*dy/d;
CGFloat vp2= collideeSpeed.x*dx/d+collideeSpeed.y*dy/d;
//Collision should have happened dt before you have detected r1+r2
CGFloat dt = (r1+r2-d)/(vp1-vp2);// the collision should have occurred at t-dt (Actually this is also an approximation).


//So you should move those two ball backward
translation.x -= speed.x*dt;
translation.y -= speed.y*dt;
collideeTranslation.x -=collideeSpeed.x*dt;
collideeTranslation.y-=collideeSpeed.y*dt;


dx=collideeTranslation.x-translation.x, dy=collideeTranslation.y-translation.y;
// where x1,y1 are center of ball1, and x2,y2 are center of ball2
CGFloat distance = sqrt(dx*dx+dy*dy);
// Unit vector in the direction of the collision
CGFloat ax=dx/distance, ay=dy/distance;
// Projection of the velocities in these axes
CGFloat va1=(speed.x*ax+speed.y*ay), vb1=(-speed.x*ay+speed.y*ax);
CGFloat va2=(collideeSpeed.x*ax+speed.y*ay), vb2=(-collideeSpeed.x*ay+collideeSpeed.y*ax);
// New velocities in these axes (after collision): ed<=1,  for elastic collision ed=1
CGFloat ed = 0.8;
CGFloat vaP1=va1 + (1+ed)*(va2-va1)/(1+self.mass/collideeMass);
CGFloat vaP2=va2 + (1+ed)*(va1-va2)/(1+collideeMass/self.mass);
// Undo the projections
speed.x=vaP1*ax-vb1*ay;  speed.y=vaP1*ay+vb1*ax;// new vx,vy for ball 1 after collision
collideeSpeed.x=vaP2*ax-vb2*ay; collideeSpeed.y=vaP2*ay+vb2*ax;// new vx,vy for ball 2 after collision


//Because we have move time backward dt, we need to move time forward dt.
translation.x+= speed.x*dt;
translation.y+= speed.y*dt;
collideeTranslation.x+=collideeSpeed.x*dt;
collideeTranslation.x+=collideeSpeed.y*dt;


[(BBStaticMarble*)sceneObject setSpeed:collideeSpeed];
[(BBStaticMarble*)sceneObject setTranslation:collideeTranslation];
[(BBStaticMarble*)sceneObject setIsMarbleMoving:YES]


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 07, 2010, 04:49:43 pm
The problem could be due to the parameters used in the simulation.

The above model of calculation assume: the time step is small enough so that the distance move in each time step is smaller than the radius of both particles.

The problem you found much be due to the time step is too large or the velocity is too large.

1. r1 and r2 are about the same or similar order.
2. $v_1 *dt<< r_1+r_2 , v_2*dt<< r_1+r_2$


Title: Re: 2D Collision
Post by: lunayo on October 08, 2010, 01:50:18 am
Quote
The problem could be due to the parameters used in the simulation.

The above model of calculation assume: the time step is small enough so that the distance move in each time step is smaller than the radius of both particles.

The problem you found much be due to the time step is too large or the velocity is too large.

1. r1 and r2 are about the same or similar order.
2. v_1 *dt<< r_1+r_2 , v_2*dt<< r_1+r_2

What should i change if the velocity is too large or the time step is too large? (I'm using 60 frame per second in the simulation)


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 08, 2010, 03:14:36 pm
Make the velocity smaller or change the time step to smaller value.

May be you are updating the view 60frame per second.
You can make the time step 1/600 second, and update the view every 10 second.
So it is up to you to change the time step to any suitable precision you want.


Title: Re: 2D Collision
Post by: lunayo on October 08, 2010, 04:04:36 pm
Sir, why the dt can be result of nan? what can cause that? how to solve it?
and i found that when ball1 collideed with ball2 with mass1/mass2 = 1.0, velocity x ball1 200 , velocity x ball 2 -100 (moving opposite) and ed = 0.8, ball1 didn't bounce a bit, instead ball1 just moving forward.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 08, 2010, 06:06:57 pm
You have the following code
Code:
dt = (r1+r2-d)/(vp1-vp2);
What if vp1==vp2???


You also have the following code

Code:
CGFloat d=sqrt(dx*dx+dy*dy);
//First calculate the component of velocity in the direction of (dx,dy)
CGFloat vp1= speed.x*dx/d+speed.y*dy/d;
CGFloat vp2= collideeSpeed.x*dx/d+collideeSpeed.y*dy/d;

What if d==0???

It could also be other kind of bug in your code. You need to trace the code (find out value for variables) and try to find out the problem.
It is not easy to find the bug.  Good luck!


Title: Re: 2D Collision
Post by: mediakitchen on October 08, 2010, 11:12:46 pm
I am very pleased to have found this site and especially this thread. I am creating a ball based game in a language called Lua and have been trying to use your code as follows:

I have multiple balls in the game. The code is so close to working perfectly - just occasionally I get a badly behaved ball that appears to shoot off the screen extremely fast.

Would appreciate if you can spot any issues. I have a maximum speed of 14. Also please note I have a tempX and tempY property for each ball. Once I have checked for all the collisions with all the balls. I then set their actual screen x and y positions.

Hope you can help me identify any issues with my code.

Thanks

Paul

Code:

local function checkForCollisionWithBall( firstBallRef, secondBallRef )

   -- ------------------
   -- Set some constants
   -- ------------------

   local D = 14 -- Radius of ball
   local D2 = (2 * D) * (2 * D) -- Radius squared

   
   -- ---------------------------------------------
   -- Calculate distance between balls on both axis
   -- ---------------------------------------------
   
   local dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
   local dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls
   
     
   local dxy = (dx * dx) + (dy * dy)
   
   if (dxy < 0.00001) then
   
     
   
      return
   
   end
   
   
   
   if (dxy < D2) then
   
      -- --------------------
      -- We have a collision!
      -- --------------------
     
      -- ------------------------------------------------------------------------------
      -- We now perform the square root to calculate the distance between the two balls
      -- ------------------------------------------------------------------------------
     
      dxy = mSqrt(dxy)
     
      local cs = dx/dxy
      local sc = dy/dxy
     
      -- -----------------------------------------------------------
      -- Calculate component of velocity in the direction of (dx,dy)
      -- -----------------------------------------------------------
     
      local vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
      local vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc
     
     
   
      local dt = (D + D - dxy) / (vp1 - vp2)
     
     
     
      firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
      firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)
     
     
     
     
      secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
      secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)
     
     
     
      dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
      dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls
     
      local distance = mSqrt(dx * dx + dy * dy)
      local ax = dx/distance
      local ay = dy/distance
     
     
     
      local va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
      local vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)
     
      local va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
      local vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)
     
     
     
      local vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
      local vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)
     
     
      firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
      firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax
   
     
      secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
      secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax
     
     
     
      firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
      firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt
     
      secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
      secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

   
   end
   
end





Title: Re: 2D Collision
Post by: lunayo on October 09, 2010, 02:57:47 am
I am very pleased to have found this site and especially this thread. I am creating a ball based game in a language called Lua and have been trying to use your code as follows:

I have multiple balls in the game. The code is so close to working perfectly - just occasionally I get a badly behaved ball that appears to shoot off the screen extremely fast.

Would appreciate if you can spot any issues. I have a maximum speed of 14. Also please note I have a tempX and tempY property for each ball. Once I have checked for all the collisions with all the balls. I then set their actual screen x and y positions.

Hope you can help me identify any issues with my code.

Thanks

Paul

Code:

local function checkForCollisionWithBall( firstBallRef, secondBallRef )

   -- ------------------
   -- Set some constants
   -- ------------------

   local D = 14 -- Radius of ball
   local D2 = (2 * D) * (2 * D) -- Radius squared

   
   -- ---------------------------------------------
   -- Calculate distance between balls on both axis
   -- ---------------------------------------------
   
   local dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
   local dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls
   
     
   local dxy = (dx * dx) + (dy * dy)
   
   if (dxy < 0.00001) then
   
     
   
      return
   
   end
   
   
   
   if (dxy < D2) then
   
      -- --------------------
      -- We have a collision!
      -- --------------------
     
      -- ------------------------------------------------------------------------------
      -- We now perform the square root to calculate the distance between the two balls
      -- ------------------------------------------------------------------------------
     
      dxy = mSqrt(dxy)
     
      local cs = dx/dxy
      local sc = dy/dxy
     
      -- -----------------------------------------------------------
      -- Calculate component of velocity in the direction of (dx,dy)
      -- -----------------------------------------------------------
     
      local vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
      local vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc
     
     
   
      local dt = (D + D - dxy) / (vp1 - vp2)
     
     
     
      firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
      firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)
     
     
     
     
      secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
      secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)
     
     
     
      dx = secondBallRef.tempX - firstBallRef.tempX -- horizontal distance between the 2 balls
      dy = secondBallRef.tempY - firstBallRef.tempY -- vertical distance between the 2 balls
     
      local distance = mSqrt(dx * dx + dy * dy)
      local ax = dx/distance
      local ay = dy/distance
     
     
     
      local va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
      local vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)
     
      local va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
      local vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)
     
     
     
      local vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
      local vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)
     
     
      firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
      firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax
   
     
      secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
      secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax
     
     
     
      firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
      firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt
     
      secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
      secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

   
   end
   
end




You have the following code
Code:
dt = (r1+r2-d)/(vp1-vp2);
What if vp1==vp2???


You also have the following code

Code:
CGFloat d=sqrt(dx*dx+dy*dy);
//First calculate the component of velocity in the direction of (dx,dy)
CGFloat vp1= speed.x*dx/d+speed.y*dy/d;
CGFloat vp2= collideeSpeed.x*dx/d+collideeSpeed.y*dy/d;

What if d==0???

It could also be other kind of bug in your code. You need to trace the code (find out value for variables) and try to find out the problem.
It is not easy to find the bug.  Good luck!

@prof, i've found the bug , it's on collision.
@mediakitchen i have multiple balls , how do you compare each array without having compare the same one.
for example Array 1 (ball1,ball2,ball3), Array 2 (ball1,ball2,ball3) how do you skip the same last one?


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 09, 2010, 10:31:14 am
Make a double loop
i=0 to n
j=i+1 to n



Title: Re: 2D Collision
Post by: lunayo on October 09, 2010, 01:13:07 pm
Make a double loop
i=0 to n
j=i+1 to n



Thank you professor, I made it!!  :D. You are a very good teacher.  ;D


Title: Re: 2D Collision
Post by: mediakitchen on October 09, 2010, 02:00:49 pm
Thank you for the reply. I should have included my code that shows where I call the collision function.

I loop through all balls and check each against all the others whilst ensuring that I do not compare the same one with itself

Code:

for (var i = 0; i < howManyBalls; i++) {

     ball1 = ballObjects[i]

     
     for (var j = 0; i < howManyBalls; j++) {

          ball2 = ballObjects[j]

          if (ball1 != ball2) {
               
                 checkForCollisionWithBall(ball1, ball2 )
          }

    }



}



Is this equivalent to the double loop?


Quote
You have the following code
Code:

dt = (r1+r2-d)/(vp1-vp2);

What if vp1==vp2???


You also have the following code

Code:

CGFloat d=sqrt(dx*dx+dy*dy);
//First calculate the component of velocity in the direction of (dx,dy)
CGFloat vp1= speed.x*dx/d+speed.y*dy/d;
CGFloat vp2= collideeSpeed.x*dx/d+collideeSpeed.y*dy/d;


What if d==0???

It could also be other kind of bug in your code. You need to trace the code (find out value for variables) and try to find out the problem.
It is not easy to find the bug.  Good luck!


How do I deal with the situation where vp1 = vp2 or d = 0?

Thank you

Paul


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 09, 2010, 02:54:03 pm
The problem is due to your double loops.

For example: when  i=0, j=0 it is not collision between two different balls.
Think about what you were doing and you will understand why it is not working.

You should change the second loop to
Code:
for (var j = i; i < howManyBalls; j++)


Title: Re: 2D Collision
Post by: mediakitchen on October 09, 2010, 03:02:19 pm
Thank you for the fast reply.

Surely my line of code that says if (ball1 != ball2) will prevent checking one ball against itself? There was a small typo in my code I typed in


Code:

for (var j = 0; i < howManyBalls; j++) {


Should have been

Code:

for (var j = 0; j < howManyBalls; j++) {


Code:


for (var i = 0; i < howManyBalls; i++) {

   ball1 = ballObjects[i]

   
   for (var j = 0; j < howManyBalls; j++) {

      ball2 = ballObjects[j]

      if (ball1 != ball2) {
       
         checkForCollisionWithBall(ball1, ball2 )
      }

   }



If I use the following:

Code:
for (var j = i; i < howManyBalls; j++)

Surely if i = 2 then j will never have a value of 0 or 1?

Thank you

Paul


Title: Re: 2D Collision
Post by: mediakitchen on October 09, 2010, 04:04:48 pm
With multiple balls and when looping through all balls checking for collision. If 2 balls collide we use dt to reposition them at point of collision. Do we also need to reposition all other balls to their position based on dt? Just wondered if this was possible cause of problem?

Though perhaps my double loop is still not right?

Thank you so much for help

Paul


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 09, 2010, 05:34:28 pm
There is another problem even you rule out case for  i==j
 
Try to set howManyBalls to 3 and following the loop.
Write down what you were asking the computer to do.
And you will find out what is the problem.

After you figure out the problem, then check out my previous suggestion for the double loop.

You need to figure out by yourself!

Code:
Surely if i = 2 then j will never have a value of 0 or 1?

The collision between 0-1 and 0-2 should have been processed when outer loop i=0, right? :D


Title: Re: 2D Collision
Post by: mediakitchen on October 09, 2010, 05:54:45 pm
Thank so very much. I will try what you suggested and hope I find the problem.


Title: Re: 2D Collision
Post by: mediakitchen on October 10, 2010, 04:19:18 am
I have spent the day trying to figure this out with no joy.

I have created two test movies using Flash, one with 3 balls and one with 5, the links are as follows:

http://www.mediakitchen.co.uk/physics/testFile3balls.html
http://www.mediakitchen.co.uk/physics/testFile5balls.html

Simply click on the ball at the bottom and drag mouse to launch the ball towards the other balls. If you pull it back as much as possible before releasing mouse it will propell the ball faster. It is when it goes faster the problem occurs, especially when you aim towards the middle of the group of upper balls. It is random when it doesn't work so please try a few times.

Ok I thought I  found the problem and changed my loop to a double loop. I could really do with help fixing this problem.

Thanks

Paul

Code:

function initialiseGameConstants() {

objGame.friction = 0.8;

objGame.dV = 0.08;

objGame.D = 14; // Ball radius
objGame.D2 = (2 * objGame.D) * (2 * objGame.D)


}

function moveBallObjects(e:Event):void {


var howManyBallObjects:Number = objGame.ballObjects.length;

for (var i:Number = 0; i < howManyBallObjects; i++) {

var ballObject = objGame.ballObjects[i];

var V = (ballObject.horizontalVelocity * ballObject.horizontalVelocity) + (ballObject.verticalVelocity * ballObject.verticalVelocity);

    if (V == 0) {
   
        continue;
    }

    V = Math.sqrt(V);


    var k = (V - objGame.dV) / V;


    if (k < 0)
    {
        k = 0;
    } // end if

    ballObject.horizontalVelocity = ballObject.horizontalVelocity * k;
    ballObject.verticalVelocity = ballObject.verticalVelocity * k;

ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity;

objGame.numTotalBalls = 3;

for (var j:Number = 0; j < objGame.numTotalBalls; j++) {

var firstBallObject = objGame.ballObjects[j];

for (var f:Number = (j + 1); f < objGame.numTotalBalls; f++) {

var otherBallMC = objGame.ballObjects[f];

checkForCollisionWithBall(firstBallObject, otherBallMC);

}

}

// ---------------------------------
// Update Position of Ball On Screen
// ---------------------------------


ballObject.x = ballObject.tempX;
ballObject.y = ballObject.tempY;

}


}






function checkForCollisionWithBall(firstBallRef:MovieClip, secondBallRef:MovieClip):void {
 
  var dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
  var dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls
 
   
  var dxy = (dx * dx) + (dy * dy)
 
  if (dxy < 0.00001) { 
 
    return
 
  }
 
   
  if (dxy < objGame.D2) {
 
    // --------------------
    // We have a collision!
    // --------------------
   
    // ------------------------------------------------------------------------------
    // We now perform the square root to calculate the distance between the two balls
    // ------------------------------------------------------------------------------
   
    dxy = Math.sqrt(dxy)
   
    var cs = dx/dxy
    var sc = dy/dxy
   
    // -----------------------------------------------------------
    // Calculate component of velocity in the direction of (dx,dy)
    // -----------------------------------------------------------
   
    var vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
    var vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc

    var dt = (objGame.D + objGame.D - dxy) / (vp1 - vp2)

    firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
    firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)

    secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
    secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)   
   
    dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
    dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls
   
    var distance = Math.sqrt(dx * dx + dy * dy)
    var ax = dx/distance
    var ay = dy/distance
   
   
   
    var va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
    var vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)
   
    var va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
    var vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)
   
   
   
    var vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
    var vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)
   
   
    firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
    firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax
 
   
    secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
    secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax
   
   
   
    firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
    firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt
   
    secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
    secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

 
  }
 
}





Title: Re: 2D Collision
Post by: mediakitchen on October 10, 2010, 04:36:07 am
Further to my last post, I have printed some variable values to the screen when the problem occurs as follows:

Code:

dxy = 11.183594089759662
cs = -0.9113209567523853
sc = -0.41169662833683374
vp1 = 10.423261322708719
vp2 = 0
dt = 1.6133535742410243
firstBallRef.tempX = 150.00761013707466
firstBallRef.tempY = 179.69153092093967
secondBallRef.tempX = 120.18423352873543
secondBallRef.tempY= 104.91271705850214
firstBallRef.horizontalVelocity = 5.118247803194922
firstBallRef.verticalVelocity = -1.4318442742343485
secondBallRef.horizontalVelocity = -6.0840764405175305
secondBallRef.verticalVelocity = -21.748043021508227
dxy = 20.415665302423797
cs = 0.9706157589148952
sc = -0.24063467860236176
vp1 = -0.6719671288981877
vp2 = 0
dt = -11.286764443391895
firstBallRef.tempX = 32.46887484970526
firstBallRef.tempY = -133.54646421285148
secondBallRef.tempX = 227.71535867903015
secondBallRef.tempY= 338.4591812713536
firstBallRef.horizontalVelocity = 1.6874473756267157
firstBallRef.verticalVelocity = -0.6207144175197532
secondBallRef.horizontalVelocity = -7.771523816144245
secondBallRef.verticalVelocity = -21.12732860398847
dxy = 21.703543611196096
cs = -0.23089377668368133
sc = 0.9729789637442047
vp1 = -2.342372578705536
vp2 = -18.295318544168257
dt = 0.3946892569206588
firstBallRef.tempX = 179.14739832875304
firstBallRef.tempY = 163.96685005743075
secondBallRef.tempX = 174.03981574604762
secondBallRef.tempY= 200.25638673254542
firstBallRef.horizontalVelocity = 4.778078082260453
firstBallRef.verticalVelocity = -20.52327562601023
secondBallRef.horizontalVelocity = -7.70027935503791
secondBallRef.verticalVelocity = -1.3810100832728573
dxy = 14.346250582823185
cs = -0.9694056603163411
sc = -0.24546418424413502
vp1 = 0.4042924324869883
vp2 = 0
dt = 33.77196385593056
firstBallRef.tempX = 37.17943584519696
firstBallRef.tempY = 836.9689122027011
secondBallRef.tempX = 316.72790067410847
secondBallRef.tempY= -553.4474215064265
firstBallRef.horizontalVelocity = 0.4152722629195494
firstBallRef.verticalVelocity = 0.08786827300331551
secondBallRef.horizontalVelocity = 4.344665927632815
secondBallRef.verticalVelocity = -20.53322763415942


I notice the value of dt is very high e.g dt = 33.77196385593056

Should dt have such a high value and if not, any idea why it is having this value?

Thank you

Paul


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 10, 2010, 09:04:32 am
As I have said several time, there is an assumption for the code I presented (to process the collision).
It require : the time step is smaller enough so that the movement of each ball should be smaller than radius of both balls.
i.e. v*dt<< r

Code:
ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
Your time step is always 1.
You should change the time step to a small value when velocity is too large.

Or you should make another loop to make the ball move with smaller steps.
i.e. ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity*dt;
with proper dt value.


Another issue is you are processing collision before all the particles are moving to the next time step.
You have loop i to move particle , inside loop i
 you have loop j and loop f to process collision,

I would suggest you move loop j and loop f outside loop i.
Process collision after all particles have move one time step.

And for loop j and loop f: you are still have both loop from 0-numTotalBalls.
 It seems that you did not listen to my suggestion. The code was processing collision twice.
for example: if you have three particles  j loop from 0-2, f:loop from 0-2
  your code is doing the following (j,f) pairs
  (0,0): self collision --- not real 
  (0,1):collision between particle 0 and particle 1
  (0,2):collision between particle 0 and particle 2
  (1,0):collision between particle 1 and particle 0--- this should have been take care in (0,1)
  (1,1):self collision --- not real 
  (1,2):collision between particle 2 and particle 0--- this should have been take care in (0,2)
  (2,0):collision between particle 2 and particle 1--- this should have been take care in (1,2)
  (2,1):collision between particle 2 and particle 2
  (2,2); self collision --- not real   

You should spend some time try to draw a conceptual flow to understand what you were really doing.


Title: Re: 2D Collision
Post by: mediakitchen on October 10, 2010, 12:17:42 pm
Thanks you for your patience.

I assure you I am reading your replies and attempting to act on your advice.

With regards the time, my movie is running at 30FPS therefore I was under the impression that the largest time slot was 1/30 seconds. I assume that the "actionLoop" function (see below) is being called 30 times per second.  Please can you explain this.

I thought my loop was correct as when I traced which balls it was comparing it had the following:

Code:

firstBallRef = ball1
secondBallRef = ball2
firstBallRef = ball1
secondBallRef = ball3
firstBallRef = ball1
secondBallRef = ball4
firstBallRef = ball1
secondBallRef = ball5
firstBallRef = ball2
secondBallRef = ball3
firstBallRef = ball2
secondBallRef = ball4
firstBallRef = ball2
secondBallRef = ball5
firstBallRef = ball3
secondBallRef = ball4
firstBallRef = ball3
secondBallRef = ball5
firstBallRef = ball4
secondBallRef = ball5


I have moved my code to do the collision detection after the code to calculate all the ball object new positions based on your recommendation:

Quote
Another issue is you are processing collision before all the particles are moving to the next time step.

Code:
function actionLoop(e:Event):void {

calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()

}

Unfortunately I am still getting the same error (New version here http://www.mediakitchen.co.uk/physics/testFile5v2balls.html ) but assume this must be due to the dt problem as the following is an example of my variable values when the issue occurs.

Code:
firstBallRef.tempX = 164.12788355997395
firstBallRef.tempY = 172.2370476331055
secondBallRef.tempX = 115.87211644002605
secondBallRef.tempY= 112.1629523668944
firstBallRef.horizontalVelocity = 9.36283073039942
firstBallRef.verticalVelocity = -4.751832309742385
secondBallRef.horizontalVelocity = -9.36283073039942
secondBallRef.verticalVelocity = -18.44816769025763
firstBallRef = ball1
secondBallRef = ball3
firstBallRef = ball1
secondBallRef = ball4
firstBallRef = ball1
secondBallRef = ball5
firstBallRef = ball2
secondBallRef = ball3
firstBallRef = ball2
secondBallRef = ball4
dxy = 27.020217899991174
cs = 0.8929566611667419
sc = -0.4501426454780135
vp1 = -0.056295059772248024
vp2 = 0
dt = -17.404406425230103
firstBallRef.tempX = -70.12509047107508
firstBallRef.tempY = -194.96160633456583
secondBallRef.tempX = 325.9972069111011
secondBallRef.tempY= 407.12455870146016
firstBallRef.horizontalVelocity = 1.3239575671590866
firstBallRef.verticalVelocity = -0.8017997994089945
secondBallRef.horizontalVelocity = -10.686788297558504
secondBallRef.verticalVelocity = -17.646367890848634


Note that the position of secondBallRef jumps from being x = 115 to x = 407, a very large movement and hence the issue I am experiencing.

Here is my updated code:

Code:
function actionLoop(e:Event):void {

calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()

}





function calculateBallObjectNewPositions():void {


var howManyBallObjects:Number = objGame.ballObjects.length;

for (var i:Number = 0; i < howManyBallObjects; i++) {

var ballObject = objGame.ballObjects[i];

if (ballObject.alpha < 1) {



var newScale = ballObject.scaleX * 0.98;

ballObject.alpha = ballObject.alpha - 0.1;
ballObject.scaleX = newScale;
ballObject.scaleY = newScale;   

if (ballObject.alpha <= 0) {
       
            ballObject.horizontalVelocity = 0;
ballObject.verticalVelocity = 0;
       
            continue;

        } // end if
       

}


var V = (ballObject.horizontalVelocity * ballObject.horizontalVelocity) + (ballObject.verticalVelocity * ballObject.verticalVelocity);

    if (V == 0)
    {
        continue;
    } else {



}

    V = Math.sqrt(V);

    var k = (V - objGame.dV) / V;


    if (k < 0)
    {
        k = 0;
    } // end if

    ballObject.horizontalVelocity = ballObject.horizontalVelocity * k;
    ballObject.verticalVelocity = ballObject.verticalVelocity * k;

ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity;

}



}



function checkForCollisions():void {

objGame.numTotalBalls = 5;

for (var j:Number = 0; j < objGame.numTotalBalls; j++) {

var firstBallObject = objGame.ballObjects[j];
for (var f:Number = (j + 1); f < objGame.numTotalBalls; f++) {

var otherBallMC = objGame.ballObjects[f];

checkForCollisionWithBall(firstBallObject, otherBallMC);

}

}


}


function checkForCollisionWithBall(firstBallRef:MovieClip, secondBallRef:MovieClip):void {

trace ("firstBallRef = " + firstBallRef.instanceNameValue);
trace ("secondBallRef = " + secondBallRef.instanceNameValue);
 
  var dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
  var dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls
 
   
  var dxy = (dx * dx) + (dy * dy)
 
  if (dxy < 0.00001) { 
 
    return
 
  }
 
 
 
  if (dxy < objGame.D2) {
 
    // --------------------
    // We have a collision!
    // --------------------
   
    // ------------------------------------------------------------------------------
    // We now perform the square root to calculate the distance between the two balls
    // ------------------------------------------------------------------------------
   
    dxy = Math.sqrt(dxy)
   
    var cs = dx/dxy
    var sc = dy/dxy

trace ("dxy = " + dxy);

trace ("cs = " + cs);
trace ("sc = " + sc);
   
    // -----------------------------------------------------------
    // Calculate component of velocity in the direction of (dx,dy)
    // -----------------------------------------------------------
   
    var vp1 = firstBallRef.horizontalVelocity * cs + firstBallRef.verticalVelocity * sc
    var vp2 = secondBallRef.horizontalVelocity * cs + secondBallRef.verticalVelocity * sc
   
    trace ("vp1 = " + vp1);
trace ("vp2 = " + vp2);
 
    var dt = (objGame.D + objGame.D - dxy) / (vp1 - vp2)
   
   
   
    firstBallRef.tempX = firstBallRef.tempX - (firstBallRef.horizontalVelocity * dt)
    firstBallRef.tempY = firstBallRef.tempY - (firstBallRef.verticalVelocity * dt)
   
   
   
   
    secondBallRef.tempX = secondBallRef.tempX - (secondBallRef.horizontalVelocity * dt)
    secondBallRef.tempY = secondBallRef.tempY - (secondBallRef.verticalVelocity * dt)
   
   
   
    dx = secondBallRef.tempX - firstBallRef.tempX // horizontal distance between the 2 balls
    dy = secondBallRef.tempY - firstBallRef.tempY // vertical distance between the 2 balls
   
    var distance = Math.sqrt(dx * dx + dy * dy)
    var ax = dx/distance
    var ay = dy/distance
   
   
   
    var va1 = (firstBallRef.horizontalVelocity * ax + firstBallRef.verticalVelocity * ay)
    var vb1 = (-1 * firstBallRef.horizontalVelocity * ay + firstBallRef.verticalVelocity * ax)
   
    var va2 = (secondBallRef.horizontalVelocity * ax + secondBallRef.verticalVelocity * ay)
    var vb2 = (-1 * secondBallRef.horizontalVelocity * ay + secondBallRef.verticalVelocity * ax)
   
   
   
    var vaP1 = va1 + (1 + 1) * (va2 - va1)/(1 + 1/1)
    var vaP2 = va2 + (1 + 1) * (va1 - va2)/(1 + 1/1)
   
   
    firstBallRef.horizontalVelocity = vaP1 * ax - vb1 * ay
    firstBallRef.verticalVelocity = vaP1 * ay + vb1 * ax
 
   
    secondBallRef.horizontalVelocity = vaP2 * ax - vb2 * ay
    secondBallRef.verticalVelocity = vaP2 * ay + vb2 * ax
   
   
   
    firstBallRef.tempX = firstBallRef.tempX + firstBallRef.horizontalVelocity * dt
    firstBallRef.tempY = firstBallRef.tempY + firstBallRef.verticalVelocity * dt
   
    secondBallRef.tempX = secondBallRef.tempX + secondBallRef.horizontalVelocity * dt
    secondBallRef.tempY = secondBallRef.tempY + secondBallRef.verticalVelocity * dt

trace ("dt = " + dt);

trace ("firstBallRef.tempX = " + firstBallRef.tempX);
trace ("firstBallRef.tempY = " + firstBallRef.tempY);

trace ("secondBallRef.tempX = " + secondBallRef.tempX);
trace ("secondBallRef.tempY= " + secondBallRef.tempY);

trace ("firstBallRef.horizontalVelocity = " + firstBallRef.horizontalVelocity);
trace ("firstBallRef.verticalVelocity = " + firstBallRef.verticalVelocity);

trace ("secondBallRef.horizontalVelocity = " + secondBallRef.horizontalVelocity);
trace ("secondBallRef.verticalVelocity = " + secondBallRef.verticalVelocity);

 
  }
 
}


function updateBallPositions() {

var howManyBallObjects:Number = objGame.ballObjects.length;

for (var i:Number = 0; i < howManyBallObjects; i++) {

var ballObject = objGame.ballObjects[i];

ballObject.x = ballObject.tempX;
ballObject.y = ballObject.tempY;
}



}





It is so frustrating that this works 90% of the time.

Many thanks for your help

Paul


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on October 10, 2010, 04:26:43 pm
You should have noticed that the velocity of those two balls are not small when the problem occurs.
Your time step is 1, however, dt=-17.4 so it is the problem. The time step 1 is too large.

I know that you are under a fix time step. 30FPS or whatever time step by your program.

You are doing one step of particle movement for each frame.
Here is my suggestion for your code
Code:
function actionLoop(e:Event):void {

calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()

}

Your time step is 1 for the above 3 functions. Please change it to smaller value. e.g. change it to 0.1

You can change code like
Code:
ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity;
to
Code:
ballObject.tempX = ballObject.tempX + ballObject.horizontalVelocity*deltat;
ballObject.tempY = ballObject.tempY + ballObject.verticalVelocity*deltat;
and define deltat=0.1 (Because we change to smaller time step 0.1 so we need to calculate it 10 times)

then, change actionLoop
Code:
function actionLoop(e:Event):void {
 for (var i:Number = 0; i < 10; i++) {
calculateBallObjectNewPositions()
checkForCollisions()
updateBallPositions()
 }
}

Now, you are calculating it with 300FPS, even the program only update the view with 30FPS.

You can change 'deltat' to other values and change the number of outer loop (1/deltat) accordingly.
It is also possible to add code to adjust deltat according to velocity distribution (in some case, this might make it more efficient).

May be it only take you 1 hour to write the code, but you might need to spend 10 hours to debug the code (if you did not understand what your were doing or if you make a mistake without noticed).


Title: Re: 2D Collision
Post by: mediakitchen on October 10, 2010, 04:54:57 pm
Thank you again. I have made the amends you suggested and it appears to work now.

http://www.mediakitchen.co.uk/physics/testFile5v2ballsDelta.html

Thank you for your patience.

Paul


Title: Re: 2D Collision
Post by: lunayo on November 07, 2010, 07:52:47 am
Sir, how to calculate the momentum of ball hitting the wall? (Wall with various angle and various shape)


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on November 09, 2010, 01:46:24 pm
You can use the same equation as above, set m2>>m1

The result will be
 The component parallel to the wall will be the same
 but the normal component of the velocity will change direction (with the same magnitude).


Title: Re: 2D Collision
Post by: thepreditor10 on February 01, 2012, 08:34:26 pm
i am finding this all a little confusing is there a simple way to explain it in layman's terms  ???


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on February 01, 2012, 10:48:34 pm
Please write down which part (where) you feel confusing!


Title: Re: 2D Collision
Post by: thepreditor10 on February 02, 2012, 08:35:55 pm
i find physics confusing in general i am trying to create a simulation not far off the same as shown here for my university project i have the ball moving using angle and velocity by doing 


double scale_x=cos(angle);
double scale_y=sin(angle);
double v_x = (speed * scale_x);
double v_y = (speed * scale_y);

now i am looking to get the ball to bounce off the sides of the JPannel on collision also collision detection with two balls.
however i find it hard to understand how we are getting the balls to collide here and collision with the JPannel.


Title: Re: 2D Collision
Post by: nsuhaili6 on May 07, 2012, 07:31:52 pm
Hi prof,
your coding is for a circle 2-d collision right?
how am i going to simulate for irregular shape of object?
i want to simulate for water molecules model of this shape but in 2d..
-*-


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on May 08, 2012, 03:53:33 pm
Do you mean three circles (as shown in the picture attached) as one object.

Then, you need to check collision between any two circles. And you need to re-derive the equation (with conservation of momentum and conservation of angular momentum and conservation of energy-- five equations for 2D case). It will be much more complicated than the above simulation.


Title: Re: 2D Collision
Post by: Some1 on January 08, 2013, 06:45:36 am
Hello!

I have utilised your algorithm in a personal project and now I need to write a documentation for it. One problem I am having is explaining to someone what the actual mass of the ball is measured in... I noticed you give the default value of m1=r1*r1; So the square of the ray of the circle but technically it can be anything.

My question is how much of m1 is a gram.
So:
1 gram = m1
m1 = ?

Thank you in hopes that you can answer my question and once again. I really appreciate your work. It has helped immensely.


Title: Re: 2D Collision
Post by: Fu-Kwun Hwang on January 08, 2013, 03:07:06 pm
The mass used in the simulation can be 1g or 1kg or any other unit. It does not matter, the result will be the same (as long as all the particles used the same unit).

Because This is a two dimensional simulation, the mass is proportional to area (mass=density*area).
And the area of a circle is $A=\pi r^2$, that is why the mass is proportional to r*r in a 2D simulation.
(mass will be proportional to $r^3$ for a 3-D simulation.). 


Title: Re: 2D Collision
Post by: bark46k on September 26, 2013, 12:38:02 pm
great stuff!