![使用 TikZ 制作彩色棱镜](https://linux22.com/image/410990/%E4%BD%BF%E7%94%A8%20TikZ%20%E5%88%B6%E4%BD%9C%E5%BD%A9%E8%89%B2%E6%A3%B1%E9%95%9C.png)
全部。
我使用 TikZ 的 3d 库绘制了一个五角柱。代码如下:
\documentclass[tikz,border=1cm]{standalone}
\colorlet{blu}{blue!10}
\usetikzlibrary{3d,
% arrows
}
\begin{document}
\begin{tikzpicture}[opacity=0.8]
\newdimen\len
\len=2cm
%\foreach
\begin{scope}[canvas is zx plane at y=0]
\pgfmathsetmacro{\angle}{360/5}
\draw[fill=blu] %
(0:\len) coordinate (a0)
\foreach \i in {1,...,4} {
-- (\angle*\i:\len) coordinate (a\i)
}
-- cycle;
\end{scope}
\begin{scope}[canvas is zx plane at y=3]
\pgfmathsetmacro{\angle}{360/5}
\draw[fill=blu] %
(0:\len) coordinate (b0)
\foreach \i in {1,...,4} {
-- (\angle*\i:\len) coordinate (b\i)
}
-- cycle;
\end{scope}
\draw (a3) -- (b3);
\draw[fill=blu] (a0) -- node [midway,anchor=north] {$l$} (a4) -- node[midway,anchor=east] {$h$} (b4) -- (b0);
\foreach \q in {0,1}{
\pgfmathsetmacro{\s}{\q + 1}
\draw[fill=blu] (a\s) -- (a\q) -- (b\q) -- (b\s) ;
}
\draw (a2) -- (b2);
\pgfmathsetmacro{\R}{5}
%\coordinate (O) at (0,0,0);
%\foreach \a/\pos in {x/north,y/east,z/west}
% \draw[very thin,->] (O) -- (xyz cs: \a=\R) node[anchor=\pos] {$\a$};
\end{tikzpicture}
尽管它可以工作并且看起来可以接受,但我想使用循环来优化此代码。这是另一个 MWE:
\documentclass[tikz,border=1cm]{standalone}
\colorlet{blu}{blue!10}
\usetikzlibrary{3d}
\begin{document}
\begin{tikzpicture}
\newdimen\len
\len=2cm
\foreach \i in {1,...,5} {
\begin{scope}[canvas is xz plane at y=0]
\coordinate (a\i) at (\i*360/5:\len);
\end{scope}
\begin{scope}[canvas is xz plane at y=3]
\coordinate (b\i) at (\i*360/5:\len);
\end{scope}
\draw (a\i) -- (b\i);
}
\foreach \q in {a,b}{
\foreach \j in {1,...,4} {
\pgfmathsetmacro\k{\j+1}
\draw (\q\j) -- (\q\k);
}
\draw (\q5) -- (\q1); %LOOP
}
\end{tikzpicture}
\end{document}
这很好。我现在不知道该怎么做的是如何填充它;我也非常想循环绘制底面五边形(这就是我添加“%LOOP”注释的原因)。在第一个例子中,我注释了生成轴的代码,但它们最终会出现在这个图中。看到这个帖子,我想指出的是,我希望棱柱像这样画,而不是以五边形作为前景和背景(这是我正在写的一组笔记,像这样画棱柱很重要)。
我知道每篇帖子应该问一个问题,所以我真正想首先解决的是填充部分:如何填充第二个图形的表面(按原样绘制)?
谢谢!
答案1
我不认为这个3d
图书馆能给你带来很大的优势,但这里有一个使用它的答案。
\documentclass[tikz,border=1cm]{standalone}
\colorlet{blu}{blue!10}
\usetikzlibrary{3d,backgrounds,perspective}
\begin{document}
\begin{tikzpicture}[3d view={65}{25}]
\newdimen\len
\len=2cm
\foreach \i in {1,...,6} {
\begin{scope}[canvas is xy plane at z=0]
\coordinate (a\i) at (\i*360/5:\len);
\end{scope}
\begin{scope}[canvas is xy plane at z=3]
\coordinate (b\i) at (\i*360/5:\len);
\end{scope}
\ifnum\i>1
\draw[fill=blue!20,fill opacity=0.5]
(b\the\numexpr\i-1) -- (a\the\numexpr\i-1) -- (a\i) -- (b\i) -- cycle;
\fi
}
\begin{scope}[on background layer]
\draw[fill=blue!20,fill opacity=0.5] plot[samples at={1,...,5}] (a\x);
\end{scope}
\draw[fill=blue!20,fill opacity=0.5] plot[samples at={1,...,5}] (b\x);
\end{tikzpicture}
\end{document}
正如你所看到的,我忍不住添加了一个正交投影。
使其完全可旋转的一种方法是使用这个帖子,这需要3D 工具库。(这个库的开发陷入停滞,因为似乎没有办法在 GitHub 上维护它。)
\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\usetikzlibrary{3dtools}
\begin{document}
\newcommand\GetProj[2]{\begingroup
\foreach \Coord [count=\nCoord] in #1
{\ifnum\nCoord=1
\xdef\temp{\Coord}
\else
\xdef\temp{\temp+\Coord}
\fi}
\edef\ntemp{\noexpand\path[overlay,3d coordinate={(tmp)=\temp}];}
\ntemp
\pgfmathsetmacro{#2}{TD("(n)o(tmp)")}
\pgfmathsmuggle#2\endgroup}
\newcounter{tdorder}
\foreach \X in {1,...,20}
{\pgfdeclarelayer{layer\X}
\ifnum\X=1
\xdef\LstLayers{layer\X}
\else
\xdef\LstLayers{\LstLayers,layer\X}
\fi}
\pgfsetlayers\LstLayers
\tikzset{closed polygon/.style={insert path={foreach \Coord [count=\nCoord] in {#1}
{\ifnum\nCoord=1
\Coord
\else
-- \Coord
\fi} -- cycle}},polygon/.style={insert path={foreach \Coord [count=\nCoord] in {#1}
{\ifnum\nCoord=1
\Coord
\else
-- \Coord
\fi}}}}
%
\foreach \X in {5,15,...,355}
{\tdplotsetmaincoords{90-30*cos(\X)}{\X}
\begin{tikzpicture}[tdplot_main_coords,font=\sffamily,fill opacity=1]
\path[tdplot_screen_coords,use as bounding box] (-5,-5) rectangle (5,5);
\path foreach \X [count=\cX] in {b,t}
{foreach \Y [count=\cY] in {A,B,C,D,E}
{({2*cos(72*\cY)},{2*sin(72*\cY)},-4.5+3*\cX) coordinate(\X\Y)}};
\def\PlaneData{%
{draw,fill=blue!20}/closed polygon/{(bA),(tA),(tB),(bB)},%
{draw,fill=blue!20}/closed polygon/{(bB),(tB),(tC),(bC)},%
{draw,fill=blue!20}/closed polygon/{(bC),(tC),(tD),(bD)},%
{draw,fill=blue!20}/closed polygon/{(bD),(tD),(tE),(bE)},%
{draw,fill=blue!20}/closed polygon/{(bE),(tE),(tA),(bA)},%
{draw,fill=blue!20}/closed polygon/{(tA),(tB),(tC),(tD),(tE)},%
{draw,fill=blue!20}/closed polygon/{(bA),(bB),(bC),(bD),(bE)}}
% normal of screen
\path[overlay] ({sin(\tdplotmaintheta)*sin(\tdplotmainphi)},
{-1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)},
{cos(\tdplotmaintheta)}) coordinate (n);
% build up the list of projections
\foreach \Style/\Poly/\CoordLst [count=\nC] in \PlaneData
{%
\GetProj{\CoordLst}{\currproj}
\ifnum\nC=1
\xdef\LstProj{\currproj}
\else
\xdef\LstProj{\LstProj,\currproj}
\fi}
% draw the planes in appropriate layers
\foreach \Style/\Poly/\CoordLst [count=\nC] in \PlaneData
{%
\GetProj{\CoordLst}{\currproj}
\setcounter{tdorder}{1}
\foreach \Proj in \LstProj
{\pgfmathtruncatemacro{\itest}{ifthenelse(\Proj<\currproj,1,0)}
\ifnum\itest=1
\stepcounter{tdorder}
\fi}
\begin{pgfonlayer}{layer\number\value{tdorder}}
\edef\temp{\noexpand\path[\Style,\Poly={\CoordLst}];}
\temp
\end{pgfonlayer}
}
%
\end{tikzpicture}}
\end{document}