5

I am trying to make a Furuta Pendulum with the help of TikZ and the parts are mostly cylinders and cylindrical rods. I can draw the shape of the cylinders just fine without filling colors.

However, when I am trying to fill the cylindrical surface, it appears fine when I make the normal of the surface parallel to my direction. But when I rotate to some angle, the fill is distorted, as if it is joining the top and bottom arcs so formed with a plane surface. Is there any way to make it fill along the cylindrical surface, no matter how it is rotated along some axis?

Here's my MWE:

\documentclass[tikz,multi,border=3mm]{standalone}

\usepackage{tikz-3dplot}

\begin{document}
\begin{tikzpicture}
\begin{scope}[x={(1cm,0cm)},y={(0cm,-0.5cm)},z={(0cm,1cm)}]
\draw[-stealth] (0,0,0) -- (8,0,0) node[right]{$x$};
\draw[-stealth] (0,0,0) -- (0,8,0) node[right]{$y$};
\draw[-stealth] (0,0,0) -- (0,0,8) node[right]{$z$};


\draw [fill=gray] (0,0,0) circle [radius=1];
\draw [ultra thick,preaction={fill=gray,nearly transparent}] (0:1) arc[start angle=0,end angle=180,radius=1] --++ (0,0,3) arc[start angle=180,end angle=0,radius=1] --cycle;
\end{scope}
\end{tikzpicture}
\end{document}

Unrotated

When I pass rotate around z=80 I get:

Rotated with unwanted fill

2 Answers 2

6

You can tried this code by 3dtools

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{calc,3dtools}
\begin{document} 
    \begin{tikzpicture}[3d/install view={phi=70,theta=70},
        declare function={r=2;h=3;}]
        \pic{3d/frustum={r=r,R=r,h=h}};
    \end{tikzpicture}
%%fill cylinder 
        \begin{tikzpicture}[3d/install view={phi=70,theta=70},
        declare function={r=2;h=3;}]
        \pic[3d/visible/.style={fill=gray,fill opacity=0.5}]{3d/frustum={r=r,R=r,h=h}};
    \end{tikzpicture}
    \end{document}

enter image description here

Animation

\documentclass[tikz,border=3mm]{standalone}
\usetikzlibrary{3dtools,calc} % https://github.com/marmotghost/tikz-3dtools
\begin{document} 
    \foreach \Angle in {5,15,...,355}
{   
    \begin{tikzpicture}[same bounding box=A,line cap=round,line join=round,
        3d/install view={phi=\Angle,psi=0,theta=70},
        declare function={R=3;h=3;
        }]
        \path (0,0,0) coordinate (O)
        (0,0,h) coordinate (O');
        \path[save named path=ox] (0,0,0) -- (R+ 3,0,0) node[anchor=north east]{$x$};
        \path [save named path=oy] (0,0,0) -- (0,R+2,0) node[anchor=north west]{$y$};
        \path [save named path=oz] (0,0,0) -- (0,0,h+2) node[anchor=south]{$z$};
    
        \path [3d/visible/.style={save named path=cyc,draw={none},fill=gray,fill opacity=0.5}] pic{3d/frustum={R=R,r=R,h=h}};
        
        \draw[3d/hidden,blue] (O) -- (O');
        \draw[3d/visible, - latex,blue] (O') -- (0,0,h+2);
        \tikzset{3d/ordered paths/.cd,ox/.style={blue,- latex},oy/.style={blue,- latex},oz/.style={blue,- latex}}
        \tikzset{3d/draw ordered paths={ox,oy,cyc}}
        \path foreach \p/\g in {O/-90}
        {(\p)node{}+(\g:2.5mm) node{$\p$}};
    \end{tikzpicture}}
    \end{document}

enter image description here

7
  • This library seems new to me. Is this a recent addition? And what is the purpose of R here?
    – SolidMark
    Aug 14, 2023 at 9:22
  • I get it now, you have drawn the cylinder using frustrum here with equal radius for top and bottom ends.
    – SolidMark
    Aug 14, 2023 at 9:31
  • How do you feel this library? Aug 14, 2023 at 9:34
  • I haven't heard of it or tried it before. Will give a try.
    – SolidMark
    Aug 14, 2023 at 9:38
  • Is 3dtools on CTAN? I can't seem to find it nor my TeX distribution has it. I use MikTeX version 4.9
    – SolidMark
    Aug 14, 2023 at 9:49
5

I have found a workaround to this problem by using multiple cylindrical surfaces (2 surfaces in order to simplify the problem) whose area changes according to the rotation about an axis in such a way that you still see the half cylinder. I had to use a separate macro that I created, \zr which adjusts the start angles and end angles of the arcs accordingly. The \zr macro defines the angle of rotation about the z-axis for this particular problem.

\documentclass[tikz,border=3mm]{standalone}

\begin{document}

\pgfmathsetmacro{\zr}{0} % Value of rotation angle about z-axis
\begin{tikzpicture}[x={(1cm,0cm)},y={(0cm,-0.5cm)},z={(0cm,1cm)},rotate around z=\zr]
\draw[-stealth] (0,0,0) -- (8,0,0) node[right]{$x$};
\draw[-stealth] (0,0,0) -- (0,8,0) node[below]{$y$};
\draw[-stealth] (0,0,0) -- (0,0,8) node[above]{$z$};

\draw[fill=gray!10,opacity=0.5] (0,0,0) circle [radius=1];
\draw[preaction={fill=gray,nearly transparent}] (0:1) arc[start angle=0,end angle=180-\zr,radius=1] --++ (0,0,3) arc[start angle=180-\zr,end angle=0,radius=1] -- cycle;
\draw[preaction={fill=gray,nearly transparent}] (0:-1) arc[start angle=180,end angle=180-\zr,radius=1] --++ (0,0,3) arc[start angle=180-\zr,end angle=180,radius=1] -- cycle;
\end{tikzpicture}
\end{document}

The output for various values of \zr: half-cylinder view

UPDATE

And now for full cylinder rotation about z-axis:

\documentclass[tikz,border=3mm]{standalone}

\usepackage{tikz-3dplot}

\begin{document}

\pgfmathsetmacro{\zr}{0} % Value of rotation angle about z-axis
\begin{tikzpicture}[x={(1cm,0cm)},y={(0cm,-0.5cm)},z={(0cm,1cm)},rotate around z=\zr]
\draw[-stealth] (0,0,0) -- (2,0,0) node[right]{$x$};
\draw[-stealth] (0,0,0) -- (0,2,0) node[below]{$y$};

\draw (0,0,0) circle [radius=1];
\fill[gray] (0:1) arc[start angle=0,end angle=180-\zr,radius=1] --++ (0,0,3) arc[start angle=180-\zr,end angle=0,radius=1] --cycle;
\fill[gray] (0:-1) arc[start angle=180,end angle=180-\zr,radius=1] --++ (0,0,3) arc[start angle=180-\zr,end angle=180,radius=1] --cycle;
\fill[gray] (0:-1) arc[start angle=180,end angle=360-\zr,radius=1] --++ (0,0,3) arc[start angle=360-\zr,end angle=180,radius=1] --cycle;
\fill[gray] (0:1) arc[start angle=0,end angle=0-\zr,radius=1] --++ (0,0,3) arc[start angle=0-\zr,end angle=0,radius=1] --cycle;
\draw[very thin] {[canvas is xy plane at z=0] (-\zr:1)}{[canvas is xy plane at z=3] -- (-\zr:1)};
\draw[very thin] {[canvas is xy plane at z=0] (180-\zr:1)}{[canvas is xy plane at z=3] -- (180-\zr:1)};
\draw[fill=gray!10,opacity=0.5] (0,0,3) circle [radius=1];
\draw (0,0,3) --++ (\zr:1);

\draw[-stealth] (0,0,3) -- (0,0,4) node[above]{$z$};
\end{tikzpicture}
\end{document}

The output of full rotation of cylinder about z-axis:

full cylinder rotation

And now for the final part, which involves setting values for \zr and another macro \phi that I named to represent the rotation of the second arm of the Furuta Pendulum.

The complete code:

\documentclass[tikz,border=3mm]{standalone}

\usepackage{tikz-3dplot}

\begin{document}

\pgfmathsetmacro{\zr}{45} % Value of rotation angle about z-axis
\pgfmathsetmacro{\phi}{0} % Joint rotation angle
\begin{tikzpicture}[x={(1cm,0cm)},y={(0cm,-0.5cm)},z={(0cm,1cm)}]
\draw[-stealth] (0,0,0) -- (3,0,0) node[right]{$x$};
\draw[-stealth,y={(0.707cm,0.707cm)}] (0,0,0) -- (0,2,0) node[below]{$y$};

% Base of the Furuta Pendulum (DC Motor?)
\draw (0,0,0) circle [radius=1];
\fill[gray] (0:1) arc[start angle=0,end angle=180-\zr,radius=1] --++ (0,0,3) arc[start angle=180-\zr,end angle=0,radius=1] --cycle;
\fill[gray] (0:-1) arc[start angle=180,end angle=180-\zr,radius=1] --++ (0,0,3) arc[start angle=180-\zr,end angle=180,radius=1] --cycle;
\fill[gray] (0:-1) arc[start angle=180,end angle=360-\zr,radius=1] --++ (0,0,3) arc[start angle=360-\zr,end angle=180,radius=1] --cycle;
\fill[gray] (0:1) arc[start angle=0,end angle=0-\zr,radius=1] --++ (0,0,3) arc[start angle=0-\zr,end angle=0,radius=1] --cycle;
\draw[very thin] {[canvas is xy plane at z=0] (0:1)}{[canvas is xy plane at z=3] -- (0:1)};
\draw[very thin] {[canvas is xy plane at z=0] (180:1)}{[canvas is xy plane at z=3] -- (180:1)};
\draw[fill=gray!10] (0,0,3) circle [radius=1];
\begin{scope}[rotate around z=\zr]
%  Motor Driver
\draw (0,0,3) circle [radius=0.75];
\fill[gray!80]{[canvas is xy plane at z=3] (0:0.75) arc[start angle=0,end angle=180-\zr,radius=0.75]}{[canvas is xy plane at z=3.5] --++ (0,0,0) arc[start angle=180-\zr,end angle=0,radius=0.75]} --cycle;
\fill[gray!80]{[canvas is xy plane at z=3] (0:-0.75) arc[start angle=180,end angle=180-\zr,radius=0.75]}{[canvas is xy plane at z=3.5] --++ (0,0,0) arc[start angle=180-\zr,end angle=180,radius=0.75]} --cycle;
\fill[gray!80]{[canvas is xy plane at z=3] (0:-0.75) arc[start angle=180,end angle=360-\zr,radius=0.75]}{[canvas is xy plane at z=3.5] --++ (0,0,0) arc[start angle=360-\zr,end angle=180,radius=0.75]} --cycle;
\fill[gray!80]{[canvas is xy plane at z=3] (0:0.75) arc[start angle=0,end angle=0-\zr,radius=0.75]}{[canvas is xy plane at z=3.5] --++ (0,0,0) arc[start angle=0-\zr,end angle=0,radius=0.75]} --cycle;
\draw[very thin] {[canvas is xy plane at z=3] (-\zr:0.75)}{[canvas is xy plane at z=3.5] -- (-\zr:0.75)};
\draw[very thin] {[canvas is xy plane at z=3] (180-\zr:0.75)}{[canvas is xy plane at z=3.5] -- (180-\zr:0.75)};
\draw[fill=gray!10] (0,0,3.5) circle [radius=0.75];

\draw[-stealth] (0,0,3.5) -- (0,0,6) node[above]{$z$};

% First Arm
\draw[fill=gray!10]{[canvas is yz plane at x=0.75] (0,3.25,0) circle [radius=0.1]};
\fill[gray!60]{[canvas is yz plane at x=0.75] (0,3.25,0) ++ (\zr:0.1) coordinate (a) arc[start angle=\zr,end angle=\zr+90,radius=0.1]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+90,end angle=\zr,radius=0.1]} --cycle;
\fill[gray!60]{[canvas is yz plane at x=0.75] (0,3.25,0) ++ (\zr+90:0.1) coordinate (a) arc[start angle=\zr+90,end angle=\zr+180,radius=0.1]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+180,end angle=\zr+90,radius=0.1]} --cycle;
\fill[gray!60]{[canvas is yz plane at x=0.75] (0,3.25,0) ++ (\zr+180:0.1) coordinate (b) arc[start angle=\zr+180,end angle=\zr+270,radius=0.1]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+270,end angle=\zr+180,radius=0.1]} --cycle;
\fill[gray!60]{[canvas is yz plane at x=0.75] (0,3.25,0) ++ (\zr+270:0.1) coordinate (b) arc[start angle=\zr+270,end angle=\zr+360,radius=0.1]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+360,end angle=\zr+270,radius=0.1]} --cycle;
\draw[fill=gray!10]{[canvas is yz plane at x=2.75] (0,3.25,0) circle [radius=0.1]};

