I have a polygon and inside of it is a moving ball.
The ball should bounce back if it hits a border.
My current 'solution':
I split the polygon in lines and calculate when the ball hits the moving line
all variables:
a = length of a
b = length of b
c = length of c
ax = x position of A
ay = y position of A
bx = x position of B
by = y position of B
cx = x position of C
cy = y position of C
vax = speed of A on the x-axis
vay = speed of A on the y-axis
vbx = speed of B on the x-axis
vby = speed of B on the y-axis
vcx = speed of C on the x-axis
vcy = speed of C on the y-axis
h = height (equals r, because it collides when h is r)
r = radius
t = time (one time unit equals 1 frame. not relevant)
axc = x positon of A at the collision
ayc = y positon of A at the collision
bxc = x positon of B at the collision
byc = y positon of B at the collision
cxc = x positon of C at the collision
cyc = y positon of C at the collision
Calculate the collision position of all points:
axc:=ax+vax*t
ayc:=ay+vay*t
bxc:=bx+vbx*t
byc:=by+vby*t
cyc:=cy+vcy*t
cxc:=cx+vcx*t
Calculate the length of all vertices
a:=√((axc-cxc)^(2)+(ayc-cyc)^(2))
b:=√((bxc-cxc)^(2)+(byc-cyc)^(2))
c:=√((axc-bxc)^(2)+(ayc-byc)^(2))
Calculate h
h=((√(2*(a^(2)*b^(2)+b^(2)*a^(2)+c^(2)*a^(2))-(a^(4)+b^(4)+c^(4))))/(2*c))
Solve for t
solve(h=((√(2*(a^(2)*b^(2)+b^(2)*a^(2)+c^(2)*a^(2))-(a^(4)+b^(4)+c^(4))))/(2*c)), t)
BUUUUUT: My calculator (Ti-Nspire CX CAS) crashes. And Microsoft Mathematics takes waaay too long (I am calculating right now... for 1 hour and still nothing...)
So... HELP!
(Don't question my paint skills)
If your polygon is convex and all velocities remain the same all the time, you could use these series of tricks I just came up with (so there is probably some better way):
1) Replace each line with infinitely long line by simply extending it.
You can do this only if the polygon is convex. Consider the following image:
The red lines are the original polygon, the green ones are the infinite extension. Can the circle ever hit a green line before it hits a red line? No. We can now focus on ball hitting infinitely long lines, which (at least for me) is simpler task.
2) Compute collision time with each line separately, then choose minimum
If we want to know whether and when a perfectly round ball hits a line, we can easily solve if a point hits a line instead, consider following image:
Basicly circle will hit a line when it's center will enter an area around that line, where the area are all points that are at most radius
away from the line, where radius
is the radius of the circle.
So we can go ahead and just replace the circle with a single point at the center and move the line towards the newly created point by the radius.
3) Compute when moving point hits moving line
If the line is defined by two moving points a
and b
with velocities va
and vb
, as well as the point is at point c
with velocity vc
, we can make point a
stationary (not moving) and at position (0,0) by replacing other two points location and velocities by b-a
, vb-va
and c-a
, vc-va
.
Now let's name the new coordinates and velocities of b
and c
like this: [bx, by]
, (vbx, vby)
and [cx, cy]
, (vcx, vcy)
. We can now figure out the time of collision time by solving this formula:
cx+t * vcx = s*bx + s*t*vbx
cy+t * vcy = s*by + s*t*vby
However be careful: this leads to quadratic equation, and you have to ignore possible negative solutions, which could mean that the point is moving away from the line or that the collision is happening right now, so make sure the ball isn't already colliding before you start doing anything.
Also (I hope there is no need to say this) after you substitute for t
and s
, you will not get the final point of collision, you need to undo all the easements you have done (add a
for example)
If you need it for non-convex polygons, I have a workaround for it, so write in the comments.