Dadas las coordenadas de los dos focos $(x_1,y_1)$
y $(x_2,y_2)$
de la hipérbola y la distancia de diferencia fija, ¿cómo puedo dibujarla usando TikZ?
Aquí una breve explicación:
Respuesta1
Para obtener la hipérbola se puede dibujar la estándar: x -> 1/x
en una base adecuada con centro en el centro de la hipérbola y vectores en las asíntotas.
Aquí hay una solución que pics
se introduce en 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}
Para dibujar una hipérbola con puntos focales (F1) y (F2), con relación b/a y tamaño s, ahora puedes simplemente hacer:
\path (0,0) pic[thick, red]{hyperbola={(F1)-<b/a>-(F2)[s]}};
Respuesta2
En realidad, existe una manera (más o menos) fácil de hacer esto. Simplemente se toma la parametrización estándar de una hipérbola que está centrada alrededor del origen y luego se gira y se desplaza para que los focos se encuentren en la posición deseada.
El único problema es que la aplicación de transformaciones afines en las coordenadas de PGFplots no está integrada, pero afortunadamente la pregunta¿Cómo puedo hacer una transformación de coordenadas afines en pgfplots?da una muy buena solución a eso, que he adaptado para tomar un ángulo en lugar de vectores base.
Incluso puedes dibujar decoraciones TikZ en la hipérbola como si estuviera centrada alrededor del origen, usando las teclas shift
y rotate around
proporcionadas por TikZ. En caso de que te lo preguntes: estos no funcionan para transformar \addplot
coordenadas; en cambio, estropean las cosas cuando se usan en tramas.
El código en sí es bastante sencillo y está comentado, por lo que debería ser fácil de seguir.:-)
\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}
Respuesta3
Aquí hay una solución alternativa con TikZ pero sin PGFPlots. La idea básica es la misma que en la respuesta de Fritz: rotar y desplazar. La parametrización es tal que el usuario especifica la relación de a
a c
( \acRatio
), donde c
es la mitad de la distancia entre los focos y a
la mitad de la diferencia fija de distancias desde un punto dado de la hipérbola a los dos focos.
Una buena referencia a las matemáticas de la hipérbola se puede encontrar enMundoMatemático.
\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}