TikZ 无法正确显示相交平面

TikZ 无法正确显示相交平面

我在 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,并且我们在外部生成数据。单个表面需要三个具有xyz坐标的矩阵。对于两个表面,我们可以将 、 和 堆叠在一起[x; x][y; y]为了[z1; z2]使两个表面断开连接,我们可以在堆叠的矩阵之间插入一个适当大小的向量,例如n,其中 s 的大小为 ,例如、和,以及选项。最后,我们将三个矩阵保存为三个堆叠的列,代表三元组,正如预期的那样。这还需要用 指定矩阵的列数。NaN[x; n; x][y; n; y][z1; n; z2]unbounded coords=jump(x,y,z)pgfplotsmesh/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 symbolicpoint 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,这非常令人难过。无论如何,结果如下:

三个彩色平面的交点

相关内容