我想绘制一个单位壳层来显示原子的排列,如下图所示。(Zumdahl,《化学原理》,第 5 版,霍顿·米夫林,第 773 页。)
我想出了以下代码来绘制原子面(上面的立方体)。它采用了只需定义一次立方体面的想法:然后可以倾斜它来绘制其他面。但是,我不知道如何(从数学上)绘制阴影(剪裁球体)。有什么建议吗?
如果可能的话,使用只定义一个隔间面的想法。这非常方便,因为我必须绘制上述所有示例,甚至更多(我在示例中添加了两个面)。但是,如果这不可能,其他解决方案是值得赞赏的。不能旋转解决方案。
\documentclass{minimal}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\D}{4}
\pgfmathsetmacro{\halfD}{\D/2}
\newcommand{\mycubicleface}{
\pgfmathsetmacro{\R}{\D/2}
\draw [fill=blue!30] (0,\R) arc [start angle=90, end angle=0, radius=\R] -- +(-\R,0);
\draw [fill=blue!30] (0,\R) arc [start angle=-90, end angle=0, radius=\R] -- +(-\R,0);
\draw [fill=blue!30] (\D,\R) arc [start angle=-90, end angle=-180, radius=\R] -- +(\R,0);
\draw [fill=blue!30] (\D,\R) arc [start angle=90, end angle=180, radius=\R] -- +(\R,0);
\draw (0,0) rectangle +(\D,\D);
}
%\newcommand{\mycubicleface}{
% \pgfmathsetmacro{\R}{\D/sqrt(8)}
% \draw [fill=blue!30] (\D/2,\D/2) circle [radius=\R];
% \draw [fill=blue!30] (0,\R) arc [start angle=90, end angle=0, radius=\R] -- +(-\R,0);
% \draw [fill=blue!30] (0,\D - \R) arc [start angle=-90, end angle=0, radius=\R] -- +(-\R,0);
% \draw [fill=blue!30] (\D,\D - \R) arc [start angle=-90, end angle=-180, radius=\R] -- +(\R,0);
% \draw [fill=blue!30] (\D,\R) arc [start angle=90, end angle=180, radius=\R] -- +(\R,0);
% \draw (0,0) rectangle +(\D,\D);
%}
\begin{scope}[yslant=-.5]
\mycubicleface
\end{scope}
\begin{scope}[xshift=\D cm, yshift=-\halfD cm, yslant=.5]
\mycubicleface
\end{scope}
\begin{scope}[xshift=\D cm, yshift=\halfD cm, yslant=.5, xslant=-1]
\mycubicleface
\end{scope}
\end{tikzpicture}
\end{document}
答案1
这是您结果的对应部分。
这个想法来自于这个例子在球体上绘制一些经线/纬度圆。我没有绘制这些圆弧,而是将它们用作剪切路径。部分作品需要将弧连接在一起。
\documentclass[tikz]{standalone}
\usepackage{tikz,spath}
\usetikzlibrary{calc,fadings}
\newcommand\pgfmathsinandcos[3]{
\pgfmathsetmacro#1{sin(#3)}\pgfmathsetmacro#2{cos(#3)}}
\newcommand\LongitudePlane[3][current plane]{
\pgfmathsinandcos\sinEl\cosEl{#2}\pgfmathsinandcos\sint\cost{#3}
\tikzset{#1/.style={cm={\cost,\sint*\sinEl,0,\cosEl,(0,0)}}}}
\newcommand\LatitudePlane[3][current plane]{%
\pgfmathsinandcos\sinEl\cosEl{#2}\pgfmathsinandcos\sint\cost{#3}
\pgfmathsetmacro\yshift{\cosEl*\sint}
\tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}}}
\newcommand\ClipLongitudeCircle[2]{
\LongitudePlane\angEl{#1}
\pgfmathsetmacro\angVis{atan(sin(#1)*cos(\angEl)/sin(\angEl))}
\path[save path=\tmppath,current plane](\angVis:\R)arc(\angVis:\angVis+180:\R);
\pgfoonew\patha=new spath(\tmppath)
\pgfmathsetmacro\angVis{-atan(sin(\angEl)*cos(#1)/sin(#1))}
\path[save path=\tmppath](-90+\angVis:\R)arc(-90+\angVis:#2180-90+\angVis:\R);
\pgfoonew\pathb=new spath(\tmppath)
\patha.concatenate with lineto(,\pathb)\patha.close()\patha.use path with tikz(clip)}
\newcommand\ClipLatitudeCircle[2]{
\LatitudePlane{\angEl}{#1}
\path[save path=\tmppath,current plane](-180:\R)arc(-180:0:\R);
\pgfoonew\patha=new spath(\tmppath)
\path[save path=\tmppath](0:\R)arc(0:#2180:\R);
\pgfoonew\pathb=new spath(\tmppath)
\patha.concatenate with lineto(,\pathb)\patha.close()\patha.use path with tikz(clip)}
\newcommand\EighthSphere[3]{
\ClipLongitudeCircle{45-\angPh}{#1}
\ClipLongitudeCircle{135-\angPh}{#2}
\ClipLatitudeCircle{0}{#3}
\fill[ball color=white](0,0)circle(\R);}
\begin{document}
\def\R{6} % sphere radius
\def\angEl{20} % elevation angle in interval [1,89]
\def\angPh{10} % phase angle in interval [-44,44]
\pgfmathsetmacro\uofx{cos(-135-\angPh)}
\pgfmathsetmacro\vofx{sin(-135-\angPh)*sin(\angEl)}
\pgfmathsetmacro\uofy{cos(-45-\angPh)}
\pgfmathsetmacro\vofy{sin(-45-\angPh)*sin(\angEl)}
\pgfmathsetmacro\uofz{0}
\pgfmathsetmacro\vofz{cos(\angEl)}
\begin{tikzpicture}
\begin{scope}[x={(\uofx cm,\vofx cm)},y={(\uofy cm,\vofy cm)},z={(\uofz cm,\vofz cm)}]
\path(-6,-6,-6)coordinate(A){}(6,6,6)coordinate(B){};
\path(6,-6,-6)coordinate(P){}(6,6,-6)coordinate(Q){}(-6,6,-6)coordinate(R){}
(-6,6,6)coordinate(S){}(-6,-6,6)coordinate(T){}(6,-6,6)coordinate(U){};
\end{scope}
\path(-12,-12)(12,12);
\draw(P)--(Q)--(R)--(S)--(T)--(U)--cycle;
\clip(P)--(Q)--(R)--(S)--(T)--(U)--cycle;
\begin{scope}[transform canvas={shift=(A)}]
\EighthSphere{+}{-}{+}
\end{scope}
\begin{scope}[transform canvas={shift=(P)}]
\EighthSphere{+}{+}{+}
\end{scope}
\begin{scope}[transform canvas={shift=(R)}]
\EighthSphere{-}{-}{+}
\end{scope}
\begin{scope}[transform canvas={shift=(T)}]
\EighthSphere{+}{-}{-}
\end{scope}
\begin{scope}[transform canvas={shift=(Q)}]
\EighthSphere{-}{+}{+}
\end{scope}
\begin{scope}[transform canvas={shift=(S)}]
\EighthSphere{-}{-}{-}
\end{scope}
\begin{scope}[transform canvas={shift=(U)}]
\EighthSphere{+}{+}{-}
\end{scope}
\end{tikzpicture}
\end{document}
答案2
终于到了!您可以通过注释和取消注释以下代码来生成所有三个立方体。
答案基本上是符号 1 的答案,仅修改。请注意,您需要spath
手动安装包正如这里所告知的。
代码中的注释部分用于调试(绘制要剪切的路径)。
最终结果令人满意。但是,请注意最中间图像中两个半球的堆叠和阴影不正确。
\documentclass[tikz]{standalone}
\usepackage{spath}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{fadings}
\begin{document}
% Source: LaTeX-Community.org
% <http://www.latex-community.org/viewtopic.php?f=4&t=2111>
\begin{tikzpicture}
\newcommand\pgfmathsinandcos[3]{%
\pgfmathsetmacro#1{sin(#3)}%
\pgfmathsetmacro#2{cos(#3)}%
}
\newcommand\LongitudePlane[3][current plane]{%
\pgfmathsinandcos\sinEl\cosEl{#2} % elevation
\pgfmathsinandcos\sint\cost{#3} % azimuth
\tikzset{#1/.style={cm={\cost,\sint*\sinEl,0,\cosEl,(0,0)}}}
}
\newcommand\LatitudePlane[3][current plane]{%
\pgfmathsinandcos\sinEl\cosEl{#2} % elevation
\pgfmathsinandcos\sint\cost{#3} % latitude
\pgfmathsetmacro\yshift{\cosEl*\sint}
\tikzset{#1/.style={cm={\cost,0,0,\cost*\sinEl,(0,\yshift)}}}
}
%\newcommand\DrawLongitudeCircle[2][4]{
% \LongitudePlane{\angEl}{#2}
%% \tikzset{current plane/.prefix style={scale=#1}}
% % angle of "visibility"
% \pgfmathsetmacro\angVis{atan(sin(#2)*cos(\angEl)/sin(\angEl))}
% \draw[current plane, blue] (\angVis:\R) arc (\angVis:\angVis+180:\R);
% \draw[current plane, blue] (\angVis-180:\R) arc (\angVis-180:\angVis:\R);
%}
%\newcommand\DrawLatitudeCircle[2][5]{
% \LatitudePlane{\angEl}{#2}
%% \tikzset{current plane/.prefix style={scale=#1}}
%% \pgfmathsetmacro\sinVis{sin(#2)/cos(#2)*sin(\angEl)/cos(\angEl)}
%% % angle of "visibility"
%% \pgfmathsetmacro\angVis{asin(min(1,max(\sinVis,-1)))}
% \draw[current plane, red] (\angVis:\R) arc (\angVis:-\angVis-180:\R);
% \draw[current plane, red] (180-\angVis:\R) arc (180-\angVis:\angVis:\R);
%}
\newcommand\ClipLongitudeCircle[2]{
\LongitudePlane{\angEl}{#1}
\pgfmathsetmacro\angVis{atan(sin(#1)*cos(\angEl)/sin(\angEl))}
\path[save path=\tmppath, current plane] (\angVis:\R) arc (\angVis:\angVis+180:\R); % current plane transformation
\pgfoonew\patha=new spath(\tmppath)
\pgfmathsetmacro\angVis{-atan(sin(\angEl)*cos(#1)/sin(#1))}
\path[save path=\tmppath] (-90+\angVis:\R) arc (-90+\angVis:#2 180-90+\angVis:\R); % no coordinate transform (no current plane)
\pgfoonew\pathb=new spath(\tmppath)
\patha.concatenate with lineto(,\pathb)
\patha.close()
\patha.use path with tikz(clip)
% \patha.use path with tikz(fill=magenta, opacity=.2)
% \patha.use path with tikz(draw=magenta, very thick)
}
\newcommand\ClipLatitudeCircle[2]{
\LatitudePlane{\angEl}{#1}
\path[save path=\tmppath,current plane] (-180:\R) arc (-180:0:\R);
\pgfoonew\patha=new spath(\tmppath)
\path[save path=\tmppath] (0:\R) arc (0:#2 180:\R);
\pgfoonew\pathb=new spath(\tmppath)
\patha.concatenate with lineto(,\pathb)
\patha.close()
\patha.use path with tikz(clip)
% \patha.use path with tikz(fill=cyan, opacity=.2)
% \patha.use path with tikz(draw=cyan, very thick)
}
\newcommand\ClippedEightSphere[4]{
\begin{scope}[transform canvas={shift=(#4)}]
\ClipLongitudeCircle{45-\angPh}{#1}
\ClipLongitudeCircle{135-\angPh}{#2}
\ClipLatitudeCircle{0}{#3}
\fill[ball color=white] (0,0) circle (\R);
\end{scope}}
\newcommand\ClippedLatitudeSphere[3]{
\begin{scope}[transform canvas={shift=(#1)}]
\LatitudePlane{\angEl}{#2}
\ClipLatitudeCircle{0}{#3}
\fill[ball color=white] (0,0) circle [radius=\R];
\end{scope}}
\newcommand\ClippedLongitudeSphere[3]{
\begin{scope}[transform canvas={shift=(#1)}]
\LongitudePlane{\angEl}{#2}
\ClipLongitudeCircle{#2}{#3}
\fill[ball color=white] (0,0) circle [radius=\R];
\end{scope}}
\newcommand\DrawLongitudeArc[4]{
\LongitudePlane{\angEl}{#2}
\begin{scope}[current plane, transform canvas={shift=(#1)}]
\fill [cyan] (0,0) -- ++(#3:\R) arc [start angle=#3, delta angle=#4, radius=\R] -- cycle;
\draw ++(#3:\R) arc [start angle=#3, delta angle=#4, radius=\R];
\end{scope}}
\newcommand\DrawLatitudeArc[4]{
\LatitudePlane{\angEl}{#2}
\begin{scope}[current plane, transform canvas={shift=(#1)}]
\fill [cyan] (0,0) -- ++(#3:\R) arc [start angle=#3, delta angle=#4, radius=\R] -- cycle;
\draw ++(#3:\R) arc [start angle=#3, delta angle=#4, radius=\R];
\end{scope}}
\def\D{8} % cubic side length
% \pgfmathsetmacro\R{\D/2} % sphere radius
\pgfmathsetmacro\R{sqrt(2)/4*\D} % sphere radius
% \pgfmathsetmacro\R{sqrt(3)/4*\D} % sphere radius
\def\angEl{20} % elevation angle in interval [1,89]
\def\angPh{10} % phase angle in interval [-44,44]
\pgfmathsetmacro\uofx{cos(-135-\angPh)}
\pgfmathsetmacro\vofx{sin(-135-\angPh)*sin(\angEl)}
\pgfmathsetmacro\uofy{cos(-45-\angPh)}
\pgfmathsetmacro\vofy{sin(-45-\angPh)*sin(\angEl)}
\pgfmathsetmacro\uofz{0}
\pgfmathsetmacro\vofz{cos(\angEl)}
% The coordinates of the cube
\begin{scope}[x={(\uofx cm,\vofx cm)}, y={(\uofy cm,\vofy cm)}, z={(\uofz cm,\vofz cm)}]
\coordinate (C1) at (\D,0,0);
\coordinate (C2) at (\D,0,\D);
\coordinate (C3) at (0,0,\D);
\coordinate (C4) at (0,\D,\D);
\coordinate (C5) at (0,\D,0);
\coordinate (C6) at (\D,\D,0);
\coordinate (C7) at (0,0,0);
\coordinate (C8) at (\D,\D,\D);
% \foreach \n in {1,2,...,8} \node at (C\n) {C\n};
\coordinate (C0) at ($(C2)!.5!(C5)$);
\coordinate (S1) at ($(C2)!.5!(C6)$);
\coordinate (S2) at ($(C2)!.5!(C4)$);
\coordinate (S3) at ($(C8)!.5!(C5)$);
\coordinate (S4) at ($(C6)!.5!(C7)$);
\coordinate (S5) at ($(C1)!.5!(C3)$);
\coordinate (S6) at ($(C5)!.5!(C3)$);
\end{scope}
% Draw the clipped spheres
\ClippedEightSphere{+}{-}{+}{C7}
\ClippedLongitudeSphere{S5}{45-\angPh}{+}
\ClippedLongitudeSphere{S6}{135-\angPh}{-}
\ClippedLatitudeSphere{S4}{0}{+}
\ClippedEightSphere{-}{+}{-}{C8}
\ClippedEightSphere{+}{-}{-}{C3}
\ClippedEightSphere{+}{+}{-}{C2}
% \fill[ball color=white] (C0) circle [radius=\R];
\ClippedEightSphere{-}{-}{-}{C4}
\ClippedEightSphere{+}{+}{+}{C1}
\ClippedEightSphere{-}{-}{+}{C5}
\ClippedEightSphere{-}{+}{+}{C6}
% Draw the half spheres
\ClippedLatitudeSphere{S2}{0}{-}
\ClippedLongitudeSphere{S3}{45-\angPh}{-}
\ClippedLongitudeSphere{S1}{135-\angPh}{+}
\DrawLatitudeArc{S2}{0}{0}{360}
\DrawLongitudeArc{S1}{135-\angPh}{0}{360}
\DrawLongitudeArc{S3}{45-\angPh}{0}{360}
% Draw the Arcs
\DrawLongitudeArc{C1}{135-\angPh}{90}{90}
\DrawLongitudeArc{C2}{135-\angPh}{-90}{-90}
\DrawLongitudeArc{C4}{45-\angPh}{-90}{-90}
\DrawLongitudeArc{C5}{45-\angPh}{90}{90}
\DrawLongitudeArc{C6}{135-\angPh}{90}{-90}
\DrawLongitudeArc{C6}{45-\angPh}{90}{-90}
\DrawLongitudeArc{C8}{135-\angPh}{-90}{90}
\DrawLongitudeArc{C8}{45-\angPh}{-90}{90}
\DrawLatitudeArc{C2}{0}{45-\angPh}{-90}
\DrawLatitudeArc{C3}{0}{-45-\angPh}{-90}
\DrawLatitudeArc{C4}{0}{135-\angPh}{90}
\DrawLatitudeArc{C8}{0}{135-\angPh}{-90}
% Draw the cube
\draw (C1)--(C2)--(C3)--(C4)--(C5)--(C6)--cycle;
\draw (C2)--(C8)--(C6);
\draw (C8)--(C4);
% Radius node
\coordinate (r) at ($(C2) - (\R/10,0)$);
\LongitudePlane{\angEl}{135-\angPh}
\draw [<->, current plane] (r) -- node [left] {$r$} +(-90:\R);
\end{tikzpicture}