编辑

编辑

我想知道是否有更好更快的方法在 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))});
    }
}

数学不是实用的吗?

相关内容