12

I am new to tikz and am using it to draw cylinders. I understand how to invoke cylinder body fill to completely fill one, but I also need some cylinders that are only shaded to a certain height. Is there a built in parameter for cylinder that automates this? Looking at p433 of the documentation and searching this forum, I don't see one. If so, I'd like to learn it.

If not, I was thinking I'd just overlay two cylinders---one "body filled" with blue, the other, shorter one filled with white---to achieve the desired effect. I can do that, so I'm not asking for code. I'm more wondering if this is how veteran tikz users think about this problem.

Edit: Adding my (admittedly inelegant) code.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,shapes,decorations.markings}

% Syntax: \Cylinder{<x-coordinate>}{<y-coordinate>}{<name>}
\newcommand\whitebodyCylinder[3]{%
\tikzset{Cylin/.style={cylinder, shape border rotate = 90, draw, cylinder uses custom fill,
  cylinder end fill = white, cylinder body fill = white, minimum height = 4cm,
  minimum width = 3cm, opacity = 1, aspect = 2.5}}
  \node[Cylin] (#3) at (#1,#2) {};
}

\newcommand\bluebottomCylinder[3]{%
\tikzset{Cylin/.style={cylinder, shape border rotate = 90, draw, cylinder uses custom fill,
  cylinder end fill = blue!20, cylinder body fill = blue!20, minimum height =2cm,
  minimum width = 3cm, opacity = 1, aspect = 2.5}}
  \node[Cylin] (#3) at (#1,#2) {};
  \draw[dashed] (#1+1.5,-.5+#2) arc [start angle=0, end angle=180,
    x radius=1.5cm, y radius=3mm];
}

\begin{document}


\begin{tikzpicture}
  \whitebodyCylinder{0}{0}{}
  \bluebottomCylinder{0}{-1}{}
\end{tikzpicture}

\end{document}

enter image description here

4
  • 3
    Real men, like Andrew Stacey, do stuff like this.
    – Jake
    Commented May 10, 2012 at 21:32
  • Ha! I saw that one while searching. It's on my "things to figure out how to do" list. ;-)
    – JohnD
    Commented May 10, 2012 at 21:44
  • 1
    Andrew hasn't told us how he did that, but he did post a really nice explanation for getting (unfilled) 3D cylinders at Drawing simple 3D cylinders in TikZ
    – Jake
    Commented May 10, 2012 at 21:45
  • 1
    The code in the question that Jake links to first really, really was horrible. It was a quick hack to make a joke and many things were done by eye. Thinking about what the final output would have to involve, I can't think of a way to do this that isn't, deep down, two cylinders with one filled and one drawn. To make it look as good as possible, I'd probably decompose it further to ensure that the fills and draws take place in the right order. Of course, one could wrap it up in a macro (as TB has done) but deep down that's what would be happening. Commented May 11, 2012 at 7:11

1 Answer 1

14

I don't know about cylinder patricians like Andrew Stacey, but if you don't neccesarily need the filled cylinders in any perspectivce, a cylinder pleb like me might do something like this:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}

\newcommand{\paficy}[5]{%
\pgfmathsetmacro{\cylinderradius}{#1}
\pgfmathsetmacro{\cylinderheight}{#2}
\pgfmathsetmacro{\fillpercentage}{#3}
\pgfmathsetmacro{\aspectratio}{#4}
\providecommand{\fillcolor}{#5}
\fill[\fillcolor] (0,0) ellipse (\cylinderradius*1cm and \cylinderradius*\aspectratio*1cm);
\fill[\fillcolor] (0,\cylinderheight*\fillpercentage) ellipse (\cylinderradius*1cm and \cylinderradius*\aspectratio*1cm);
\fill[\fillcolor] (-\cylinderradius,0) rectangle (\cylinderradius,\cylinderheight*\fillpercentage);
\draw (-\cylinderradius,0) arc (180:360:\cylinderradius*1cm and \cylinderradius*\aspectratio*1cm);
\draw[dashed] (-\cylinderradius,0) arc (180:0:\cylinderradius*1cm and \cylinderradius*\aspectratio*1cm);
\draw (0,\cylinderheight*\fillpercentage) ellipse (\cylinderradius*1cm and \cylinderradius*\aspectratio*1cm);
\draw (0,\cylinderheight) ellipse (\cylinderradius*1cm and \cylinderradius*\aspectratio*1cm);
\draw (-\cylinderradius,0) -- (-\cylinderradius,\cylinderheight);
\draw (\cylinderradius,0) -- (\cylinderradius,\cylinderheight);
}

\begin{document}

\begin{tikzpicture}
    \paficy{2}{7}{0.37}{0.35}{red!50!orange}
\end{tikzpicture}
\begin{tikzpicture}
    \paficy{2}{7}{0.89}{0.35}{green!50!orange}
\end{tikzpicture}

\begin{tikzpicture}
    \paficy{4}{5}{0.25}{0.15}{blue!70!gray}
\end{tikzpicture}
\begin{tikzpicture}
    \paficy{4}{5}{0.75}{0.15}{red!70!gray}
\end{tikzpicture}

\end{document}

enter image description here

If however you need them in other perspectives, I really can recommend Andrew Stacey's answer linked by Jake, it came in very handy when I had to do a exploded view drawing a while back.

4
  • 2
    Looks good to me. The only thing I can see that I would have done differently would be to make the options pgf keys. Not only can they then be set as defaults, but also it makes it easier to remember which one is which. Commented May 11, 2012 at 7:14
  • Yes, I thought about that. But that would have required to look up exactly how that was done again, and this I could do out of the box. But feel free to edit it ;) Commented May 11, 2012 at 8:07
  • 1
    Great, highly flexible solution with those 5 control parameters. This helps me greatly. Thanks!
    – JohnD
    Commented May 11, 2012 at 13:17
  • To draw in other perspectives, the idea of changing x and y as given in tex.stackexchange.com/a/31606/157031 should work I guess. Commented Jul 6, 2020 at 16:24

You must log in to answer this question.

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