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:

enter image description here enter image description here


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}
  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
  \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]}};

enter image description here

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.

Prametrization of hyperbolas

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.

Annotated Hyperbola

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


   % 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
% Given: a = half the distance difference

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

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

% Calculate offset from origin to center between hyperbolas

    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[domain=-2:2] ({\a*cosh(x)}, {\b*sinh(x)});
    \addplot[domain=-2:2] ({-\a*cosh(x)}, {\b*sinh(x)});
    \addplot[only marks, mark=+] coordinates {(-\c,0) (\c,0)};

% 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};
  • 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
  • 1
    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
  • 1
    @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.

Output of example code


% Clipping area
\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);

%% Computation
% Half the distance between foci
\coordinate (BA) at ($ (B)-(A) $);
% Semiminor axis
% Semimajor axis
% Rotation angle
% Shift
\coordinate (O) at ($ (A)!.5!(B) $);
%% Plotting
% Hyperbola. Adjust domain if a wider view is needed.
\draw[hyperbola] plot ({ \a*cosh(\t)},{\b*sinh(\t)});
\draw[hyperbola] plot ({-\a*cosh(\t)},{\b*sinh(\t)});
% Asymptotes
    samples=2,domain=\clipLeft:\clipRight,dash pattern=on 2mm off 1mm}}
\draw[asymptote] plot ({\x},{\baRatio*\x});
\draw[asymptote] plot ({\x},{-\baRatio*\x});
% Axes
\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);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.