4

I am trying to recreate the following picture with tikz-3dplot.

I made the cube without any problem but I can't add the cylinders inside the cube. I need to create solid cylinders inside the cube, the dotted lines are only in order to show the beginning and the end of the cylinder. does anyone have any idea?

enter image description here

\documentclass{article}
\usepackage{tikz}
\usepackage{xcolor}
\usepackage{tikz-3dplot}
\begin{document}
\tdplotsetmaincoords{69}{200}

\begin{tikzpicture}[scale=4,tdplot_main_coords]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\coordinate (O) at (0,0,0);
\coordinate (A0) at (0,5.5,0);
\coordinate (A1) at (1.3,5.5,0);
\coordinate (A2) at (1.3,7,0);
\coordinate (A3) at (2.7,7,0);
\coordinate (A4) at (2.7,5.5,0);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\coordinate (OB) at (0,0,1.5);
\coordinate (B0) at (0,5.5,1.5);
\coordinate (B1) at (1.3,5.5,1.5);
\coordinate (B2) at (1.3,7,1.5);
\coordinate (B3) at (2.7,7,1.5);
\coordinate (B4) at (2.7,5.5,1.5);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\draw[fill=green!70,opacity=0.6] (B4) -- (B3) --(B2)--(B1)-- cycle;

\draw[fill=green!70,opacity=0.6] (A2) -- (B2) --(B3)--(A3)--cycle;

\draw[fill=green!70,opacity=0.6] (A2) -- (B2) --(B1)--(A1)--cycle;  

\draw[fill=green!70,opacity=0.6] (A4) -- (B4) --(B3)--(A3)--cycle;    

\draw[fill=green!70,opacity=0.6] (A4) -- (A3) --(A2)--(A1)-- cycle;

\end{tikzpicture}
\end{document}
3
  • 1
    What have you tried? Nov 23, 2019 at 22:03
  • @cfr I already added the code
    – BadRobot
    Nov 23, 2019 at 22:40
  • 1
    You mean you have now ;). Thanks.
    – cfr
    Nov 24, 2019 at 0:36

1 Answer 1

7

To draw the cylinders, we need to compute the critical angles for the cylinder in y direction, the x direction being analogous. This has been done for the circles on a sphere (see here and the very nice package) and tori (see here). This answer provides you with the analogous expressions for a cylinder for generic view angles. (The cylinder in x direction is analogous, and the z direction is trivial and can be found e.g. here.) The following animation is to show that it works:

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\tikzset{declare function={
vcrity(\ph,\th)=atan2(sin(\th)*sin(\ph),min(cos(\ph),-1/sqrt(2))*cos(\th));% critical t value y cylinder
vcritz(\ph,\th)=\ph;% critical t value y cylinder
},pics/ycylinder/.style={code={
\tikzset{3d/cylinder/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/3d/cylinder/##1}}
\pgfmathsetmacro{\vmin}{vcrity(\tdplotmainphi,\tdplotmaintheta)}
\pgfmathsetmacro{\vmax}{\vmin-180}
\path[3d/cylinder/mantle]
  let \p1=($(0,1,0)-(0,0,0)$),\n1={atan2(\y1,\x1)} in
  [shading angle=\n1]
  plot[variable=\t,domain=\vmin:\vmax,smooth]
    ({\pv{r}*cos(\t)},0,{\pv{r}*sin(\t)})
    -- 
    plot[variable=\t,domain=\vmax:\vmin,smooth]
    ({\pv{r}*cos(\t)},\pv{h},{\pv{r}*sin(\t)})
    --cycle;
\pgfmathtruncatemacro{\itest}{sign(cos(\tdplotmainphi))}
\ifnum\itest=-1
    \path[3d/cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},\pv{h},{\pv{r}*sin(\t)}) ;
\fi
\ifnum\itest=1
    \path[3d/cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},0,{\pv{r}*sin(\t)}) ;
\fi
}},3d/.cd,cylinder/.cd,r/.initial=1,h/.initial=1,
mantle/.style={draw},top/.style={draw}}
\begin{document}
\foreach \X in {0,10,...,350}
{\tdplotsetmaincoords{69}{\X}
\begin{tikzpicture}[tdplot_main_coords]
 \path[tdplot_screen_coords,use as bounding box] (-4,-2.5) rectangle (4,2.5);
 \path pic{ycylinder={r=1,h=3,top/.append style={fill=gray}}};
\end{tikzpicture}}
\end{document}

enter image description here

This can be used to draw the cylinders in your picture. Notice that I reordered the planes of your picture. You may want to consider simplifying this stuff, but since I do not know what you intend to do with it I kept it for now.

