Collision of Ball in Triangle

373 Views Asked by At

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

There are 2 best solutions below

2
On BEST ANSWER

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.

8
On

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}")