![我如何用 tikz 绘制许多不相交的 3D 圆柱体,就像 3D 织物一样,无需编织?](https://linux22.com/image/406528/%E6%88%91%E5%A6%82%E4%BD%95%E7%94%A8%20tikz%20%E7%BB%98%E5%88%B6%E8%AE%B8%E5%A4%9A%E4%B8%8D%E7%9B%B8%E4%BA%A4%E7%9A%84%203D%20%E5%9C%86%E6%9F%B1%E4%BD%93%EF%BC%8C%E5%B0%B1%E5%83%8F%203D%20%E7%BB%87%E7%89%A9%E4%B8%80%E6%A0%B7%EF%BC%8C%E6%97%A0%E9%9C%80%E7%BC%96%E7%BB%87%EF%BC%9F.png)
下面的代码制作了一组圆柱体(可接受)。我正尝试制作另外两组与此圆柱体成直角的圆柱体。第二组圆柱体位于平行平面上,因此从两个圆柱体中垂直看,可以看到空的方形孔。第三组圆柱体垂直于平面,穿透方形孔。
我尝试了各种旋转但似乎无法掌握所需的变换。
目标是创建一个可以参数化的网格,使得圆柱体很薄并且在一个表达式中不会接近接触,或者圆柱体很厚并且在另一个表达式中重叠。
思考这一问题的一种方式是,看看纽约地铁的布置,地铁管道必须互不接触地通过,包括通往站台的电梯井。
平均能量损失
\documentclass[12pt]{article}
\usepackage{tikz}
\usetikzlibrary{backgrounds,shapes}
\listfiles
\begin{document}
\newcommand\Cylinder[3]{%
\begin{scope}
\tikzset{every node/.style={
cylinder,
rotate=#3,
draw,
cylinder uses custom fill,
cylinder end fill=white!25!black,
cylinder body fill=white!60!black,
minimum height=10cm,
minimum width=0.1cm,
opacity=.4}}
\node at (#1,#2) {};
\end{scope}
}
\begin{tikzpicture}
[background rectangle/.style={fill=yellow!45!white},
show background rectangle]
\foreach \y in {0,1,2,3,4,5,6,7,8,9}{
\Cylinder{0}{\y}{0}
}
\end{tikzpicture}
\end{document}
谢谢 Sc!!!!!! 在 Sc 的指导下,MWE 几乎完全按照我的要求完成了工作。
\documentclass[12pt]{article}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\usetikzlibrary{backgrounds,shapes}
\tikzset{pics/simple 3d cylinder/.style={code={
\tikzset{simple 3d cylinder/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
\tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
\begin{scope}[tdplot_rotated_coords]
\draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm]
(0,0,-\pv{h}/2) -- (0,0,\pv{h}/2);
\pgfmathtruncatemacro{\itest}{sign(
sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
-1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
+cos(\tdplotmaintheta)*cos(\pv{beta})
)}
\unless\ifnum\itest=0
\path[fill,simple 3d cylinder/mantle]
plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2});
\path[fill,simple 3d cylinder/top]
plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
\fi
\end{scope}
}},
simple 3d cylinder/.cd,
r/.initial=0.1,
h/.initial=10,
alpha/.initial=0,
beta/.initial=0,
top/.style={fill=gray},
mantle/.style={black}
}
\listfiles
\begin{document}
% TODO build chopstick mesh up from the bottom to satisfy hiddenness
\tdplotsetmaincoords{70}{126}
\noindent
\begin{tikzpicture}[tdplot_main_coords,scale=0.95]
% actin vertical
\path foreach \X in {0,...,10} {
(-0.5,\X-0.5,-5)
pic{
simple 3d cylinder=
{mantle/.style={blue},h=12}
}
};
% actin horizontal
\path foreach \X in {0,...,10} {
(0,4.5,-\X)
pic{
simple 3d cylinder=
{mantle/.style={red},h=12,alpha=90,beta=90}
}
};
% Calcium crosslink
\foreach \Z in {0,...,10} { \foreach \Y in {0,...,10} {
\shade [ball color=gray] (-0.2,\Y-0.3,-\Z-0.1)
circle [radius=0.2cm]; % 0.2 some, 0.7 complete
}}
% neurofibril
\path foreach \X in {1,...,10} {
(3.5,-0.5,-\X)
pic{
simple 3d cylinder=
{h=9.2,beta=90}
}
};
\end{tikzpicture}
\noindent\rule{\textwidth}{1pt}
\end{document}
答案1
这是一个完全可旋转的“简单”圆柱体版本,其中“简单”意味着我们稍微作弊,只画一条粗线,并确保两端没问题。我们在这个版本中没有轮廓(但可以找到轮廓这里)。然而,这些圆柱体是完全可旋转的。旋转角度为alpha
和beta
。(显然,我们只需要两个旋转角度,因为圆柱体绕其轴具有旋转对称性。)但是,这个答案(目前)没有任何 3d 排序。(可能)可以根据圆柱体的质心坐标对其进行排序。我不认为 Ti钾Z 是超越这一点的正确工具。
\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{pics/simple 3d cylinder/.style={code={
\tikzset{simple 3d cylinder/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
\tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
\begin{scope}[tdplot_rotated_coords]
\draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm] (0,0,-\pv{h}/2) --
(0,0,\pv{h}/2);
\pgfmathtruncatemacro{\itest}{sign(
sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
-1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
+cos(\tdplotmaintheta)*cos(\pv{beta})
)}
\unless\ifnum\itest=0
\path[fill,simple 3d cylinder/mantle] plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2}) ;
\path[fill,simple 3d cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
\fi
\end{scope}
}},simple 3d cylinder/.cd,r/.initial=0.2,h/.initial=2,
alpha/.initial=0,beta/.initial=0,
top/.style={fill=gray},mantle/.style={blue}}
\begin{document}
\tdplotsetmaincoords{70}{110}
\begin{tikzpicture}[tdplot_main_coords]
\path foreach \X in {1,...,10}
{(0,4,-\X) pic{simple 3d cylinder={alpha=90,beta=90,h=6,mantle/.style={red}}}
(4,0,-\X) pic{simple 3d cylinder={alpha=0,beta=90,h=6}}
(\X,\X,3) pic{simple 3d cylinder={alpha=0,beta=0,h=6,mantle/.style={orange}}}
};
\end{tikzpicture}
\end{document}
您可以手动进行 3d 排序,例如逐层绘制网格。
\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{pics/simple 3d cylinder/.style={code={
\tikzset{simple 3d cylinder/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
\tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
\begin{scope}[tdplot_rotated_coords]
\draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm] (0,0,-\pv{h}/2) --
(0,0,\pv{h}/2);
\pgfmathtruncatemacro{\itest}{sign(
sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
-1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
+cos(\tdplotmaintheta)*cos(\pv{beta})
)}
\unless\ifnum\itest=0
\path[fill,simple 3d cylinder/mantle] plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2}) ;
\path[fill,simple 3d cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
\fi
\end{scope}
}},simple 3d cylinder/.cd,r/.initial=0.15,h/.initial=12,
alpha/.initial=0,beta/.initial=0,
top/.style={fill=gray},mantle/.style={blue}}
\begin{document}
\tdplotsetmaincoords{70}{120}
\begin{tikzpicture}[tdplot_main_coords]
\foreach \X in {1,...,5}
{\path foreach \Z in {1,...,5}
{(-1+2*\X-6,0,2*\Z-6)
pic{simple 3d cylinder={alpha=90,beta=90,mantle/.style={red}}}
};
\path foreach \Y in {1,...,5}
{ foreach \Z in {1,...,5}
{(2*\X-5,2*\Y-7,2*\Z-5)
pic{simple 3d cylinder={alpha=0,beta=90,h=2,mantle/.style={blue}}}
}
(2*\X-6,2*\Y-6,0)
pic{simple 3d cylinder={alpha=0,beta=0,mantle/.style={orange}}}
};}
\end{tikzpicture}
\end{document}
下面的动画是为了说明“逐层”的含义。
\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{pics/simple 3d cylinder/.style={code={
\tikzset{simple 3d cylinder/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/simple 3d cylinder/##1}}%
\tdplotsetrotatedcoords{\pv{alpha}}{\pv{beta}}{0}
\begin{scope}[tdplot_rotated_coords]
\draw[simple 3d cylinder/mantle,line width=2*\pv{r}*1cm] (0,0,-\pv{h}/2) --
(0,0,\pv{h}/2);
\pgfmathtruncatemacro{\itest}{sign(
sin(\tdplotmaintheta)*sin(\tdplotmainphi)*cos(\pv{alpha})*sin(\pv{beta})
-1*sin(\tdplotmaintheta)*cos(\tdplotmainphi)*sin(\pv{alpha})*sin(\pv{beta})
+cos(\tdplotmaintheta)*cos(\pv{beta})
)}
\unless\ifnum\itest=0
\path[fill,simple 3d cylinder/mantle] plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{-\itest*\pv{h}/2}) ;
\path[fill,simple 3d cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
({\pv{r}*cos(\t)},{\pv{r}*sin(\t)},{\itest*\pv{h}/2});
\fi
\end{scope}
}},simple 3d cylinder/.cd,r/.initial=0.15,h/.initial=12,
alpha/.initial=0,beta/.initial=0,
top/.style={fill=gray},mantle/.style={blue}}
\begin{document}
\tdplotsetmaincoords{70}{120}
\foreach \Step in {1,...,15}
{\begin{tikzpicture}[tdplot_main_coords]
\path[tdplot_screen_coords,use as bounding box] (-8,-8) rectangle (8,8);
\foreach \X in {1,...,5}
{\path foreach \Z in {1,...,5}
{(-1+2*\X-6,0,2*\Z-6) \ifnum\numexpr3*\X-3<\Step
pic{simple 3d cylinder={alpha=90,beta=90,mantle/.style={red}}}
\fi
};
\path foreach \Y in {1,...,5}
{ foreach \Z in {1,...,5}
{(2*\X-5,2*\Y-7,2*\Z-5) \ifnum\numexpr3*\X-1<\Step
pic{simple 3d cylinder={alpha=0,beta=90,h=2,mantle/.style={blue}}}
\fi
}
(2*\X-6,2*\Y-6,0) \ifnum\numexpr3*\X-2<\Step
pic{simple 3d cylinder={alpha=0,beta=0,mantle/.style={orange}}}
\fi
};}
\end{tikzpicture}}
\end{document}
显然,对于(非常)不同的视角,需要改变图层。