Skip to content

Instantly share code, notes, and snippets.

@alexhunsley
Created January 30, 2025 10:50
Show Gist options
  • Save alexhunsley/38021a320fcceae39bba70e4c4daa083 to your computer and use it in GitHub Desktop.
Save alexhunsley/38021a320fcceae39bba70e4c4daa083 to your computer and use it in GitHub Desktop.
Bad python code found on social media for intersection of objects. Don't do this!
import math
def perpendicular_interceptor(pO, vO, pI, speedI):
"""
Calculates an interceptor velocity that is perpendicular to vO and
finds the time of intercept, if it exists.
Parameters:
-----------
pO : tuple (xO, yO)
Target's initial position.
vO : tuple (vOx, vOy)
Target's velocity.
pI : tuple (xI, yI)
Interceptor's initial position.
speedI : float
The interceptor's desired speed.
Returns:
--------
(vI, t) : (tuple, float) or (None, None)
vI is the interceptor's velocity vector (vx, vy).
t is the time at which the interceptor meets the target.
If no positive solution for t is found, (None, None) is returned.
"""
# 1. Construct a perpendicular vector to vO in 2D.
# A vector perpendicular to (vOx, vOy) can be (vOy, -vOx) or (-vOy, vOx).
vOx, vOy = vO
perp_vec = (vOy, -vOx)
print(perp_vec)
# 2. Normalize and scale by speedI to get the interceptor velocity.
# norm = sqrt(vOy^2 + (-vOx)^2) = sqrt(vOx^2 + vOy^2)
magnitude = math.sqrt(perp_vec[0]**2 + perp_vec[1]**2)
print(magnitude)
if magnitude == 0:
# If the target has no velocity, perpendicular isn't defined.
return (None, None)
factor = speedI / magnitude
vIx = perp_vec[0] * factor
vIy = perp_vec[1] * factor
# 3. Solve for intercept time.
# We need pO + vO*t = pI + vI*t => (vO - vI)*t = pI - pO
# We'll find t from x-component and y-component, then check if they match.
xO, yO = pO
xI, yI = pI
# Compute differences
dx = xI - xO
dy = yI - yO
# Differences in velocity
dvx = vOx - vIx
dvy = vOy - vIy
t_candidates = []
# From x-component if dvx != 0
if abs(dvx) > 1e-12:
tx = dx / dvx
t_candidates.append(tx)
# From y-component if dvy != 0
if abs(dvy) > 1e-12:
ty = dy / dvy
t_candidates.append(ty)
# If both x and y gave us times, we need them to be "close" to each other.
# If only one gave a time, we use that. If neither did, there's no solution.
if len(t_candidates) == 0:
# Means the interceptor velocity exactly matches the target’s velocity in x and y,
# or the target is stationary.
return (None, None)
if len(t_candidates) == 1:
t = t_candidates[0]
else:
# We have two values: tx and ty. They must match within a small tolerance.
tx, ty = t_candidates
if abs(tx - ty) < 1e-9:
t = (tx + ty) / 2.0 # they are effectively the same
else:
return (None, None)
# We want a positive time for a future intercept.
if t < 0:
return (None, None)
# Return the interceptor velocity vector and time
return ((vIx, vIy), t)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment