
Мне нужно реализовать массив, состоящий из цилиндрических элементов. Однако, код ниже может предоставить только прямой цилиндр (кредит кода принадлежитэта ссылка), вместо этого мне нужно согнуть его, как показано на рисунке, может быть, не под тем углом, а вертикально. Но у меня это не получилось. Я даже не смог увеличить количество цилиндров с одного на большее.
\documentclass[border=2mm]{standalone}
\usepackage{xcolor}
\definecolor{mycolor}{RGB}{8,108,131}
\usepackage{tikz}
\usetikzlibrary{positioning}
\usetikzlibrary{backgrounds}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{calc}
\tikzset{cylinder end fill/.style={path picture={
\pgftransformshift{\centerpoint}%
\pgftransformrotate{\rotate}%
\pgfpathmoveto{\beforetop}%
\pgfpatharc{90}{-270}{\xradius and \yradius}%
\pgfpathclose
\pgfsetfillcolor{#1}%
\pgfusepath{fill}}
}}
\begin{document}
\begin{tikzpicture}
\begin{scope}[on background layer]
\path let \p1=(0.2,8.4),
\n1={atan2(\y1,\x1)},\n2={veclen(\y1,\x1)} in
node[cylinder, rotate=270,
minimum height=0.85*\n2,minimum width=1cm,aspect=1.0,
cylinder end fill=red,
left color=red!30,right color=black,middle color=red!80, opacity=0.7,
draw] at (0.8,4.7) {1};
\end{scope}
\end{tikzpicture}
\end{document}
решение1
Вот ответ, который производит что-то длинное, эти строки. Ключевой ингредиент — perspective
библиотека. Она используетхороший трюк от Symbol 1(и, как обычно, действительно крутые вещи не имеют большого количества голосов... ;-) что позволяет нам избегать записи tpp cs:x=...,y=...,z=...
, мы можем просто координаты и переключатель switch on perspective
. Поскольку декорации вызывают dimension too large
ошибки, градиент цвета и изменение ширины линии достигаются с помощью циклов, поэтому это занимает некоторое время для компиляции (12 секунд на 5-летнем MacBook Pro). Более быстрый ответ на основе декораций, который работает для не слишком извилистых путей, можно найти ниже.
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{calc,perspective,3d}
\makeatletter
\tikzset{switch on perspective/.code={\def\tikz@parse@splitxyz##1##2##3,##4,{%
\def\pgfutil@next{\tikz@scan@one@point##1(tpp cs:x={##2},y={##3},z={##4})}% https://tex.stackexchange.com/a/365418/194703
}}}
\makeatother
\begin{document}
\begin{tikzpicture}[3d view={-70}{15}]
\begin{scope}[perspective={p = {(20,0,0)}, q = {(0,20,0)}},switch on perspective]
\path let \p1=($(0,2,0)-(0,0,0)$),\p2=($(20,2,0)-(20,0,0)$),
\n1={atan2(\y1,\x1)/2+atan2(\y2,\x2)/2} in
[left color=black,right color=gray!80!black,shading angle=\n1]
(0,-3,0) -- (0,3,0) -- (20,3,0) -- (20,-3,0) -- cycle;
\begin{scope}
\clip (1,-3,0) -- (1,3,0) -- (20,3,0) -- (20,-3,0) -- cycle;
\foreach \X [count=\Y] in {2,1.2,-1.2,-2}
{\foreach \Z [evaluate=\Z as \CF using {int(90-\Z/3)}] in {1,...,95}
{\draw let
\p1=($(0.8+\Z/5,\X+0.5,0)-(0.8+\Z/5,\X-0.5,0)$),
\n1={sqrt(\x1*\x1+\y1*\y1)} in [line width=0.1*\n1,gray!\CF!black]
plot[variable=\t,domain=0.8+\Z/5:0.8+\Z/5+0.4,samples=5,smooth]
(\t,{\X+0.2*pow(-1,\Y+1)*isodd(int(\t/2.05))},0) ;}}
\path foreach \X [count=\Y] in {2,1.2,-1.2,-2}
{(1,{\X+pow(-1,\Y+1)*0.2*isodd(int(1/2.05))},0) coordinate (aux\Y) };
\end{scope}
\end{scope}
\begin{scope}[canvas is xz plane at y=0]
\fill[rotate=-15] foreach \X in {1,...,4} {(aux\X) circle[x radius=5pt,y radius=1pt]};
\end{scope}
\end{tikzpicture}
\end{document}
Для прямых цилиндров проблем не возникает, декорирование выполнено хорошо.
\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{calc,decorations,perspective,3d}
\makeatletter
\tikzset{switch on perspective/.code={\def\tikz@parse@splitxyz##1##2##3,##4,{%
\def\pgfutil@next{\tikz@scan@one@point##1(tpp cs:x={##2},y={##3},z={##4})}% https://tex.stackexchange.com/a/365418/194703
}}}
\makeatother
% the following decoration is based on
% https://tex.stackexchange.com/a/14295/128068 and
% https://tex.stackexchange.com/a/471222
\pgfkeys{/pgf/decoration/.cd,
start color/.store in=\startcolor,
start color=black,
end color/.store in=\endcolor,
end color=black,
varying line width steps/.initial=100
}
\pgfdeclaredecoration{width and color change}{initial}{
\state{initial}[width=0pt, next state=line, persistent precomputation={%
\pgfmathparse{\pgfdecoratedpathlength/\pgfkeysvalueof{/pgf/decoration/varying line width steps}}%
\let\increment=\pgfmathresult%
\def\x{0}%
}]{}
\state{line}[width=\increment pt, persistent postcomputation={%
\pgfmathsetmacro{\x}{\x+\increment}
},next state=line]{%
\pgfmathparse{varyinglw(100*(\x/\pgfdecoratedpathlength))}
\pgfsetlinewidth{\pgfmathresult pt}%
\pgfpathmoveto{\pgfpointorigin}%
\pgfmathsetmacro{\steplength}{1.4*\increment}
\pgfpathlineto{\pgfqpoint{\steplength pt}{0pt}}%
\pgfmathsetmacro{\y}{100*(\x/\pgfdecoratedpathlength)}
\pgfsetstrokecolor{\endcolor!\y!\startcolor}%
\pgfusepath{stroke}%
}
\state{final}{%
\pgfsetlinewidth{\pgflinewidth}%
\pgfpathmoveto{\pgfpointorigin}%
\pgfmathsetmacro{\y}{100*(\x/\pgfdecoratedpathlength)}
\color{\endcolor!\y!\startcolor}%
\pgfusepath{stroke}%
}
}
\begin{document}
\begin{tikzpicture}[3d view={-70}{15}]
\begin{scope}[perspective={p = {(20,0,0)}, q = {(0,20,0)}},switch on perspective]
\path let \p1=($(0,2,0)-(0,0,0)$),\p2=($(20,2,0)-(20,0,0)$),
\n1={atan2(\y1,\x1)/2+atan2(\y2,\x2)/2} in
[left color=black,right color=gray!80!black,shading angle=\n1]
(0,-3,0) -- (0,3,0) -- (20,3,0) -- (20,-3,0) -- cycle;
\begin{scope}
\clip (1,-3,0) -- (1,3,0) -- (20,3,0) -- (20,-3,0) -- cycle;
\foreach \X [count=\Y] in {2,1.2,-1.2,-2}
{\draw[decorate,decoration={width and color change}] let
\p1=($(10,\X+0.5,0)-(10,\X-0.5,0)$),\p2=($(1,\X+0.5,0)-(1,\X-0.5,0)$),
\n1={sqrt(\x1*\x1+\y1*\y1)},\n2={sqrt(\x2*\x2+\y2*\y2)} in
[declare function={varyinglw(\x)=0.1*\n1+0.1*(\n2-\n1)*\x/100;},
/pgf/decoration/start color=gray!70!black,/pgf/decoration/end color=gray]
(20,\X,0) -- (1,\X,0) coordinate (aux\Y);}
\end{scope}
\end{scope}
\begin{scope}[canvas is xz plane at y=0]
\fill[rotate=-15] foreach \X in {1,...,4} {(aux\X) circle[x radius=5pt,y radius=1pt]};
\end{scope}
\end{tikzpicture}
\end{document}
Вероятно, можно найти области параметров, в которых криволинейные пути тоже работают, но, возможно, лучше потратить время на то, чтобы попытаться обучиться этим декорациям fpu
.