Ball vs arc

Now lets se what happens if moving ball has to deal with arc. Arc is part of the circle, when circle makes full 360 degrees, the arc does not reach 360 degrees. With ball vs ball collision we only had 1 possible collision point. With ball vs arc we have not only 1, not even 2, but 4 possible collision points.

In the left moving ball has hit arc from outside, in the middle ball has hit arc from inside, in the right ball has hit endpoint of the arc (arc has 2 endpoints and ball could hit both).

To define a circle we need coordinates of its center point and its radius. To define an arc we need center point and radius too, but we also need angle of its starting point and angle of its ending point.

Example of defining arc

arc={p0:{x:170, y:90}, r:30, ang1:135, ang2:315};

Center of this arc would be at x=170, y=90, its radius would be 30, angle of starting point would be 135 degrees and angle of ending points 315. Once we know all that, we can find coordinates of its start and end points:

ang1rad=ang1*Math.PI/180;
ang2rad=ang2*Math.PI/180;
v1.p0={
x:p0.x+r*Math.cos(ang1rad),
y:p0.y+r*Math.sin(ang1rad)
};
v1.p1={
x:p0.x+r*Math.cos(ang2rad),
y:p0.y+r*Math.sin(ang2rad)
};

Vector v1 is between starting and ending points of the arc.

Collisions

We start by checking if ball will hit the arc from outside by using moving ball vs ball collision from chapter 10. If the collision would happen, we also need to check if the ball would hit arc in the area where arc exists and not in the empty part of circle.

We need to find point p3 which is the point where ball and arc are in contact. We already know center coordinates of moving ball when collision happens so we can draw vector v2 from the center of arc to center of ball at the moment of collision:

v2={p0:arc.p0, p1:ball.p3};

Point p3 is on this vector and its in the distance from arc center equal to radius of arc (its also from center of ball by distance of radius of the ball):

p3={
x:arc.p0.x+v2.dx*arc.r,
y:arc.p0.y+v2.dy*arc.r
};

Next we draw vector from starting point of arc to point p3:

v3={p0:v1.p0, p1:p3};

Point p3 is on the arc only if dot product between v3 and left normal of v1 is bigger then 0:

if(dotP(v3, v1LeftNormal)>=0){
  //collision
}else{
  //not on the arc
}

If collision was found and ball has hit the arc from outside then we can skip other 3 collision checks. However if collision point was outside of arc we need to check if ball would hit either of endpoints of the arc of if it would hit arc from inside.

For endpoints we can use same moving ball vs ball system, imagine invisible ball with radius equal to 0 sitting on the endpoint coordinates. If for ball vs full arc we used:

ballvsBall(ball, arc.p0, arc.r);

then we can now find collisions like this:

ballvsBall(ball, v1.p0, 0);
ballvsBall(ball, v1.p1, 0);

For collision of ball inside of the arc we use system of outside collision with slight modifications. For outside collision we used:

r=arc.r+ball.r;
moveBack=Math.sqrt(r*r-vn.len*vn.len);
ball.p3={
x:ball.p2.x-moveBack*v.dx,
y:ball.p2.y-moveBack*v.dy};

For inside collision we use:

r=arc.r-ball.r;
moveBack=Math.sqrt(r*r-vn.len*vn.len);
ball.p3={
x:ball.p2.x+moveBack*v.dx,
y:ball.p2.y+moveBack*v.dy};

It is possible for ball to collide with more then point with arc so once all 3 collisions have been found we need to pick shortest path the ball would move to collide.

And in this example of ball vs arc for you to play with:

You can download the source fla of example here.

Top