[Tex/LaTex] Efficient way to partially fill a cylinder

tikz-pgf

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

Best Answer

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.