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}
BadRobot
  • 179

1 Answers1

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