Today I have been asked about a very common interception problem, which was originally about pirates, but let us wrap it into a different story :

Alice just spotted a white rabbit urging to its rabbit hole ! Given the coordinates of the positions , , of Alice, the bunny and the hole, as well as the respective speeds and of Alice and the rabbit, say whether Alice can catch the Rabbit before it disappears, and give the time and place of the fastest possible interception !

I guess that I am not the first one to solve this problem. However I couldn’t find any simple solution on the internet. So here is one, proving how helpful trigonometry can be when it comes to catching rabbits. The nice thing about it is that, while it relies on trigonometry, it doesn’t actually require to compute any trigonometrical function !

First it is obvious that, since we are looking for the fastest catch, Alice’s trajectory is a straight line. Let us call and the location and the time of the catch. We have then and . In our problem, finding the length would tell us whether Alice can catch the rabbit before is reaches the rabbit hole (case ), and would immediately lead to both the location and time of the interception :

To express BC using the coordinates of the points, let us apply the famous Law of Sines to the triangle :

Wich leads to

Now all we have to do is to express and in function of the given data. To do so we will first compute , then we will express with , and finally using the two first sines. The value of can be computed from the points coordinates as follows:

Then we use the Law of Sines again, to compute :

This only makes sense, of course, if . If this is not the case we can deduce that Alice will never catch the rabbit, which solves the problem.

Finally we use the fact that the angles of a triangle sum to to compute :

Here we are ! Below is a script implementing this technique using Python's **pylab** module (but any other langage would do !).

from pylab import * def interception(A, B, H, Sa, Sb): ''' Returns None if A cannot catch B before B reaches H. Otherwise it returns the time and position of the interception. See attached documentation for justifications. ''' sin_beta = det(array((A-B,H-B))) / ( norm(A-B) * norm(H-B) ) sin_alpha = (Sb / Sa) * sin_beta if abs(sin_alpha) > 1 : print "B moves too fast to be ever caught !" return None else: sin_gamma = ( sin_alpha * sqrt(1 - sin_beta**2) + sin_beta * sqrt(1 - sin_alpha**2) ) BC = norm(B-A) * (sin_alpha / sin_gamma) if BC > norm(H-A): print "B reaches H before being caught by A !" return None else: t = BC / Sb C = B + BC * (H-B)/norm(H-B) print "A intercepted B !" return t,C ##### EXAMPLE # Define the constants A = array(( 1.0 , 5.0 )) B = array(( 4.0 , 1.0 )) H = array(( 6.0 , 7.0 )) Sa = 1.1 Sb = 1.0 # Find the intersection t,C = interception(A, B, H, Sa, Sb) # Plot the results scatter(*zip(A,B,H,C), s=100, color='r') for label, point in zip(['A','B','H','C'], [A,B,H,C]): annotate( label, xy = point, xytext = (-10, 10), textcoords = 'offset points', fontsize = 24) annotate("", xy=H, xytext=B, xycoords='data', textcoords='data',size=20, arrowprops=dict(arrowstyle="simple",connectionstyle="arc3")) annotate("", xy=C, xytext=A, xycoords='data', textcoords='data',size=20, arrowprops=dict(arrowstyle="simple",connectionstyle="arc3")) title("A intercepts B in C", fontsize = 24) show()

And here is the result :