geom.tangentpoints
drafting: P = geom.tangentpoints (C, R, Q)
Where the tangents from a point touch a circle.
P = geom.tangentpoints (C, R, Q) returns the
points at which the two lines through Q touch the circle of radius
R centred at C. P has two rows when Q lies outside
the circle and one when it lies on it, that one being Q itself.
Drawing the tangent from a point is how a belt is laid onto a pulley, a chamfer run out to a face, a leader taken to a hole without crossing it, and how the flanks of a slot meet its ends.
No line through a point inside a circle can touch it: every such line cuts it twice. There is no answer to return, so this raises rather than handing back an empty result that would read as "none happen to exist here".
See also: geom.intersectcircle, geom.intersectcircles, geom.fillet
Source Code: geom.tangentpoints
The tangent from a point is how a belt is laid onto a pulley, or a leader taken to a hole without crossing it. The radius to each contact meets the tangent at a right angle, which is what makes it a tangent.
C = [0, 0]; R = 20; Q = [70, 30]; P = geom.tangentpoints (C, R, Q)
P = -2.7743 19.8066 12.4295 -15.6687
D = draw.Drawing ().circle (C, R); D = D.line (Q, P(1,:)).line (Q, P(2,:));
the radius to each contact, which meets its tangent at a right angle
D.Colour = 'red';
D = D.line (C, P(1,:)).line (C, P(2,:));
plot (D);
title ('tangents from a point, with the radii to their contacts');
A belt over two pulleys is four tangents and two arcs. Here is the open belt, taking the outer tangent on each side.
C1 = [0, 0]; R1 = 25; C2 = [90, 0]; R2 = 12;
The outer tangent touches where a circle of the radius difference does
T = geom.tangentpoints (C1, R1 - R2, C2);
D = draw.Drawing ().circle (C1, R1).circle (C2, R2);
for k = 1:2
u = (T(k,:) - C1) / norm (T(k,:) - C1);
D = D.line (C1 + R1 * u, C2 + R2 * u);
endfor
plot (D);
title ('an open belt over two pulleys');