# Using calc: Draw tangent lines to an ellipse path by tikz

I wonder if one can draw tangent lines out of a point to a path of an ellipse using tikz. Actually for the case of circle paths this can be accomplished easily as given in the tikz-pgf manual, but for other paths it wouldn't be an easy task.

I have tried to solve this problem with the help of some threads, but my solution, unfortunately, relies on some mathematical background. I wonder if I could solve the same problem with pure tikz.

Here is my solution:

\documentclass{standalone}
\usepackage{tikz,pgfplots}
\usetikzlibrary{calc,intersections,arrows}
\usepackage{times}
\begin{document}

\begin{tikzpicture}[scale=1,>=latex',scale=1.5,outer sep=0,inner sep=0,line width=0.7pt]

\def\a{2} \def\b{1}    % radii of Ellipse
\def\cx{0} \def\cy{0}  % determines center of Ellipse
\def\xp{0} \def\yp{-5} % coordinates of point P

\coordinate (P) at (\xp,\yp);
\coordinate (A) at (0,\b);   % up
\coordinate (B) at (0,-\b);  % down
\coordinate (C) at (\a,0);   % right

\draw[name path=ellipse,fill=gray!30,opacity=0.5](\cx,\cy)circle[x radius=\a,y radius=\b];

\path[name path=linePC] (P)--(C);
\path[name path=linePC] (P)--(C);

\path [name intersections={of = ellipse and linePC}];
\coordinate (E) at (intersection-2);
\coordinate (F) at (intersection of A--C and B--E);
\path let \p1=(F) in node (G) at (-1.2*\a,\y1){};

\path[name path=lineFG] (F)--(G);
\path [name intersections={of = ellipse and lineFG}];
\coordinate (X) at (intersection-1);
\coordinate (Y) at (intersection-2);
\draw (X)--(P)--(Y);

%%%%%%%%%%%%%%%%%%%%%% Second Ellipse%%%%%%%%%%%%%%
\def\a{1} \def\b{0.5}  % radii of Ellipse
\def\cx{0} \def\cy{0}  % determines center of Ellipse
\def\xp{0} \def\yp{-5} % coordinates of point P

\coordinate (P) at (\xp,\yp);
\coordinate (A) at (0,\b);   % up
\coordinate (B) at (0,-\b);  % down
\coordinate (C) at (\a,0);   % right

\draw[name path=ellipse,fill=white](\cx,\cy)circle[x radius=\a,y radius=\b];

\path[name path=linePC] (P)--(C);
\path[name path=linePC] (P)--(C);

\path [name intersections={of = ellipse and linePC}];
\coordinate (E) at (intersection-2);
\coordinate (F) at (intersection of A--C and B--E);
\path let \p1=(F) in node (G) at (-1.2*\a,\y1){};

\path[name path=lineFG] (F)--(G);
\path [name intersections={of = ellipse and lineFG}];
\coordinate (X) at (intersection-1);
\coordinate (Y) at (intersection-2);
\draw (X)--(P) (P)--(Y);

\draw [->,thin](0,-5.5)--(0,1.5) node[above]{$z$};
\draw [<-,shorten <=0.2pt,thin](P)--+(0.4,-0.1) node[right]{Gap};

\draw [->,thin](0,-2.2) arc (90:65.4:2.5);
\node [fill=white] at (0.5,-2.5){$\theta_2$};
\draw [->,thin](0,-3.5) arc (90:79:1.6);
\node  at (0.13,-3.7){$\theta_1$};

\end{tikzpicture}

\end{document}


I appreciate your help and thank you in advance.

• Is this actually valid or is it just a good approximation? I don't mean to downplay it, but I cannot figure out how it works. – John Kormylo Jul 18 '14 at 22:30
• I was checking out how tikz does intersections, and discovered it uses closed form solutions. Specifically, paths consist of segments of lines and a limited variety of curves. For any given combination of segments, it finds the intersections and checks to see if they lie within the segment limits. – John Kormylo Jul 25 '14 at 3:56

## 3 Answers

If we were dealing with circles, then the radius would be perpendicular to the tangent, so we would need to find a right triangle connecting the center C, point P, and the circle. If you recall your geometry, any triangle inscribed in a circle where one side of the triangle passes through the center will form a right triangle. So if we construct a circle whose center is the midpoint between P and C, the intersection of the two circles is the point(s) of tangency.

Since ellipses can be thought of as circles seen from an angle, instead of a circle we need an ellipse with the same aspect ratio.

For the purposes of illustration, I made the construct visible (pink).

\documentclass{standalone}
\usepackage{tikz,pgfplots}
\usetikzlibrary{calc,intersections,arrows}
\usepackage{times}
\begin{document}

\begin{tikzpicture}[scale=1,>=latex',scale=1.5,outer sep=0,inner sep=0,line width=0.7pt]

\def\a{2} \def\b{1}    % radii of Ellipse
\def\cx{0} \def\cy{0}  % determines center of Ellipse
\def\xp{0} \def\yp{-5} % coordinates of point P

\coordinate (C) at (\cx,\cy);% center of ellipse
\coordinate (P) at (\xp,\yp);% focal point

\draw[name path=ellipse,fill=gray!30,opacity=0.5](C)circle[x radius=\a,y radius=\b];

\pgfmathparse{abs(\cx-\xp)/\a}% compute normalized distance from C to P
\edef\dx{\pgfmathresult}
\pgfmathparse{abs(\cy-\yp)/\b}
\edef\dy{\pgfmathresult}
\pgfmathparse{0.5*ifthenelse(\dx,ifthenelse(\dy,sqrt(\dx*\dx+\dy*\dy),\dx),\dy)}
\edef\d{\pgfmathresult}% half the distance from C to P
\pgfmathparse{\a*\d}% compute ellipse radii
\edef\rx{\pgfmathresult}
\pgfmathparse{\b*\d}
\edef\ry{\pgfmathresult}

\draw[color=pink,name path=construct] ($(C)!0.5!(P)$) circle[x radius=\rx, y radius=\ry];
\path [name intersections={of = ellipse and construct}];
\coordinate (X) at (intersection-1);
\coordinate (Y) at (intersection-2);

\draw (X)--(P)--(Y);

\end{tikzpicture}
\end{document} • Thank you Kormylo for your contribution. I wrote "but my solution, unfortunately, relies on some mathematical background". In your solution you have used similar approach to mine except you have used circles to calculate intersection points and I used lines. The accepted solution should only be based on tikz algorithms without much geometry. – AboAmmar Jul 18 '14 at 19:46
• @AboAmmar The use of TikZ always relies on some mathematical background... – Paul Gaborit Jul 19 '14 at 7:38

A pure PSTricks solution for fun.

\documentclass[pstricks,border=12pt,dvipsnames]{standalone}
\usepackage{pstricks-add}

\psset
{
urx=15pt,
ury=15pt,
llx=-5pt,
lly=-5pt,
xAxisLabel=$x$,
yAxisLabel=$y$,
algebraic,
plotpoints=1000,
tickcolor=gray,
}

\def\ChangeEvalVariable#1{%
\pstVerb{tx@Derive begin
/origEvalVariable /EvalVariable load def
/EvalVariable { 2 index (#1) eq { (1) } { (0) } ifelse 4 -1 roll exch 6 2 roll } def
end }%
}%
\def\ResetEvalVariable{%
\pstVerb{tx@Derive begin
/EvalVariable /origEvalVariable load def
end }%
}%

\def\x{2*cos(t)}
\def\y{sin(t)}

\def\xp{Derive(1,\x)}
\def\yp{Derive(1,\y)}

\begin{document}
\begin{psgraph}[linecolor=gray,axespos=top]{<->}(0,0)(-3,-3)(3,3){\dimexpr6cm-30pt}{!}
\ChangeEvalVariable{t}
\psparametricplot[linecolor=NavyBlue,strokeopacity=.5]{0}{TwoPi}{\x|\y}
\psplotTangent[linecolor=Red,Derive={\xp|\yp}]{Pi 4 div}{2}{\x|\y}
\psplotTangent[linecolor=ForestGreen,Derive={-\yp|\xp}]{Pi 4 div}{2}{\x|\y}
\ResetEvalVariable
\end{psgraph}
\end{document} Note: \ChangeEvalVariable{t} and \ResetEvalVariable are macros developed by Christoph here (click).

This uses a binary search to find the tangent. The only knowledge of geometry required here is that the tangent is located somewhere inside the arc formed by a miss. Will work on any closed shape.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,intersections,arrows}

\newlength{\bigenough}
\newcount\total

% locates both points on a closed shape tangent to a point outside the shape.
% \tangent{pathname}{center}{point}{first}{second}
\newcommand{\tangent}% #1=path name for shape, #2=coordinate name for center, #3=cordinate name for outside point
{\begingroup% #4=coordinate name for first tangent point, #5=coordinate name for second coordinate point
\setlength{\bigenough}{1cm}
\loop% loop until big enough
\path[name path=temp]  ($(#2)!\bigenough!-90:(#3)$)--($(#2)!\bigenough!90:(#3)$);
\path[name intersections={of = #1 and temp, total=\t}]%
\pgfextra{\global\total=\t};%
\ifnum\total<2 \global\bigenough=2\bigenough\repeat%
\endgroup
\coordinate (#4) at (intersection-1);% initial guess
\coordinate (#5) at (intersection-2);%
\tangentsearch{#1}{#2}{#3}{#4}%
\tangentsearch{#1}{#2}{#3}{#5}}

% find tangent using binary search
\newcommand{\tangentsearch}% #1=path name for shape, #2=coordinate name for center, #3=cordinate name for outside point
{\begingroup% #4=coordinate name for tangent point (initail guess -> final)
\loop% loop until only 1 intersection
\path[name path=temp] (#3)--($(#4)!-\bigenough!(#3)$);
\path[name intersections={of = #1 and temp, total=\t}]%
\pgfextra{\global\total=\t};%
\ifnum\total=2 \coordinate (#4) at ($(intersection-1)!0.5!(intersection-2)$);
\draw[pink] (intersection-1)--(intersection-2);% included only for debugging purposes
\path[name path=temp] (#4)--($(#4)!-\bigenough!(#2)$);
\path[name intersections={of = #1 and temp}];%
\coordinate (#4) at (intersection-1);%
\repeat%
\endgroup}

\begin{document}

\begin{tikzpicture}[scale=1,>=latex',scale=1.5,outer sep=0,inner sep=0,line width=0.7pt]

\def\a{2} \def\b{1}    % radii of Ellipse
\def\cx{0} \def\cy{0}  % determines center of Ellipse
\def\xp{0} \def\yp{-5} % coordinates of point P

\coordinate (C) at (\cx,\cy);
\coordinate (P) at (\xp,\yp);
\coordinate (A) at (\a,0);   % initial guess

\draw[name path=ellipse,fill=gray!30,opacity=0.5](\cx,\cy)circle[x radius=\a,y radius=\b];

\tangent{ellipse}{C}{P}{X}{Y}
\draw (X)--(P)--(Y);

\end{tikzpicture}

\end{document} If you look closely you can see little pink lines of chords from misses.