tangents to a circle through a point

Started by
12 comments, last by Jkom329 15 years, 9 months ago
I haven't had much luck searching the internet for code to find the tangents to a circle, which pass though a external point, so i wrote this one up:
def find_tangents_through_point(circle_center, circle_radius, point):
	#find the direction from the point to the center of the circle
	dir = point - circle_center
	#extract the length and angle
	len = dir.length
	angle = atan2(dir.y, dir.x)
	
	# derive the length of the tangent using pythagoras
	tangent_len = sqrt(len**2 + circle_radius**2)
	# and the angle using trigonometry
	tangent_angle = atan(circle_radius/len)
	
	# there are 2 tangents, one either side
	pos = angle + tangent_angle
	neg = angle - tangent_angle
	
	#return the direction vector of each tanget (the starting point was passed in)
	return ( vec2d(cos(pos), sin(pos)), vec2d(cos(neg), sin(neg)) )
Unfortunately, it seems to have some accuracy problems:
find_tangents_through_point( vec2d(0,0), 2.0, vec2d(2.0,2.0) )
yields:
vec2d(0.169101983309, 0.985598564148), vec2d(0.985598564148, 0.169101983309)
instead of the expected (0, 1), (1, 0). Any ideas where the inaccuracy is coming from? Am I doing something silly re floating point error?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Advertisement
Ah, I see where I went wrong: I assumed that a line connecting the pair of tangent points would pass through the center of the circle, which is clearly not the case.

So, back to the drawing board. Does anyone have a link/explanation of how to find these 'horizon' points?

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Argh, not my day for thinking things out. I now realise that I had rotated the triangle in my mind, and placed the right angle at the center, rather than at the tangent point :)

In case anybody wants it, the working version (note that tangent_len is the distance from the point to the tangent point):
def find_tangents_through_point(circle_center, circle_radius, point):	#find the direction from the point to the center of the circle	dir = point - circle_center	#extract the length and angle	len = dir.length	angle = atan2(dir.y, dir.x)		# derive the length of the tangent using pythagoras	tangent_len = sqrt(len**2 - circle_radius**2)	# and the angle using trigonometry	tangent_angle = asin(circle_radius/len)		# there are 2 tangents, one either side	pos = angle + tangent_angle	neg = angle - tangent_angle			#return the direction vector of each tanget (the starting point was passed in)	return ( vec2d(cos(pos), sin(pos)), vec2d(cos(neg), sin(neg)) )

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

The key truth to note here is that the vector from your outside point to your tangent point forms a right angle with the vector from your tangent point to the center of your circle.

Definitions: r=radius of circle, A=center of circle, B=outside point, C=one tangent point, |AB|=length from A to B

So, using Pythagoras, you can find that |BC| = sqrt(|AB|^2 - r^2).

So now you have a right triangle, and you know the lengths of all three sides and the locations of two of the points (A and B). Finding the two possible locations of the third point yields your two tangent points.
Wow, guess I typed that too slow :-)
Quote:Original post by BeanDog
Wow, guess I typed that too slow :-)
Thanks anyway!

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Quote:Original post by swiftcoder
Ah, I see where I went wrong: I assumed that a line connecting the pair of tangent points would pass through the center of the circle, which is clearly not the case.

Which is actually quite impossible [grin] I'm surprised that your code didn't somehow divide by zero, or implode the universe, or do some other horrible thing!
Quote:Original post by Zipster
Quote:Original post by swiftcoder
Ah, I see where I went wrong: I assumed that a line connecting the pair of tangent points would pass through the center of the circle, which is clearly not the case.

Which is actually quite impossible [grin] I'm surprised that your code didn't somehow divide by zero, or implode the universe, or do some other horrible thing!
Well, it wasn't so bad. Basically I was just calculating secant lines (lower figure) instead of tangent lines (upper figure):



Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

You should also be able to use differential equations here:

Nevermind that, it was a complete disaster. I need to redo it.

[Edited by - Jkom329 on July 2, 2008 5:50:12 PM]
Quote:Original post by Jkom329
You should also be able to use differential equations here...
That looks about right to me, I might re-implement it that way if it shows up in the profiler :)

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement