# Can PSTricks or others draw the 4 common tangent lines of 2 “disjoint” circles without having to do extra calculations?

There are two disjoint circles. Their centers and radii are given. Without doing extra calculations, can we draw the 4 tangent lines using PSTricks (preferred) or others?

I asked many Illustrator, Free-hand, CAD experts, they cannot do it exactly. :-)

• What do you mean by "without doing extra calculations"? – Yossi Farjoun Dec 16 '10 at 9:05
• @Yossi, without doing extra calculation means we don't need to do trigonometric calculations. I think you know what I mean. – xport Dec 16 '10 at 11:11
• Actually, I'm really not sure...is the answer given by Andrew good or did you hope for something like the TikZ tangent option only that it can take two circles instead of a point and a circle? – Yossi Farjoun Dec 16 '10 at 11:40
• This can be done by rule and compass. Some GUI grograms, like GeoGebra, Geometer's Sketchpad can draw such Euclidian geometry graphs easily. – Leo Liu Feb 1 '11 at 16:11

## 4 Answers

pstricks-add knows a macro for calculating and saving 10 points as nodes, the two central points and the four points on each circle. See the documentation (run texdoc pstricks-add) for the names:

\documentclass[pstricks,border=20pt]{standalone}
\usepackage{pstricks-add}% loads also pst-node

\begin{document}
\begin{pspicture}[showgrid](-2,-2)(10,10)
\pnodes(1,1){M1}(7,7){M2}
\pscircle(M1){1}\pscircle(M2){3}
\psCircleTangents(M1){1}(M2){3}
\pcline[nodesepA=-1cm,nodesepB=-4.5cm,linecolor=blue](CircleTO1)(CircleTO2)
\pcline[nodesepA=-1cm,nodesepB=-4.5cm,linecolor=blue](CircleTO3)(CircleTO4)
\pcline[nodesep=-1cm,linecolor=red](CircleTI1)(CircleTI2)
\pcline[nodesep=-1cm,linecolor=red](CircleTI3)(CircleTI4)
\psdots(M1)(M2)(CircleTC1)(CircleTC2)%
(CircleTO1)(CircleTO2)(CircleTO3)(CircleTO4)%
(CircleTI1)(CircleTI2)(CircleTI3)(CircleTI4)%
\end{pspicture}

\end{document} • This is a solution with no extra calculations! +1 Very nice! – Yossi Farjoun Dec 17 '10 at 15:37
• Just out of curiosity: Did you just implement that feature/function? Two versions (that is 4 days - from ctan.org) back it did not exist. – Carsten Thiel Dec 17 '10 at 15:55
• The solution in pst-eucl needs some understanding on how tangent lines are build. The tangents of two circles is the same as 2 times the tangents of a point and one circle. The macro \psCircleTangents from pstricks-add didn't need any understanding of the geometry behind the constructiong of the tangent lines. The package on texnik.dante.de are development versions and will be as soon as possible on CTAN when no problems are posted. – user2478 Dec 17 '10 at 18:20
• from today it should be available by the TeXLive update manager. Read the documentation (run "texdoc pstricks-add") to see how the macro works for one circle and two circles. – user2478 Dec 19 '10 at 8:04
• thanks. Indeed the documentation was written with hot needles ... I'll correct the typos – user2478 Dec 19 '10 at 20:13

TikZ can work out the tangent line between a circle and a point, so it's halfway there for this. With a tiny bit of mathematics, this can be bootstrapped to the tangent lines you want. The following code will do it (though it ought to check for the case where the two radii are the same - at the moment, that will produce an error, as will the situation where the circles overlap).

Here's the result: Here's the code:

\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\rone}{3}
\pgfmathsetmacro{\rtwo}{2}
\pgfmathsetmacro{\mid}{\rone/(\rone + \rtwo)}
\pgfmathsetmacro{\out}{\rone/(\rone - \rtwo)}
\node[draw,circle,minimum size=2 * \rone cm,inner sep=0pt] (c1) at (1,0) {};
\node[draw,circle,minimum size=2 * \rtwo cm,inner sep=0pt] (c2) at (-1,-6) {};
\path (c1.center) -- node[coordinate,pos=\mid] (mid) {} (c2.center);
\path (c1.center) -- node[coordinate,pos=\out] (out) {}  (c2.center);

