I would like to draw the diagram below using either pgfplots or tikz.
I am able to draw a cylinder, using the pgfplots manual, but I don't know how to draw a fraction of a cylinder.

wedge of cheese

  • Easiest would be to use tikz3d instead. – John Kormylo Aug 17 at 23:55
  • This is not a plot, so you should not use PGFPlots, but pure TikZ. There are many sources on how to draw an arc, a line and add text(nodes). See e.g. the introduction in the TikZ manual. Anyway, for a question here you need to show what you have, and describe what is causing you problems. – hpekristiansen Aug 17 at 23:58
  • I think you found how to draw a cylinder in the TikZ manual and not in the PGFPlots manual, right? And as another side note, if you really want to use this as a diagram: Have a look at section 7.6 p. 94f in the TikZ/pgf manual (v3.0.1a) on why you shouldn't use 3D pie charts. – Stefan Pinnow Aug 18 at 5:01
up vote 21 down vote accepted

TikZ and 3D means in my experience always a bit of improvisation. One can change the view angle with some restrictions. If you want to lift these restrictions, you may have to change the drawing order and/or add or subtract certain contours. UPDATE: Fixed a bug pointed out by Friendly Ghost: the projection of the arrow on top of the cheese was incorrect. This was due to a bug in the 3d library. Some time ago I knew about it but forgot it.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{3d}
\usepackage{tikz-3dplot}
\makeatletter % https://tex.stackexchange.com/a/48776/121799
\tikzoption{canvas is xy plane at z}[]{%
  \def\tikz@plane@origin{\pgfpointxyz{0}{0}{#1}}%
  \def\tikz@plane@x{\pgfpointxyz{1}{0}{#1}}%
  \def\tikz@plane@y{\pgfpointxyz{0}{1}{#1}}%
  \tikz@canvas@is@plane
}
\makeatother

\begin{document}
\foreach \X in {0,5,...,355}
{\tdplotsetmaincoords{120+20*sin(\X)}{-135+45*cos(2*\X)}
\begin{tikzpicture}
\path[use as bounding box] (-6,-3) rectangle (6,5);
\begin{scope}[tdplot_main_coords]
\draw plot[variable=\x,domain=\tdplotmainphi+180:0,samples=30,smooth] 
({4*cos(\x)},{4*sin(\x)},0) -- (0,0,0) -- (0,-4,0)
plot[variable=\x,domain=-90:\tdplotmainphi,samples=30,smooth]
({4*cos(\x)},{4*sin(\x)},0);

\draw plot[variable=\x,domain=0:270,samples=90,smooth] 
({4*cos(\x)},{4*sin(\x)},2);

\draw (0,-4,0) -- (0,-4,2) (4,0,0) -- (4,0,2) (0,0,0) -- (0,0,2)
(0,-4,2) -- (0,0,2) -- (4,0,2) 
({4*cos(\tdplotmainphi+180)},{4*sin(\tdplotmainphi+180)},0) --
({4*cos(\tdplotmainphi+180)},{4*sin(\tdplotmainphi+180)},2)
({4*cos(\tdplotmainphi)},{4*sin(\tdplotmainphi)},0) --
({4*cos(\tdplotmainphi)},{4*sin(\tdplotmainphi)},2);
\path ({5*cos(\tdplotmainphi+180)},{5*sin(\tdplotmainphi+180)},0) coordinate(B)
({5*cos(\tdplotmainphi+180)},{5*sin(\tdplotmainphi+180)},2) coordinate(T)
(0,0,3) coordinate (A);
 \begin{scope}[x={(1,0,0)},y={(0,1,0)},z={(0,0,1)}]
 \begin{scope}[canvas is xy plane at z=2,transform shape]
  \fill (0,0) -- (0:0.1) arc(0:270:.1) -- cycle;
  \path (-0.3,0) -- (-0.3,-4) node[sloped,yscale=-1,midway] {4cm};
  \node[xscale=-1,rotate=-45] at (-0.6,0.6) {$270^\circ$};
  \pgflowlevelsynccm
  \draw[latex-latex] (0:0.4)  arc(00:270:.4);
 \end{scope}
 \end{scope}
\end{scope}
\draw[latex-latex] (T) -- (B) node[midway,left] {2cm};
\end{tikzpicture}}
\end{document}

enter image description here

ADDENDUM: A version for J Leon V. ;-)

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{3d}
\usepackage{tikz-3dplot}
\makeatletter % https://tex.stackexchange.com/a/48776/121799
\tikzoption{canvas is xy plane at z}[]{%
  \def\tikz@plane@origin{\pgfpointxyz{0}{0}{#1}}%
  \def\tikz@plane@x{\pgfpointxyz{1}{0}{#1}}%
  \def\tikz@plane@y{\pgfpointxyz{0}{1}{#1}}%
  \tikz@canvas@is@plane
}
\makeatother

\begin{document}
\foreach \X in  {0,5,...,355}
{\tdplotsetmaincoords{120+20*sin(\X)}{-135+45*cos(2*\X)}
\begin{tikzpicture}
\path[use as bounding box] (-6,-3) rectangle (6,5);
\begin{scope}[tdplot_main_coords]
% face on the left
\draw[fill=yellow!30!orange]
plot[variable=\x,domain=\tdplotmainphi+180:0,samples=30,smooth] 
({4*cos(\x)},{4*sin(\x)},0) -- ++(0,0,2)  --
plot[variable=\x,domain=0:\tdplotmainphi+180,samples=30,smooth] 
({4*cos(\x)},{4*sin(\x)},2) --cycle;
% face on the right
\draw[fill=yellow!30!orange] plot[variable=\x,domain=-90:\tdplotmainphi,samples=30,smooth]
({4*cos(\x)},{4*sin(\x)},0) -- ++(0,0,2)  --
plot[variable=\x,domain=\tdplotmainphi:-90,samples=30,smooth]
({4*cos(\x)},{4*sin(\x)},2) -- cycle;
\draw[fill=yellow!30!orange] plot[variable=\x,domain=0:270,samples=90,smooth] 
({4*cos(\x)},{4*sin(\x)},2) -- (0,-4,2) -- (0,0,2) -- (4,0,2) ;
\begin{scope}[canvas is xz plane at y=0,transform shape]
\filldraw[fill=yellow!80!orange] (4,2) -- (4,0) --(0,0) -- (0,2) -- cycle;
\foreach \x/\y/\r in {0.4/0.6/0.3, 
0.5/1.3/0.2,
1.5/0.5/0.4,
1.5/0.5/0.4, 
2.1/1.5/0.3,
2.5/0.8/0.2, 
3.3/1.1/0.3}
{\shade[ball color=yellow!80!orange,opacity=0.2] (\x,\y) circle (\r);}
\end{scope}
\begin{scope}[canvas is yz plane at x=0,transform shape]
\filldraw[fill=yellow!80!orange] (-4,2) -- (-4,0) --(0,0) -- (0,2) -- cycle;
\foreach \x/\y/\r in {-0.4/0.6/0.3, 
-0.5/1.3/0.2,
-1.5/0.5/0.4,
-1.5/0.5/0.4, 
-2.1/1.5/0.3,
-2.5/0.8/0.2, 
-3.3/1.1/0.3}
{\shade[ball color=yellow!80!orange,opacity=0.2] (\x,\y) circle (\r);}
\end{scope}
\path ({5*cos(\tdplotmainphi+180)},{5*sin(\tdplotmainphi+180)},0) coordinate(B)
({5*cos(\tdplotmainphi+180)},{5*sin(\tdplotmainphi+180)},2) coordinate(T)
(0,0,3) coordinate (A);
 \begin{scope}[x={(1,0,0)},y={(0,1,0)},z={(0,0,1)}]
 \begin{scope}[canvas is xy plane at z=2,transform shape]
  \fill (0,0) -- (0:0.1) arc(0:270:.1) -- cycle;
  \path (-0.3,0) -- (-0.3,-4) node[sloped,yscale=-1,midway] {4cm};
  \node[xscale=-1,rotate=-45] at (-0.6,0.6) {$270^\circ$};
  \pgflowlevelsynccm
  \draw[latex-latex] (0:0.4)  arc(00:270:.4);
 \end{scope}
 \end{scope}
\end{scope}
\draw[latex-latex] (T) -- (B) node[midway,left] {2cm};
\end{tikzpicture}}
\end{document}

enter image description here

2nd ADDENDUM: A version that works for all angles. This exploits the fact that the missing piece has an arc of 90 degrees. Therefore one can cook it down to 8 orderings of the elements.

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{3d}
\usepackage{tikz-3dplot}
\makeatletter % https://tex.stackexchange.com/a/48776/121799
\tikzoption{canvas is xy plane at z}[]{%
  \def\tikz@plane@origin{\pgfpointxyz{0}{0}{#1}}%
  \def\tikz@plane@x{\pgfpointxyz{1}{0}{#1}}%
  \def\tikz@plane@y{\pgfpointxyz{0}{1}{#1}}%
  \tikz@canvas@is@plane
}
\makeatother
\newcommand{\DrawVerticalPart}[3][]{%
\draw[fill=yellow!30!orange,#1]
plot[variable=\x,domain=#2:#3,samples=30,smooth] 
({4*cos(\x)},{4*sin(\x)},0) -- ++(0,0,2)  --
plot[variable=\x,domain=#3:#2,samples=30,smooth] 
({4*cos(\x)},{4*sin(\x)},2) --cycle;
}
\newcommand{\CheesePiece}[1]{\ifcase#1
\or% 1: xz face
\begin{scope}[canvas is xz plane at y=0,transform shape]
\filldraw[fill=yellow!80!orange] (4,2) -- (4,0) --(0,0) -- (0,2) -- cycle;
\foreach \x/\y/\r in {0.4/0.6/0.3, 
0.5/1.3/0.2,
1.5/0.5/0.4,
1.5/0.5/0.4, 
2.1/1.5/0.3,
2.5/0.8/0.2, 
3.3/1.1/0.3}
{\shade[ball color=yellow!80!orange,opacity=0.2] (\x,\y) circle (\r);}
\end{scope}
\or% 2: yz face 
\begin{scope}[canvas is yz plane at x=0,transform shape]
\filldraw[fill=yellow!80!orange] (-4,2) -- (-4,0) --(0,0) -- (0,2) -- cycle;
\foreach \x/\y/\r in {-0.4/0.6/0.3, 
-0.5/1.3/0.2,
-1.5/0.5/0.4,
-1.5/0.5/0.4, 
-2.1/1.5/0.3,
-2.5/0.8/0.2, 
-3.3/1.1/0.3}
{\shade[ball color=yellow!80!orange,opacity=0.2] (\x,\y) circle (\r);}
\end{scope}
\or% 3: top
\draw[fill=yellow!30!orange] plot[variable=\x,domain=0:270,samples=90,smooth] 
({4*cos(\x)},{4*sin(\x)},2) -- (0,-4,2) -- (0,0,2) -- (4,0,2);
\or% 4: bottom
\draw[fill=yellow!30!orange] plot[variable=\x,domain=0:270,samples=90,smooth] 
({4*cos(\x)},{4*sin(\x)},0) -- (0,-4,0) -- (0,0,0) -- (4,0,0);
\fi} 
\begin{document}
\foreach \X in {0,5,...,355}%{45,135,225,315} 
{%\tdplotsetmaincoords{120+20*sin(\X)}{-135+45*cos(2*\X)}
\tdplotsetmaincoords{90+30*sin(\X)}{\X}
\begin{tikzpicture}
\path[use as bounding box] (-6,-3) rectangle (6,5);
\pgfmathtruncatemacro{\xtest}{sign(cos(\tdplotmainphi+90))}
\pgfmathtruncatemacro{\ytest}{sign(-cos(\tdplotmainphi))}
\pgfmathtruncatemacro{\ztest}{sign(cos(\tdplotmaintheta))}
%\node[anchor=north west] at (-6,5) {\X,\xtest,\ytest,\ztest};
\begin{scope}[tdplot_main_coords]
\ifnum\xtest=1
  \CheesePiece{2}
  \ifnum\ytest=1
    \CheesePiece{1}
    \DrawVerticalPart{0}{\tdplotmainphi-180}
    \DrawVerticalPart{\tdplotmainphi}{270}
  \else
    \DrawVerticalPart{0}{\tdplotmainphi-180}
  \fi
\else
  \ifnum\ytest=1
    \CheesePiece{1}
    \DrawVerticalPart{\tdplotmainphi}{270}
  \else
    \DrawVerticalPart{\tdplotmainphi}{\tdplotmainphi+180}
  \fi
\fi
\ifnum\ztest=1
\CheesePiece{4}
\else
\CheesePiece{3}
\fi
\end{scope}
\end{tikzpicture}}
\end{document}

enter image description here

  • 3
    Off-topic: People, ducks, marmots and gifs, gifs, GIIIIIIFS. :) – manooooh Aug 18 at 2:26
  • 2
    At some points in space and time there are conditions in which the arrow heads look a bit weird. – Friendly Ghost Aug 18 at 2:29
  • 2
    @FriendlyGhost Very good observation! Thanks! I fixed it, I believe. (One should always look at the output before uploading... ;-) – marmot Aug 18 at 2:54
  • 2
    @manooooh Added. – marmot Aug 18 at 4:53
  • 2
    +1 Excellent, as always exceeding expectations, but what about the internal lines of the cut ... – J Leon V. Aug 18 at 6:17

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.