# How to plot hyperbola giving the foci and the fixed differene distance using TikZ

Given the two foci coordinates $(x_1,y_1)$ and $(x_2,y_2)$ of the hyperbola and the fixed difference distance, how I can draw it using TikZ?

Here a brief explanation:

• I don't know. What's the formula for it? – percusse Sep 25 '14 at 11:18
• here is a definition; mathwords.com/f/foci_hyperbola.htm – sys Sep 25 '14 at 11:24
• So, the "fixed difference distance" is 2*c, isn't it? – Dan H. Sep 25 '14 at 11:54
• I'd start by finding a way to represent your hyperbolas as parametrized curves. Once you have done that, plotting them is easy. Maybe Wikipedia can help you get started: en.wikipedia.org/wiki/Unit_hyperbola#Parametrization – Fritz Sep 25 '14 at 12:12
• @Fritz It's rarely a good idea :P – percusse Sep 25 '14 at 20:59

To obtain the hyperbola you can draw the standard one : x -> 1/x in an appropriate base with center the center of the hyperbola, and vectors on the asymptotes.

Here is a solution using pics introduced in TiKz 3.0 :

% definition of pic{hyperbola}
\tikzset{
pics/hyperbola/.style args={(#1)-<#2>-(#3)[#4]}{
code = { %
\draw [ samples=100, domain={{1/#4}:{#4}}, % the "size" of the hyperbola
shift=($(#1)!.5!(#3)$), % the center of the hyperbola
x=($(#1)!.25!atan(#2):(#3) - (#1)$), % the first vector of the new base
y=($(#1)!.25!-atan(#2):(#3) - (#1)$), % the second vector of the new base
pic actions % transfer pic's styles
]
plot (\x,1/\x) plot (-\x,-1/\x);
}
}
}

% example of use
\begin{tikzpicture}
\draw[help lines] (-4,-3) grid (4,4);
% the focal points
\fill (35:2) coordinate (F1) circle(1pt) node[above]{$F_1$};
\fill (0:-1) coordinate (F2) circle(1pt) node[below]{$F_2$};
% the center of the hyperbola
\fill ($(F1)!.5!(F2)$) circle(1pt) node[fill=white, above left]{$\frac{F_1+F_2}2$};
% the hyperbola with b/a=.7 and "domain" [1/5:5]
\path (0,0) pic[thick, red]{hyperbola={(F1)-<.7>-(F2)[5]}};
\end{tikzpicture}


To draw a hyperbola with focal points (F1) and (F2), with ratio b/a, and size s, you can now simply do :

\path (0,0) pic[thick, red]{hyperbola={(F1)-<b/a>-(F2)[s]}};


There is actually a (more or less) easy way to do this. You simply take the standard parametrization of a hyperbola which is centered around the origin and then rotate and shift it so that the foci lie in the desired position.

The only problem is that applying affine transformations on PGFplots coordinates is not build in, but thankfully the question How can I do an affine coordinate transformation in pgfplots? gives a very good solution to that, which I have adapted to take an angle instead of base vectors.

You can even draw TikZ decorations on the hyperbola as if it were centered around the origin, by using the shift and rotate around keys provided by TikZ. In case you are wondering: these do not work for transforming \addplot coordinates; instead they mess things up when used on plots.

The code itself is pretty straightforward and commented, so it should be easy to follow. :-)

\documentclass[tikz,margin=3pt]{standalone}
\usepackage{pgfplots}

\pgfplotsset{
% 3 Parameters: angle, xshift, yshift
rotate shift/.style n args={3}{
filter point/.code = {
\pgfkeysgetvalue{/data point/x}\X
\pgfkeysgetvalue{/data point/y}\Y
\pgfmathparse{cos(#1)*\X - sin(#1)*\Y + #2}
\pgfkeyslet{/data point/x}\pgfmathresult
\pgfmathparse{sin(#1)*\X + cos(#1)*\Y + #3}
\pgfkeyslet{/data point/y}\pgfmathresult
}
}
}

% Given: The two foci A and B
\def\Ax{-2}\def\Ay{1}
\def\Bx{3}\def\By{4}
% Given: a = half the distance difference
\def\a{2}

% Calculate half the focus distance c
\pgfmathsetmacro{\c}{sqrt((\Ax-\Bx)^2 + (\Ay-\By)^2)/2}
\pgfmathsetmacro{\b}{sqrt(\c^2-\a^2)}

% Calculate the rotation angle
\pgfmathsetmacro{\rotation}{atan2(\By-\Ay, \Bx-\Ax)}

% Calculate offset from origin to center between hyperbolas
\pgfmathsetmacro{\offsetX}{(\Ax+\Bx)/2}
\pgfmathsetmacro{\offsetY}{(\Ay+\By)/2}

\begin{document}
%\rotation
\begin{tikzpicture}
\begin{axis}[
axis equal,
axis lines=center,
]

% Draw the hyperbolas using the PGFplots rotate and shift key defined above.
% Everything is drawn as if the hyperbola were centered around (0,0)
\begin{scope}[/pgfplots/rotate shift={\rotation}{\offsetX}{\offsetY}]
\addplot[only marks, mark=+] coordinates {(-\c,0) (\c,0)};
\end{scope}

% Draw some annotations using the TikZ rotate and shift keys.
% Everything is drawn as if the hyperbola were centered around (0,0)
\begin{scope}[shift={(axis direction cs:\offsetX,\offsetY)}, rotate around={\rotation:(axis cs:0,0)}, ]
\draw (axis cs:-\c,0) -- (axis cs:\c,0);
\draw[densely dashed]
(axis cs:-\c,0) node[left] {A}
-- (axis cs:{\a*cosh(1)}, {\b*sinh(1)}) node[circle,fill, inner sep=1pt] {}
-- (axis cs:\c,0) node[right] {B};
\end{scope}
\end{axis}
\end{tikzpicture}
\end{document}

• what is '\a' represent here? – sys Sep 28 '14 at 11:28
• @sys: The difference distance is 2a, so \a is half the difference distance. It's even in the comments. ;-) – Fritz Sep 28 '14 at 14:12
• I think, to be more precis, 2a here is the horizontal distance difference, no? ;) – sys Oct 2 '14 at 14:43
• Well, the difference 2a is the horizontal distance between the two hyperbolas. But it also is the difference of the distances to the two foci, for any given point on one of the hyperbolas. At least as far as I understand it as a non-mathematician. ;-) – Fritz Oct 2 '14 at 23:52
• @MatthewLeingang Thanks for pointing it out. Actually I wanted to write "hyperbolas" but wrote "parabolas" instead. Now it's fixed. – Fritz Dec 8 '14 at 9:27

Here is an alternative solution with TikZ but without PGFPlots. The basic idea is the same as in Fritz's answer: rotate and shift. The parametrization is such that the user specifies the ratio of a to c (\acRatio), where c is half the distance between the foci and a is half the fixed difference of distances from a given point of the hyperbola to the two foci.

A good reference to the mathematics of the hyperbola can be found at Mathworld.

\documentclass[tikz,border=2pt]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}

% Clipping area
\pgfmathsetmacro{\clipLeft}{-4}
\pgfmathsetmacro{\clipRight}{4}
\pgfmathsetmacro{\clipBottom}{-1}
\pgfmathsetmacro{\clipTop}{4}
\clip (\clipLeft,\clipBottom) rectangle(\clipRight,\clipTop);

% Parameters of the hyperbola:
% - Foci (A) and (B). Their distance is 2*c.
% - Ratio of a to c, \acRatio, where a is half of the smallest
%   distance between the two sides of the hyperbola.
%   A number greater than 0, not larger than 1.
\coordinate (A) at (-0.3,1);
\coordinate (B) at (-0.2,2);
\pgfmathsetmacro{\acRatio}{0.35}

%% Computation
% Half the distance between foci
\coordinate (BA) at ($(B)-(A)$);
\newdimen\myBAx
\pgfextractx{\myBAx}{\pgfpointanchor{BA}{center}}
\newdimen\myBAy
\pgfextracty{\myBAy}{\pgfpointanchor{BA}{center}}
\pgfmathsetlengthmacro{\c}{veclen(\myBAx,\myBAy)/2}
% Semiminor axis
\pgfmathsetlengthmacro{\b}{sqrt(1-\acRatio^2)*\c}
% Semimajor axis
\pgfmathsetlengthmacro{\a}{\acRatio*\c}
% Rotation angle
\pgfmathanglebetweenlines{\pgfpoint{0}{0}}{\pgfpoint{1}{0}}
{\pgfpointanchor{A}{center}}{\pgfpointanchor{B}{center}}
\let\rotAngle\pgfmathresult
% Shift
\coordinate (O) at ($(A)!.5!(B)$);
%% Plotting
% Hyperbola. Adjust domain if a wider view is needed.
\tikzset{hyperbola/.style={rotate=\rotAngle,shift=(O),
domain=-3:3,variable=\t,samples=50,smooth}}
\draw[hyperbola] plot ({ \a*cosh(\t)},{\b*sinh(\t)});
\draw[hyperbola] plot ({-\a*cosh(\t)},{\b*sinh(\t)});
% Asymptotes
\pgfmathsetmacro{\baRatio}{\b/\a}
\tikzset{asymptote/.style={rotate=\rotAngle,shift=(O),
samples=2,domain=\clipLeft:\clipRight,dash pattern=on 2mm off 1mm}}
\draw[asymptote] plot ({\x},{\baRatio*\x});
\draw[asymptote] plot ({\x},{-\baRatio*\x});
% Axes
\tikzset{axis/.style={->,black!40}}
\draw[axis] (\clipLeft,0) -- (\clipRight,0);
\draw[axis] (0,\clipBottom) -- (0,\clipTop);
% Line segment between foci
\draw[blue,thick] (A) -- (O);
\draw[red,thick] (O) -- (B);
% Foci
\fill (A) circle (0.5mm);
\fill (B) circle (0.5mm);
\end{tikzpicture}
\end{document}