%\draw[red] (tangent cs:node=c2,point={(mid)}) -- (tangent cs:node=c1,point={(mid)});
%\draw[red] (tangent cs:node=c2,point={(mid)},solution=2) -- (tangent cs:node=c1,point={(mid)},solution=2);

%\draw[red] (tangent cs:node=c2,point={(out)}) -- (tangent cs:node=c1,point={(out)});
%\draw[red] (tangent cs:node=c2,point={(out)},solution=2) -- (tangent cs:node=c1,point={(out)},solution=2);

\foreach \i in {1,2}
\foreach \j in {1,2}
\foreach \k in {mid,out}
\coordinate (t\i\j\k) at (tangent cs:node=c\i,point={(\k)},solution=\j);

\foreach \i in {1,2}
\foreach \k in {mid,out}
\draw[red] ($(t1\i\k)!-1cm!(t2\i\k)$) --  ($(t2\i\k)!-1cm!(t1\i\k)$);

\end{tikzpicture}
\end{document}


The commented-out lines will draw the tangent lines to the exact points, I chose to extend them a little to show that they were genuinely tangent and that's what the code after the commented-out lines are for.

Despite being a mathematician, I didn't actually compute the formulae for the crossing points - I just guessed something that "felt right" and then tested it and it seems to work. However, I can't guarantee that it is right.

• Fantastic...I was working on it myself...but you beat me to the punch! – Yossi Farjoun Dec 16 '10 at 10:29
• @Yossi: If you had a different implementation, you should still post it. – Andrew Stacey Dec 16 '10 at 10:31
• cheers, it is not significantly different, and much less neat...I like your answer. don't worry.. – Yossi Farjoun Dec 16 '10 at 10:33

The next version of tkz-euclide can draw the tangent lines. I created two macro for the internal similitude center of two circles and the external similitude center.

\documentclass{scrartcl}
\usepackage[usenames,dvipsnames]{xcolor}
\usepackage{tkz-euclide}
\usetkzobj{all}
\definecolor{fondpaille}{cmyk}{0,0,0.1,0}
\pagecolor{fondpaille}
\color{Maroon}

\begin{document}
\begin{tikzpicture}
\tkzInit[xmin=-5,ymin=-5,xmax=5,ymax=5]
\tkzDefPoint(0,0){O}
\tkzDefPoint(4,-5){A}
\tkzDrawCircle[R](O,3 cm)
\tkzDrawCircle[R](A,2 cm)
\tkzIntSimilitudeCenter(O,3)(A,2) \tkzGetPoint{I}
\tkzDrawPoint(I)
\tkzExtSimilitudeCenter(O,3)(A,2) \tkzGetPoint{J}
\tkzDrawPoint(J)
\tkzTangent[from with R= I](O,3 cm)  \tkzGetPoints{D}{E}
\tkzTangent[from with R= I](A,2 cm)  \tkzGetPoints{D'}{E'}
\tkzTangent[from  with R= J](O,3 cm) \tkzGetPoints{F}{G}
\tkzTangent[from with R= J](A,2cm)   \tkzGetPoints{F'}{G'}
\tkzDrawSegments[color=red](I,D I,E I,D' I,E')
\tkzDrawSegments[color=blue](J,F J,G)
\end{tikzpicture}

\end{document}


the code is very simple to get these centers:

