# Collision of Ball in Triangle

A ball with position and velocity $$(P_0,V_0)$$ is in a triangle. Which side of the triangle it will hit?

Calculations: The ball's motion is

$$L( t) = P_0+t*V_0 = \ ( V_{0_{x}} t+P_{0_{x}} ,V_{0_{y}} t+P_{0_{y}}) \tag{1}$$

The sides of the triangle are given by $$A_1x+B_1y=C_1$$, and we can represent the other two sides similarly. Substituting for $$x$$ and $$y$$ in $$(1)$$, we have:

$$A_1x+B_1y=C_1 \rightarrow A_{1}( V_{0_{x}} t_1+P_{0_{x}}) +B_{1}( V_{0_{y}} t_1+P_{0_{y}}) =C_{1} \tag{5}$$ $$t_{1} =\frac{C_{1} -A_{1} P_{0_{x}} +B_{1} P_{0_{y}}}{A_{1} V_{0_{x}} +B_{1} V_{0_{y}}} \tag{6}$$

Problem: When I compute my solution in Desmos, my formulas produce the wrong minimum time. For instance, even though the ball would clearly hit the Wall 2 (Blue), the minimum time is $$t_3$$! I've tried many things, but to no avail. Any help is greatly appreciated.

Two things: One, the $$+$$ in the numerator of (6) seems like it should be $$-$$ (or, alternatively, you left out a pair of parentheses in the numerator). But also, you calculated the minimum $$t$$-values for reaching a side, whether that time represented the future (positive) or past (negative). If the ball only moves forward in time, you want the minimum non-negative time among the solutions for hitting each side of the triangle.

• Thank you for the answer, Steve. Let me try this out. Feb 19, 2022 at 1:47
• Wow Steve. You caught a really small typo -- indeed, it was the negative sign that was tripping all the answers. Thanks a bunch. Feb 19, 2022 at 3:07

This is not an answer. This just illustrates how the side can be determined with inner & cross product.

# python3 which_side.py
import math

def ip(x, y):
return x[0]*y[0]+x[1]*y[1]

def cp(x, y):
return x[0]*y[1]-x[1]*y[0]

def sub(x, y):
return (x[0]-y[0], x[1]-y[1])

# No error checking, tri is assumed to have non empty interior
# and p0 lies in the interior.
# If the velocity v0 'brings' p0 through a vertex then a side
# will be returned even though a vertex would be better.
def findEdge(tri, p0, v0):
ips = [ip(v0, sub(v, p0)) for v in tri]

# If two on positive side that's the side.
nonnegs = [i for i, x in enumerate(ips) if x >= 0]
if len(nonnegs) == 2:
return set(nonnegs)

# Find point on opposite side.
nonneg = nonnegs[0]
cps = [cp(v0, sub(v, p0)) for v in tri]
opposite = [i for i, x in enumerate(cps) if i != nonneg and cps[nonneg]*x <= 0]
return set([nonneg, opposite[0]])

tri = [(-6.25, 0), (4.9, 0), (0, 4.572)]
p0 = (-0.25, 1.44)
v0 = (0.7, 0.5)
#v0 = (-2.2, 0.47)
#v0 = (-4.3, -0.63)

side = findEdge(tri, p0, v0)
print(f"crosses line between indices {side}")

• Thanks @copper.hat! Quite insightful. I will look through the full code later, but I didn't think of this. Feb 19, 2022 at 15:24
• Basically it places the triangle vertices into 4 quadrants based on $P_0,V_0$. Feb 19, 2022 at 16:02
• Oh!!! I tried this! Yes, indeed. See: chat.stackexchange.com/transcript/message/60466585#60466585 Feb 19, 2022 at 16:29
• Why the down vote? Mar 27, 2022 at 7:52
• Hm, unfortunate. I think your answer was insightful. I upvoted it (previously). Mar 28, 2022 at 1:04