% Joint
\begin{scope}
\draw[fill=gray!10]{[canvas is yz plane at x=2.75] (0,3.25,0) circle [radius=0.3]};
\fill[gray!40]{[canvas is yz plane at x=2.75] (0,3.25,0) ++ (\zr:0.3) coordinate (a) arc[start angle=\zr,end angle=\zr+90,radius=0.3]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+90,end angle=\zr,radius=0.3]} --cycle;
\fill[gray!40]{[canvas is yz plane at x=2.75] (0,3.25,0) ++ (\zr+90:0.3) coordinate (a) arc[start angle=\zr+90,end angle=\zr+180,radius=0.3]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+180,end angle=\zr+90,radius=0.3]} --cycle;
\fill[gray!40]{[canvas is yz plane at x=2.75] (0,3.25,0) ++ (\zr+180:0.3) coordinate (b) arc[start angle=\zr+180,end angle=\zr+270,radius=0.3]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+270,end angle=\zr+180,radius=0.3]} --cycle;
\fill[gray!40]{[canvas is yz plane at x=2.75] (0,3.25,0) ++ (\zr+270:0.3) coordinate (b) arc[start angle=\zr+270,end angle=\zr+360,radius=0.3]}{[canvas is yz plane at x=3.25] --++ (0,0,0) arc[start angle=\zr+360,end angle=\zr+270,radius=0.3]} --cycle;
\draw[fill=gray!10]{[canvas is yz plane at x=3.25] (0,3.25,0) circle [radius=0.3]};
\end{scope}