%<--------------------------------------------------------------------------–>
%                    Internal Similitude center
%<--------------------------------------------------------------------------–>
\def\tkzIntSimilitudeCenter(#1,#2)(#3,#4){%
\begingroup
\path[coordinate]  (barycentric cs:#1=#4,#3=#2) coordinate (tkzPointResult);
\endgroup
}
%<--------------------------------------------------------------------------–>
%                    External Similitude center
%<--------------------------------------------------------------------------–>
\def\tkzExtSimilitudeCenter(#1,#2)(#3,#4){%
\begingroup
\path[coordinate]  (barycentric cs:#1=-#4,#3=#2) coordinate (tkzPointResult);
\endgroup
}


Then we can get the tangents. The code will be upload in a few days on the ctan servers. • Thanks for this solution. I am learning PGF/Tikz now because of its better syntax and one-step compilation. – xport Mar 10 '11 at 1:08
• @xport: I think it's a good experience. Andrew's solution is interesting too. My package will be updated in a few days beacause I have a lot of works on others packages. – Alain Matthes Mar 10 '11 at 5:59

I saw this old problem showing up recently (because someone edited one of the answers of comments), and I felt like making a MetaPost solution of it. Here it is — a "rule-and-compass" solution.

Since there is no native macro in MetaPost giving the tangents of a circle through an external point, I've created my own, which I use to solve the general problem. The trick is to consider that the two circles are homothetic (thus similar) and to find the centers of the corresponding homotheties (when existing). This program takes into account the case where both circles share the same radius.

% parameters
numeric u; u = 1cm; % unit length;

% For drawing straight lines, not segments
vardef straight_line(expr A, B) =
A + 1.5u*unitvector(A-B) -- B + 1.5u*unitvector(B-A)
enddef;

% Macro finding the point M of the circle such that (IM) is tangent to the   circle
% and such that the angle (IC, IM) is positive
vardef tangent_point_circle(expr I)(expr C, r) =
save intersect, cercle; pair intersect; path cercle[];
cercle1 = fullcircle rotated (angle(C-I)) scaled 2r shifted C;
cercle2 = fullcircle scaled (abs(C-I)) shifted (.5[C, I]);
if cercle1 intersectiontimes cercle2 <> (-1, -1):
cercle1 intersectionpoint cercle2
fi
enddef;

% Macro taking care of the four tangents
def four_tangents_of_circles(expr C_a, r_a)(expr C_b, r_b) =

begingroup;
save I, J, w, C, r, circle; clearxy;
numeric r[]; pair I, J, C[], w[]; path circle[];
C1=C_a; C2=C_b; r1=r_a; r2=r_b;

for i=1,2:
circle[i] = fullcircle scaled 2r[i] shifted C[i]; draw circle[i];
endfor;

% Creating two intermediate radii for finding the centers of the homothecies
z1 = ((C1--C2) rotatedaround (C1,90)) intersectionpoint circle1;
w1 = z1 rotatedaround(C1, 180);
z2 = ((C2--C1) rotatedaround (C2, 90)) intersectionpoint circle2;
w2 = z2 rotatedaround(C2, 180);

if r1 + r2 < abs(C2-C1): % The circles must be distinct, otherwise nothing is done

% First couple of tangents (intersection located between the circles)
drawoptions(withcolor blue);
I = whatever[w1, w2] = whatever[z1, z2];
pair S[], T[];
for i=1,2:
S[i] = tangent_point_circle(I)(C[i], r[i]);
T[i] = S[i] reflectedabout(C1, C2);
endfor;
draw straight_line(S1, S2);
draw straight_line(T1, T2);

% Second couple of tangents (intersection located outside both circles)
drawoptions(withcolor red);
if r1<>r2:
J = whatever[w1, z2] = whatever[w2, z1];
pair S[], T[];
S1 = tangent_point_circle(J)(C1, r1);
T1 = S1 reflectedabout(C1, C2);
S2 = tangent_point_circle(J)(C2, r2);
T2 = S2 reflectedabout(C1, C2);
if r1 > r2:
draw straight_line(J, S1);
draw straight_line(J, T1);
else:
draw straight_line(J, S2);
draw straight_line(J, T2);
fi;
else: % (same radius)
draw straight_line(z1, w2);
draw straight_line(z2, w1);
fi;

fi;
endgroup;
enddef;

% Two examples in two separated figures
beginfig(1);
four_tangents_of_circles ((-u, 2u), 2u) ((3u, 3u), u);% illustration of the general case
endfig;

beginfig(2);
four_tangents_of_circles ((-u, 2u), 2u) ((5u, 2u), 2u);% two circles with same radius
endfig;

end.  