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

enter image description here

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.

Link to Desmos Computation: Here


2 Answers 2


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.

  • $\begingroup$ Thank you for the answer, Steve. Let me try this out. $\endgroup$
    – rb3652
    Feb 19, 2022 at 1:47
  • 2
    $\begingroup$ Wow Steve. You caught a really small typo -- indeed, it was the negative sign that was tripping all the answers. Thanks a bunch. $\endgroup$
    – rb3652
    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}")
  • $\begingroup$ Thanks @copper.hat! Quite insightful. I will look through the full code later, but I didn't think of this. $\endgroup$
    – rb3652
    Feb 19, 2022 at 15:24
  • $\begingroup$ Basically it places the triangle vertices into 4 quadrants based on $P_0,V_0$. $\endgroup$
    – copper.hat
    Feb 19, 2022 at 16:02
  • $\begingroup$ Oh!!! I tried this! Yes, indeed. See: chat.stackexchange.com/transcript/message/60466585#60466585 $\endgroup$
    – rb3652
    Feb 19, 2022 at 16:29
  • $\begingroup$ Why the down vote? $\endgroup$
    – copper.hat
    Mar 27, 2022 at 7:52
  • 1
    $\begingroup$ Hm, unfortunate. I think your answer was insightful. I upvoted it (previously). $\endgroup$
    – rb3652
    Mar 28, 2022 at 1:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .