我在 MATLAB 中绘制了变形模型和未变形模型的图。我使用以下代码将图形转换为 TikZ:matlab2tikz并将其添加到我的 .tex 文件中。然后我注意到两个相交的配置显示不正确。为了说明我的意思,我精简了 TikZ 代码,使两个矩形在 3D 空间中交叉:
\begin{tikzpicture}
\begin{axis}[%
width=5cm,height=5cm,
view={-37.5}{45},
scale only axis,
xmin=-3, xmax=23,
ymin=0, ymax=20,
zmin=-5, zmax=5,
hide axis]
\addplot3 [fill=white!80!red,opacity=0.5,draw=black] table[row sep=crcr]{
20 0 0\\
20 20 0\\
0 20 0\\
0 0 0\\
};
\addplot3 [fill=white!80!blue,opacity=0.8,draw=black] table[row sep=crcr]{
15 5 -4\\
15 15 0\\
5 15 4\\
5 5 0\\
};
\end{axis}
\end{tikzpicture}
结果如下:
可以看出,一个平面完全位于另一个平面之上,而实际上它们是相交的(即,大约一半的蓝色平面位于红色平面的“下方”)。凭借我对 TikZ 的最低限度的了解,我希望这里有人可以帮助我解决这个问题,这样平面确实可以相交。
答案1
不幸的是,这在当前版本的 pgfplots 中似乎不可能实现。从手动的(第 4.5.1 节):
pgfplots
支持是在一定程度上可以提高缓冲技术的性能。它对于单散点图 (z buffer=sort
)、网格或曲面图 (z buffer=auto
) 或参数网格和曲面图 (z buffer=sort
) 非常有效。但是,它不能组合不同的\addplot
命令,这些命令将按照出现的顺序绘制。有时您可能会遇到限制。 也许将来的版本会有所改进。
答案2
关于这个问题还有其他几个问题,例如:
正如指出的那样经过马修·林冈,这是由于 的限制pgfplots
。
与迄今为止的所有解决方法不同,我发现一种方法(实际上是一种黑客技术),它允许在单个命令中绘制多个(实际上是任意数量的)可能相交的表面addplot3
,并具有自动 z 缓冲功能,而无需手动执行任何操作。
我们使用addplot3 table
而不是addplot3 coordinates
,并且我们在外部生成数据。单个表面需要三个具有x
、y
、z
坐标的矩阵。对于两个表面,我们可以将 、 和 堆叠在一起[x; x]
。[y; y]
为了[z1; z2]
使两个表面断开连接,我们可以在堆叠的矩阵之间插入一个适当大小的向量,例如n
,其中 s 的大小为 ,例如、和,以及选项。最后,我们将三个矩阵保存为三个堆叠的列,代表三元组,正如预期的那样。这还需要用 指定矩阵的列数。NaN
[x; n; x]
[y; n; y]
[z1; n; z2]
unbounded coords=jump
(x,y,z)
pgfplots
mesh/cols
为了实现这个想法,我定义了一些宏,允许python
通过 调用任意代码addplot shell
,将数据以表格形式保存到文本文件中,然后加载显示。这需要-shell-escape
中的标志pdflatex
。
不幸的是,由于这是一个单一的图,我看不出如何为每个单独的表面指定不同的属性(例如颜色或不透明度)。好吧,也许可以通过在数据组合选项中添加第四列来实现,point meta
就像在散点图中一样,但我还没有尝试过。
此外,通过尝试更复杂的示例,人们意识到,尽管面片可见性计算正确,但我们并没有真正得到面片相交。因此,为了在表面相交处获得平滑曲线的感觉,需要提高分辨率。我不打算使用这个;我只是因为觉得它很有趣而分享。
下面,我给出了两个相交平面的示例,但实际上可以用相同的“方法”计算任何东西。它位于 中beamer
,因为这是我已经尝试过的方法。
\documentclass{beamer}
\usefonttheme[onlymath]{serif}
\setbeamersize{text margin left=10pt}
\setbeamersize{text margin right=10pt}
\usepackage{pgfplots}
\pgfplotsset{
every axis/.append style={font=\scriptsize},
plain/.style={every axis plot/.append style={mark=none},enlargelimits=false,grid=none},
z-sort/.style={z buffer=sort,unbounded coords=jump},
}
\newcommand{\python}[1]{python -c "%
import math, sys; import numpy as np;%
#1 np.savetxt(sys.stdout, data)%
"}
\newcommand<>{\pyplot}[3][]%
{\only#4{\addplot[#1] shell[prefix=fig/data/,id=#2,] {\python{#3}};}}
\newcommand<>{\pyplott}[3][]%
{\only#4{\addplot3[z-sort,#1] shell[prefix=fig/data/,id=#2,] {\python{#3}};}}
\newcommand<>{\pyload}[3][]%
{\only#4{\addplot[#1] table[x index=0,y index=#2] {fig/data/#3.out};}}
\newcommand<>{\pyloadt}[2][]%
{\only#3{\addplot3[z-sort,#1] table {fig/data/#2.out};}}
\newcommand{\pysave}[2]{
\begin{tikzpicture}[overlay,opacity=0]
\begin{axis} \pyplot{#1}{#2} \end{axis}
\end{tikzpicture}
}
\begin{document}
\begin{frame}
\pysave{surf}{
n = 11; x = np.linspace(0,1,n); y = x;
X, Y = np.meshgrid(x,y);
Z1 = X + Y;
Z2 = 1 - X + Y;
N = np.ones([1, n]) * np.NaN;
X = np.r_[X, N, X ].reshape([-1, 1]);
Y = np.r_[Y, N, Y ].reshape([-1, 1]);
Z = np.r_[Z1, N, Z2].reshape([-1, 1]);
data = np.c_[X, Y, Z];
}
\begin{center}
\begin{tikzpicture}
\begin{axis}[plain,width=\textwidth,height=.8\textwidth]
\pyloadt[surf,mesh/cols=11]{surf};
\end{axis}
\end{tikzpicture}
\end{center}
\end{frame}
\end{document}
结果如下:
编辑
最终,可以为每个表面赋予不同的颜色。我无法制作point meta=explicit symbolic
或point meta=explicit
工作,但可以做到的是point meta=\thisrowno{3}
。以下是代码:
\documentclass{beamer}
\usefonttheme[onlymath]{serif}
\setbeamersize{text margin left=10pt}
\setbeamersize{text margin right=10pt}
\usepackage{pgfplots}
\pgfplotsset{
every axis/.append style={font=\scriptsize},
plain/.style={every axis plot/.append style={mark=none},enlargelimits=false,grid=none},
z-sort/.style={z buffer=sort,unbounded coords=jump},
}
\newcommand{\python}[1]{python -c "%
import math, sys; import numpy as np;%
#1 np.savetxt(sys.stdout, data)%
"}
\newcommand<>{\pyplot}[3][]%
{\only#4{\addplot[#1] shell[prefix=fig/data/,id=#2,] {\python{#3}};}}
\newcommand<>{\pyplott}[3][]%
{\only#4{\addplot3[z-sort,#1] shell[prefix=fig/data/,id=#2,] {\python{#3}};}}
\newcommand<>{\pyload}[3][]%
{\only#4{\addplot[#1] table[x index=0,y index=#2] {fig/data/#3.out};}}
\newcommand<>{\pyloadt}[2][]%
{\only#3{\addplot3[z-sort,#1] table {fig/data/#2.out};}}
\newcommand{\pysave}[2]{
\begin{tikzpicture}[overlay,opacity=0]
\begin{axis} \pyplot{#1}{#2} \end{axis}
\end{tikzpicture}
}
\begin{document}
\begin{frame}
\pysave{surf}{
n = 31; x = np.linspace(0,1,n); y = x;
X, Y = np.meshgrid(x,y);
Z1 = X + Y;
Z2 = 1 - X + Y;
Z3 = 1- X + 1 - Y;
M1 = np.ones([n, n]);
M2 = 2 * M1;
M3 = 3 * M1;
N = np.ones([1, n]) * np.NaN;
X = np.r_[X, N, X, N, X ].reshape([-1, 1]);
Y = np.r_[Y, N, Y, N, Y ].reshape([-1, 1]);
Z = np.r_[Z1, N, Z2, N, Z3].reshape([-1, 1]);
M = np.r_[M1, N, M2, N, M3].reshape([-1, 1]);
data = np.c_[X, Y, Z, M];
}
\begin{center}
\begin{tikzpicture}
\begin{axis}[
plain,width=\textwidth,height=.8\textwidth,
colormap={summap}{color=(green);color=(red);color=(yellow);},
]
\pyloadt[surf,opacity=.7,mesh/cols=31,point meta=\thisrowno{3}]{surf};
\end{axis}
\end{tikzpicture}
\end{center}
\end{frame}
\end{document}
min
在这个例子中,我展示了三个平面,颜色分别为绿色、红色和黄色。一点透明度有助于看清发生了什么。在这种情况下,像max
以前的解决方法一样,用 和 手动计算交点会非常复杂。
但是,现在绿色和黄色平面之间缺失的斑块交叉点很明显,所以我将分辨率增加到 31x31。进一步增加到 41x41 得到TeX capacity exceeded
,这非常令人难过。无论如何,结果如下: