我想知道是否有更好更快的方法在 LaTeX 中绘制椭圆曲线。到目前为止,我使用以下代码:
\begin{tikzpicture}
\begin{axis}[
scale = \scale,
xmin=-1,
xmax=5,
ymin=-3,
ymax=3,
xlabel={$x$},
ylabel={$y$},
scale only axis,
axis lines=middle,
domain=-3:3,
samples=\sample,
smooth,
% to avoid that the "plot node" is clipped (partially)
clip=false,
% use same unit vectors on the axis
axis equal image=true,
]
\addplot [line width=\thick,domain=2.10381:2.5,] {sqrt((x^3-3*x-3))};
\addplot [line width=\thick,domain=2.10381:2.5,] {-sqrt((x^3-3*x-3))};
\end{axis}
\end{tikzpicture}
这里的问题是,需要花费大量时间来找到 y = 0 的解,然后得到正确的近似值。(这可以在域后的 \addplot 中看到)。
如果没有找到解决方案并得到正确的近似值,则顶部和底部曲线之间存在差距。
答案1
xmin
是一个简单的三次方程的解。抱歉,这些是\edef\temp
黑客行为,与 pgfplots 绘制图表的方式有关。正如评论中所说,您的代码片段有太多未知数。
\documentclass[fleqn]{article}
\usepackage{dsfont}
\usepackage[margin=2cm]{geometry}
\usepackage{pgfplots}
\usetikzlibrary{calc,intersections}
\usepgfplotslibrary{groupplots}
\pgfplotsset{compat=1.16}
\newcommand{\MyGroupPlot}{
\edef\temp{\noexpand\nextgroupplot[title={$A=\mya,B=\myb$},xmin=\myxmin-0.5,xmax=\myxmin+\myd+0.5]
\noexpand\addplot [thick,domain=\myxmin:\myxmin+\myd,smooth] {ysol(x,\mya,\myb)};
\noexpand\addplot [thick,domain=\myxmin:\myxmin+\myd,smooth] {-ysol(x,\mya,\myb)};
\noexpand\addplot [smooth,thick] coordinates {({\myxmin+min(\myd,1)/20},{-ysol(\myxmin+min(\myd,1)/20,\mya,\myb)})
({\myxmin+min(\myd,1)/40},{-ysol(\myxmin+min(\myd,1)/40,\mya,\myb)})
(\myxmin,0) ({\myxmin+min(\myd,1)/40},{ysol(\myxmin+min(\myd,1)/40,\mya,\myb)})
({\myxmin+min(\myd,1)/20},{ysol(\myxmin+min(\myd,1)/20,\mya,\myb)})};}
\temp
}
\begin{document}
In order to plot the points $(x,y)\in\mathds{R}^2$ that satisfy
\[ y^2=x^3+a\,x+b\;,\]
let us first find the $x$ for which $y=0$. This is a cubic equation with the
solution
\[x_0=\frac{\sqrt[3]{2} \left(\sqrt{12 a^3+81 b^2}-9
b\right)^{2/3}-2 \sqrt[3]{3} a}{6^{2/3}
\sqrt[3]{\sqrt{12 a^3+81 b^2}-9 b}}\;.\]
This determines the lower end, $x_\mathrm{min}$, of the plot interval in
Figure~\ref{fig:elliptic}.
\begin{figure}[h]
\centering
\begin{tikzpicture}[declare function={xnod(\a,\b)=0.001+%
(-2*pow(3,1/3)*\a + pow(2,1/3)*%sign(-9*\b + sqrt(12*pow(\a,3) + 81*pow(\b,2)))*%
pow(abs(-9*\b + sqrt(12*pow(\a,3) + 81*pow(\b,2))),2/3))/%
(pow(6,2/3)*sign(-9*\b + sqrt(12*pow(\a,3) + 81*pow(\b,2)))*%
pow(abs(-9*\b + sqrt(12*pow(\a,3) + 81*pow(\b,2))),1/3));
ysol(\x,\a,\b)=sqrt((\x*\x*\x+\a*\x+\b));}]
\begin{groupplot}[group style={group size=3 by 1},
scale only axis,
samples=101,
% use same unit vectors on the axis
axis equal image=true,
]
\edef\mya{3}
\edef\myb{3}
\edef\myd{2}
\pgfmathsetmacro{\myxmin}{xnod(\mya,\myb)}
\MyGroupPlot
\edef\mya{-3}
\edef\myb{3}
\edef\myd{4}
\pgfmathsetmacro{\myxmin}{xnod(\mya,\myb)}
\MyGroupPlot
\edef\mya{-3}
\edef\myb{-3}
\edef\myd{0.4}
\pgfmathsetmacro{\myxmin}{xnod(\mya,\myb)}
\MyGroupPlot
\end{groupplot}
\end{tikzpicture}
\caption{A group plot of elliptic functions.}
\label{fig:elliptic}
\end{figure}
\end{document}
答案2
我不知道 pgfplots 有多快(因为你没有给出 MWE,所以我不想测试)。但在这里你可以绘制 5 段椭圆曲线。当切线不是太垂直时,随意的 sqrt 方法就足够了。
当切线接近垂直时,参数化为是并发现X使用牛顿法。由于您确切知道X-截距,你对初始的X0。由于这个猜测已经非常接近实际X,则需要两次迭代,最多三次。
\documentclass[tikz,border=9]{standalone}
\begin{document}
% we are to plot y^2 = (x-1)x(x+1)
% the idea is that we know x-intercepts
% don't use standard form ax + b
\let\PMSM=\pgfmathsetmacro
\pgfmathdeclarefunction{f}1{\pgfmathparse{(#1-1)*#1*(#1+1)}}
\pgfmathdeclarefunction{g}1{\pgfmathparse{3*#1*#1-1}} % g = f' = df/d#1
\tikz[cap=round]{
\draw[->](-1.1,0)--(2,0);
\draw[->](0,0)--(0,3);
{% -1 ≤ x ≤ -.9 % plot by newton method
\pgfpathmoveto{\pgfpointxy{-1}{0}}
\def\nsample{40}
\foreach\i in{0,...,\nsample}{
\PMSM\y{sqrt(f(-.9))*\i/\nsample} % y
\PMSM\yy{f(-.9)*\i*\i/\nsample/\nsample} % y^2
% initial x = -1
\PMSM\x{-1}
% first iteration
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
% second iteration
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
% third iteration not really necessary
%\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\pgfpathlineto{\pgfpointxy{\x}{\y}}
}
\pgfsetcolor{red}
\pgfusepath{stroke}
}
{% -.9 ≤ x ≤ -.1 % plot by square root
\draw[green]plot[domain=-.9:-.1](\x,{sqrt(f(\x))});
}
{% -.1 ≤ x ≤ 0 % plot by newton method
\pgfpathmoveto{\pgfpointxy{0}{0}}
\def\nsample{40}
\foreach\i in{0,...,\nsample}{
\PMSM\y{sqrt(f(-.1))*\i/\nsample}
\PMSM\yy{f(-.1)*\i*\i/\nsample/\nsample}
\PMSM\x{0} % initial x = 0
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
%\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\pgfpathlineto{\pgfpointxy{\x}{\y}}
}
\pgfsetcolor{blue}
\pgfusepath{stroke}
}
{% 1 ≤ x ≤ 1.1 % plot by newton method
\pgfpathmoveto{\pgfpointxy{1}{0}}
\def\nsample{40}
\foreach\i in{0,...,\nsample}{
\PMSM\y{sqrt(f(1.1))*\i/\nsample}
\PMSM\yy{f(1.1)*\i*\i/\nsample/\nsample}
\PMSM\x{1} % initial x = 1
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
%\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\pgfpathlineto{\pgfpointxy{\x}{\y}}
}
\pgfsetcolor{yellow!50!black}
\pgfusepath{stroke}
}
{% 1.1 ≤ x ≤ ∞ % plot by square root
\draw[cyan]plot[domain=1.1:2](\x,{sqrt(f(\x))});
}
}
\end{document}
编辑
你也可以改进你的初始猜测。X-拦截,你添加一个是2项。那么结果就非常精确、流畅。而且我只迭代一次。
\documentclass[tikz,border=9]{standalone}
\begin{document}
% we are to plot y^2 = (x-1)x(x+1)
% the idea is that we know x-intercepts
% don't use standard form x^3 + ax + b
\let\PMSM=\pgfmathsetmacro
\pgfmathdeclarefunction{f}1{\pgfmathparse{(#1-1)*#1*(#1+1)}}
\pgfmathdeclarefunction{g}1{\pgfmathparse{3*#1*#1-1}} % g = f' = df/d#1
\tikz[cap=round]{
\draw[->](-1.1,0)--(2,0);
\draw[->](0,0)--(0,3);
{% -1 ≤ x ≤ -.9 % plot by newton method
\pgfpathmoveto{\pgfpointxy{-1}{0}}
\def\nsample{40}
\foreach\i in{0,...,\nsample}{
\PMSM\y{sqrt(f(-.9))*\i/\nsample} % y
\PMSM\yy{f(-.9)*\i*\i/\nsample/\nsample} % y^2
% initial guess x = -1 + y^2/2 (first order apporx)
\PMSM\x{-1+\yy/2}
% first iteration
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
% second iteration % but one is good enough
%\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\pgfpathlineto{\pgfpointxy{\x}{\y}}
}
\pgfsetcolor{red}
\pgfusepath{stroke}
}
{% -.9 ≤ x ≤ -.1 % plot by square root
\draw[green]plot[domain=-.9:-.1](\x,{sqrt(f(\x))});
}
{% -.1 ≤ x ≤ 0 % plot by newton method
\pgfpathmoveto{\pgfpointxy{0}{0}}
\def\nsample{40}
\foreach\i in{0,...,\nsample}{
\PMSM\y{sqrt(f(-.1))*\i/\nsample} % y
\PMSM\yy{f(-.1)*\i*\i/\nsample/\nsample} % y^2
\PMSM\x{-\yy)} % initial guess x = 0 - y^2
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
%\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\pgfpathlineto{\pgfpointxy{\x}{\y}}
}
\pgfsetcolor{blue}
\pgfusepath{stroke}
}
{% 1 ≤ x ≤ 1.1 % plot by newton method
\pgfpathmoveto{\pgfpointxy{1}{0}}
\def\nsample{40}
\foreach\i in{0,...,\nsample}{
\PMSM\y{sqrt(f(1.1))*\i/\nsample} % y
\PMSM\yy{f(1.1)*\i*\i/\nsample/\nsample} % y^2
\PMSM\x{1+\yy/2} % initial guess x = 1 + y^2/2
\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
%\PMSM\x{\x-(f(\x)-\yy)/g(\x)}
\pgfpathlineto{\pgfpointxy{\x}{\y}}
}
\pgfsetcolor{yellow!50!black}
\pgfusepath{stroke}
}
{% 1.1 ≤ x ≤ ∞ % plot by square root
\draw[cyan]plot[domain=1.1:2](\x,{sqrt(f(\x))});
}
}
数学不是实用的吗?