答案1
因为这是这个网站上反复出现的问题,而且有些说法我并不完全同意,所以作为概念证明:是的,一个能使用 pgfplots 绘制此类图。您只需要有一点耐心(或拥有一台超快的计算机)。如果您有多个表面,则有两个有用的(甚至是必要的?)成分:
- 手动进行一些 3D 排序。(这对于 patchplots 来说不是必需的,但对于这类图来说,我认为是必需的。)
- 使用图层。
图表的实际排序并不重要,重要的是图层。动画也许可以最好地说明“手动 3D 排序”的含义。
请注意,动画上的奇怪线条是转换为动画 gif 的产物。实际的 pdf 没有这个问题。
\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{3d}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=1.16}
\begin{document}
\foreach \X in {3} %{1,2,3}% % <-for animation
{\pgfmathsetmacro{\v}{0.3}
\pgfmathsetmacro{\u}{1.5}
\begin{tikzpicture}[declare function={radius(\x)=sqrt(1.5^2-(\x-1.5)*(\x-1.5));
funky(\x)=(1+\v*cos(4*deg(\x)));},x={(3.2*\u cm,0.0cm)},
y={(0cm,\u cm)},z={(-\u*0.3535cm,-\u*0.3535cm)},]
\begin{axis}[set layers,colormap/cool,hide axis,
x={(3.2*\u cm,0.0cm)},
y={(0cm,\u cm)},
z={(-\u*0.3535cm,-\u*0.3535cm)},
ymin=-2.5,ymax=2.5,xmin=-0.1,xmax=3
]
\addplot3[draw=none] coordinates {(0.3,-2,-2) (0.3,2,-2) (0.3,2,2)
(2.7,2,2) (2.7,2,-2) (2.7,-2,-2)};
\path[name path=plane] (1.5,-2.25,-2.25) coordinate (z1)
-- (1.5,-2.25,2.25) coordinate (z2) -- (1.5,2.25,2.25) coordinate (z3)
-- (1.5,2.25,-2.25) coordinate (z4) -- cycle;
\draw[-latex] (0,-2.25,0) -- (3,-2.25,0) node[below left]{$x$};
\draw[-latex] (0,-2.5,0) -- (0,2.5,0) node[below left]{$y$};
\addplot3[smooth,opacity=0.3,surf,shader=interp,on layer=axis background,
samples=30,
domain=0.3:2.7,y domain=pi:2*pi,
z buffer=sort]
(x,{cos(deg(y))*radius(x)*funky(y)},
{sin(deg(y))*radius(x)*funky(y)});
%
\ifnum\X>1
\path[on layer=main,thick,purple,fill=purple,fill opacity=0.3]
plot[smooth,samples=59,domain=0:2*pi]
(1.5,{cos(deg(\x))*radius(1.5)*funky(\x)},
{sin(deg(\x))*radius(1.5)*funky(\x)});
\draw[on layer=axis background,thick,purple,purple,thick,dashed]
plot[smooth,samples=59,domain=pi:2*pi]
(1.5,{cos(deg(\x))*radius(1.5)*funky(\x)},
{sin(deg(\x))*radius(1.5)*funky(\x)});
\draw[on layer=axis foreground,thick,purple,purple,thick]
plot[smooth,samples=59,domain=0:pi]
(1.5,{cos(deg(\x))*radius(1.5)*funky(\x)},
{sin(deg(\x))*radius(1.5)*funky(\x)});
\draw[blue,thick,dashed,on layer=main,fill=blue!70!green,fill opacity=0.3]
plot[smooth,samples=59,domain=0:2*pi]
(0.3,{cos(deg(\x))*radius(0.3)*funky(\x)},
{sin(deg(\x))*radius(0.3)*funky(\x)});
\draw[blue,thick,on layer=main,fill=blue!70!green,fill opacity=0.3]
plot[smooth,samples=59,domain=0:2*pi]
(2.7,{cos(deg(\x))*radius(0.3)*funky(\x)},
{sin(deg(\x))*radius(0.3)*funky(\x)});
\fi
%
\ifnum\X>2
\addplot3[smooth,opacity=0.3,surf,shader=interp,on layer=axis foreground,
samples=30,
domain=0.3:2.7,y domain=0:pi,
z buffer=sort]
(x,{cos(deg(y))*radius(x)*funky(y)},
{sin(deg(y))*radius(x)*(1+\v*cos(4*deg(y)))});
\path[thick,name path=upper] plot[smooth,variable=\x,samples=30,domain=0.3:2.7]
(\x,{cos(deg(0))*radius(\x)*funky(0)},
{sin(deg(0))*radius(\x)*funky(0)});
\path[thick,name path=lower] plot[smooth,variable=\x,samples=30,domain=0.3:2.7]
(\x,{cos(deg(pi))*radius(\x)*funky(pi)},
{sin(deg(pi))*radius(\x)*funky(pi)});
\path [name intersections={of=plane and upper,by={x1,x2}}];
\path [name intersections={of=plane and lower,by={y1,y2}}];
\draw (y1) -- (z2) -- (z3) -- (z4) -- (x2);
\draw[dashed] (y1) -- (z1) -- (x2);
\fill (1.5,-2.25,0) circle(1pt) node[below] {$x$};
\fill (0.3,-2.25,0) circle(1pt) node[below] {$a$};
\fill (2.7,-2.25,0) circle(1pt) node[below] {$b$};
\begin{scope}[on layer=main]
\begin{scope}[canvas is zy plane at x=1.5,transform shape,xscale=-1]
\node at (0,0) {$A(x)$};
\node at (1.8,1.8) {$P_x$};
\end{scope}
\begin{scope}[canvas is zy plane at x=0.3,transform shape,xscale=-1]
\node at (0,0) {$A(a)$};
\end{scope}
\begin{scope}[canvas is zy plane at x=2.7,transform shape,xscale=-1]
\node at (0,0) {$A(b)$};
\end{scope}
\end{scope}
\draw[on layer=axis foreground,thick,blue]
plot[smooth,samples=59,domain=0.3:2.7]
(\x,{cos(deg(pi/4))*radius(\x)*funky(pi/4)},
{sin(deg(pi/4))*radius(\x)*funky(pi/4)});
\draw[on layer=axis background,thick,blue,dashed]
plot[smooth,samples=59,domain=0.3:2.7]
(\x,{cos(deg(pi/4+pi))*radius(\x)*funky(pi/4+pi)},
{sin(deg(pi/4+pi))*radius(\x)*funky(pi/4+pi)});
\fi
\end{axis}
\end{tikzpicture}
}
\end{document}
请注意,我的 3D 排序远非完美。我将域分为0:pi
和pi:2*pi
。这并不完全正确,但在这种情况下是一个合理的近似值。还请注意,3d
库在这里没有任何问题。