% Second Arm
\begin{scope}[shift={(3,0,3.25)},rotate around x=\phi]
\draw[fill=gray!10] {[canvas is xy plane at z=0.3] circle [radius=0.1]};
\fill[gray!60]{[canvas is xy plane at z=0.3] (0,0,0) ++ (\zr:0.1) coordinate (a) arc[start angle=\zr,end angle=\zr+90,radius=0.1]}{[canvas is xy plane at z=2.3] --++ (0,0,0) arc[start angle=\zr+90,end angle=\zr,radius=0.1]} --cycle;
\fill[gray!60]{[canvas is xy plane at z=0.3] (0,0,0) ++ (\zr+90:0.1) coordinate (a) arc[start angle=\zr+90,end angle=\zr+180,radius=0.1]}{[canvas is xy plane at z=2.3] --++ (0,0,0) arc[start angle=\zr+180,end angle=\zr+90,radius=0.1]} --cycle;
\fill[gray!60]{[canvas is xy plane at z=0.3] (0,0,0) ++ (\zr+180:0.1) coordinate (a) arc[start angle=\zr+180,end angle=\zr+270,radius=0.1]}{[canvas is xy plane at z=2.3] --++ (0,0,0) arc[start angle=\zr+270,end angle=\zr+180,radius=0.1]} --cycle;
\fill[gray!60]{[canvas is xy plane at z=0.3] (0,0,0) ++ (\zr+270:0.1) coordinate (a) arc[start angle=\zr+270,end angle=\zr+360,radius=0.1]}{[canvas is xy plane at z=2.3] --++ (0,0,0) arc[start angle=\zr+360,end angle=\zr+270,radius=0.1]} --cycle;
\draw[fill=gray!10] {[canvas is xy plane at z=2.3] circle [radius=0.1]};
\end{scope}
\end{scope}
\end{tikzpicture}

\end{document}

Setting the value for \zr outputs:

Driving Motor

And finally setting the value of \phi outputs:

Swinging arms

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .