5

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

Dan H.
  • 462
sys
  • 153
  • I don't know. What's the formula for it? – percusse Sep 25 '14 at 11:18
  • here is a definition; http://www.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: http://en.wikipedia.org/wiki/Unit_hyperbola#Parametrization – Fritz Sep 25 '14 at 12:12
  • Also, that would probably be a good question for http://math.stackexchange.com/ – Fritz Sep 25 '14 at 12:12
  • I know have have asked questions on this and there are answers to it. I am on my iPad so I won't look up the thread now but they do exist. – dustin Sep 25 '14 at 12:32
  • yes, the fixe difference distance according to the explanation is 2*c – sys Sep 25 '14 at 12:44
  • sorry, the fixe difference distance according to the explanation is 2a and not 2c – sys Sep 25 '14 at 13:06
  • here is one part answer of my question from mathexchange:http://math.stackexchange.com/questions/945642/how-to-derive-the-hyperbola-giving-the-foci-and-the-fixed-differene/945662#945662 – sys Sep 25 '14 at 13:39
  • Given the focal points, one can compute h=(x_1+x_2)/2 and k=(y_1+y_2)/2 and the distance between them is 2c. Given the fixed difference 2a (for horizontal) one can compute b. You now have y as function of x, or vice verses. If you prefer polar, r = b^2/(c\cos\theta - a) where r and \theta are from the right focus. – John Kormylo Sep 25 '14 at 16:05
  • ... and \theta is measured relative to the line passing through the foci. – John Kormylo Sep 25 '14 at 16:10
  • We need parametrization I think, no? – sys Sep 25 '14 at 16:18
  • It's easier than I thought. Maybe asking the mathematicians wasn't such a good idea after all. ;-) – Fritz Sep 25 '14 at 20:51
  • 2
    @Fritz It's rarely a good idea :P – percusse Sep 25 '14 at 20:59

3 Answers3

6

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. :-)

\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[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)};
\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}
Fritz
  • 6,273
  • 31
  • 55
  • 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 02 '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 02 '14 at 23:52
  • Good answer. Just a note from the math police: I can't tell for sure but it looks like you're referring to the separate branches of the hyperbola as "parabolas". They should just be called branches. – Matthew Leingang Dec 05 '14 at 16:39
  • 1
    @MatthewLeingang Thanks for pointing it out. Actually I wanted to write "hyperbolas" but wrote "parabolas" instead. Now it's fixed. – Fritz Dec 08 '14 at 09:27
3

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

\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}
mvkorpel
  • 1,598
3

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}

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]}};
Kpym
  • 23,002