使用 pgfplots 绘制原子之间的键

使用 pgfplots 绘制原子之间的键

我正在尝试使用 pgfplots 绘制一个分子。我已使用以下代码成功绘制了原子:

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}
\begin{axis}[
view = {0}{0},
axis lines=none,
axis equal
]
\addplot3[scatter,red,only marks, point meta=explicit symbolic,
          z buffer=sort, scatter/classes={H={mark size=3pt,blue},
          O={mark size=5pt,red},C={mark size=5pt,yellow}}]
  coordinates {
(0.483,0.593,0.525) [H]
(0.425,0.501,0.590) [H]
(0.510,0.580,0.640) [H]
(0.573,0.518,0.626) [H]
(0.517,0.463,0.322) [H]
(0.363,0.503,0.418) [H]
(0.538,0.422,0.558) [H]
(0.528,0.503,0.731) [H]
(0.559,0.505,0.428) [C]
(0.491,0.497,0.406) [C]
(0.449,0.518,0.455) [C]
(0.490,0.539,0.514) [C]
(0.478,0.497,0.578) [C]
(0.519,0.525,0.636) [C]
(0.610,0.491,0.397) [O]
(0.475,0.473,0.344) [O]
(0.382,0.521,0.459) [O]
(0.559,0.531,0.492) [O]
(0.490,0.428,0.566) [O]
(0.498,0.492,0.695) [O]
};
\end{axis}
\end{tikzpicture}

\end{document}

看起来像这样:

在此处输入图片描述

现在我想添加原子之间的键,就像棍子一样。我需要一种方法来连接两个分散的数据点,如果它们之间的距离小于某个距离。我对 pgfplots 感兴趣,只要原子间距离低于某个截止值,它就会自动连接原子。当然,我可以编写一个 python 脚本来确定哪些原子是键合的,并\draw为我生成所有实例,但我希望能够跳过将大量额外代码粘贴到文档中的步骤。

理想情况下,我还希望能够根据所连接的原子类型来改变键的颜色。

有可能做到这一点吗,至少是债券提取?

答案1

我绝对建议使用外部脚本。无论如何,即使作为一项脑力锻炼,以下是一些你可能会觉得有用的东西。我预计当你给它大量的原子时它会非常慢。

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}
\usepackage{tikz}

\usepackage{pdftexcmds} % for testing atom types
\usepackage{boolexpr}
\makeatletter\long\def\isequal#1#2{\pdf@strcmp{#1}{#2}}\makeatother

\begin{document}

\begin{tikzpicture}
\begin{axis}[
view = {0}{0},
axis lines=none,
axis equal
]
\def\COORDINATES{0.483/0.593/0.525/H,
                 0.425/0.501/0.590/H,
                 0.510/0.580/0.640/H,
                 0.573/0.518/0.626/H,
                 0.517/0.463/0.322/H,
                 0.363/0.503/0.418/H,
                 0.538/0.422/0.558/H,
                 0.528/0.503/0.731/H,
                 0.559/0.505/0.428/C,
                 0.491/0.497/0.406/C,
                 0.449/0.518/0.455/C,
                 0.490/0.539/0.514/C,
                 0.478/0.497/0.578/C,
                 0.519/0.525/0.636/C,
                 0.610/0.491/0.397/O,
                 0.475/0.473/0.344/O,
                 0.382/0.521/0.459/O,
                 0.559/0.531/0.492/O,
                 0.490/0.428/0.566/O,
                 0.498/0.492/0.695/O}
\newcounter{u}
\newcounter{v}
\foreach \ux/\uy/\uz/\ut in \COORDINATES {
  \stepcounter{u}
  \begingroup\edef\temp{\endgroup\noexpand%
      \addplot3[scatter,red,only marks, point meta=explicit symbolic,
            z buffer=sort, scatter/classes={H={mark size=3pt,blue},
            O={mark size=5pt,red},C={mark size=5pt,yellow}}]
      coordinates { (\ux,\uy,\uz) [\ut] };
  }\temp
  \setcounter{v}{0}
  \foreach \vx/\vy/\vz/\vt in \COORDINATES {
    \stepcounter{v}
    \ifnum\value{u}<\value{v}
    \pgfmathparse{less(sqrt((\ux-\vx)^2+(\uy-\vy)^2+(\uz-\vz)^2), 0.1)}
    \ifnum\pgfmathresult=1
      \edef\bond{\switch
        \case{\isequal{\ut}{O} \OR \isequal{\vt}{O}}  thick,color=red
        \case{\isequal{\ut}{\vt}}                     color=green
        \otherwise                                    color=black
        \endswitch}
      \begingroup\edef\temp{\endgroup\noexpand%
        \draw[\bond] (axis cs:\ux,\uy,\uz) -- (axis cs:\vx,\vy,\vz);
      }\temp
    \fi\fi
  }
}
\end{axis}
\end{tikzpicture}
\end{document}

结果是:

结果

相关内容