\documentclass{article}
\usepackage{tikz}
\usepackage{tikz-3dplot}
\tikzset{declare function={
vcrity(\ph,\th)=atan2(sin(\th)*sin(\ph),min(cos(\ph),-1/sqrt(2))*cos(\th));% critical t value y cylinder
vcritz(\ph,\th)=\ph;% critical t value y cylinder
},pics/ycylinder/.style={code={
\tikzset{3d/cylinder/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/3d/cylinder/##1}}
\pgfmathsetmacro{\vmin}{vcrity(\tdplotmainphi,\tdplotmaintheta)}
\pgfmathsetmacro{\vmax}{\vmin-180}
\path[3d/cylinder/mantle]
  let \p1=($(0,1,0)-(0,0,0)$),\n1={atan2(\y1,\x1)} in
  [shading angle=\n1]
  plot[variable=\t,domain=\vmin:\vmax,smooth]
    ({\pv{r}*cos(\t)},0,{\pv{r}*sin(\t)})
    -- 
    plot[variable=\t,domain=\vmax:\vmin,smooth]
    ({\pv{r}*cos(\t)},\pv{h},{\pv{r}*sin(\t)})
    --cycle;
\pgfmathtruncatemacro{\itest}{sign(cos(\tdplotmainphi))}
\ifnum\itest=-1
    \path[3d/cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},\pv{h},{\pv{r}*sin(\t)}) ;
\fi
\ifnum\itest=1
    \path[3d/cylinder/top] plot[variable=\t,domain=0:360,smooth cycle]
    ({\pv{r}*cos(\t)},0,{\pv{r}*sin(\t)}) ;
\fi
}},3d/.cd,cylinder/.cd,r/.initial=1,h/.initial=1,
mantle/.style={draw},top/.style={draw}}
\begin{document}
\tdplotsetmaincoords{69}{200}

\begin{tikzpicture}[scale=3,tdplot_main_coords]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\coordinate (O) at (0,0,0);
\coordinate (A0) at (0,5.5,0);
\coordinate (A1) at (1.3,5.5,0);
\coordinate (A2) at (1.3,7,0);
\coordinate (A3) at (2.7,7,0);
\coordinate (A4) at (2.7,5.5,0);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\coordinate (OB) at (0,0,1.5);
\coordinate (B0) at (0,5.5,1.5);
\coordinate (B1) at (1.3,5.5,1.5);
\coordinate (B2) at (1.3,7,1.5);
\coordinate (B3) at (2.7,7,1.5);
\coordinate (B4) at (2.7,5.5,1.5);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% bottom
\draw[fill=green!70,opacity=0.6] (A4) -- (A3) --(A2)--(A1)-- cycle;

% left
\draw[fill=green!70,opacity=0.6] (A4) -- (B4) --(B3)--(A3)--cycle;    

\path[transform shape] 
 foreach \Z in {0.3,0.6,0.9,1.2} 
 {(2,5.5,\Z) pic{ycylinder={r=0.12,h=1.5,top/.append style={fill=gray}}}};

% right
\draw[fill=green!70,opacity=0.6] (A2) -- (B2) --(B1)--(A1)--cycle;  

% front
\draw[fill=green!70,opacity=0.6] (A2) -- (B2) --(B3)--(A3)--cycle;

% top
\draw[fill=green!70,opacity=0.6] (B4) -- (B3) --(B2)--(B1)-- cycle;

\end{tikzpicture}
\end{document}

enter image description here

ADDENDUM: If you do not need the contour, you can draw it without all these computations.

\documentclass[tikz,border=3mm]{standalone}
\usepackage{tikz-3dplot}
\begin{document}
\foreach \X in {0,10,...,350}
{\tdplotsetmaincoords{69}{\X}
\begin{tikzpicture}[tdplot_main_coords]
 \path[tdplot_screen_coords,use as bounding box] (-4,-2.5) rectangle (4,2.5);
 \draw[blue,line width=2cm] (0,0,0) -- (0,3,0);
 \pgfmathtruncatemacro{\itest}{sign(cos(\tdplotmainphi))}
 \ifnum\itest=1
    \path[fill=blue] plot[variable=\t,domain=0:360,smooth cycle]
    ({cos(\t)},3,{sin(\t)}) ;
    \path[fill=gray] plot[variable=\t,domain=0:360,smooth cycle]
    ({cos(\t)},0,{sin(\t)}) ;
 \fi
 \ifnum\itest=-1
    \path[fill=blue] plot[variable=\t,domain=0:360,smooth cycle]
    ({cos(\t)},0,{sin(\t)}) ;
    \path[fill=gray] plot[variable=\t,domain=0:360,smooth cycle]
    ({cos(\t)},3,{sin(\t)}) ;
 \fi
\end{tikzpicture}}
\end{document}

enter image description here

5
  • 1
    @ Schrödinger's cat I really appreciate your help, it was more than my initial doubt. Excellent work, thank you very much.
    – BadRobot
    Nov 24, 2019 at 3:06
  • @MaxMeneses You are welcome!
    – user194703
    Nov 24, 2019 at 3:16
  • 1
    Have you considered writing a book on advanced drawing using tikz? :)
    – Diaa
    Nov 24, 2019 at 8:56
  • @Diaa No. Some of these things get collected in this library, though.
    – user194703
    Nov 24, 2019 at 12:38
  • This is nice. Is it possible to do the same adding vanishing point perspective? I mean, the disk that is further should appear smaller. Mar 11, 2021 at 13:35

You must log in to answer this question.

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