24

I want to draw 3 cubes, one filled with water, a full half full and another completely empty. I can draw them, but I can't do the impression of three forms: full, empty and half full.

\documentclass{article}
\usepackage{tikz}
\usepackage{xcolor}
\begin{document}
\newcommand{\Depth}{2}
\newcommand{\Height}{2}
\newcommand{\Width}{2}
\begin{tikzpicture}
\coordinate (O) at (0,0,0);
\coordinate (A) at (0,\Width,0);
\coordinate (B) at (0,\Width,\Height);
\coordinate (C) at (0,0,\Height);
\coordinate (D) at (\Depth,0,0);
\coordinate (E) at (\Depth,\Width,0);
\coordinate (F) at (\Depth,\Width,\Height);
\coordinate (G) at (\Depth,0,\Height);
\draw[blue,fill=gray!20] (O) -- (C) -- (G) -- (D) -- cycle;
\draw[blue,fill=gray!20] (O) -- (A) -- (E) -- (D) -- cycle;
\draw[blue,fill=gray!10] (O) -- (A) -- (B) -- (C) -- cycle;
\draw[gray,fill=gray20,opacity=0.4] (D) -- (E) -- (F) -- (G) -- cycle;
\draw[blue,fill=gray!20,opacity=0.6] (C) -- (B) -- (F) -- (G) -- cycle;
\draw[blue,fill=gray!20,opacity=0.8] (A) -- (B) -- (F) -- (E) -- cycle;
\end{tikzpicture}
\qquad
\begin{tikzpicture}
\coordinate (O) at (0,0,0);
\coordinate (A) at (0,\Width,0);
\coordinate (B) at (0,\Width,\Height);
\coordinate (C) at (0,0,\Height);
\coordinate (D) at (\Depth,0,0);
\coordinate (E) at (\Depth,\Width,0);
\coordinate (F) at (\Depth,\Width,\Height);
\coordinate (G) at (\Depth,0,\Height);
\draw[fill=whitegray!20] (O) -- (C) -- (G) -- (D) -- cycle;
\draw[fill=gray!20] (O) -- (A) -- (E) -- (D) -- cycle;
\draw[fill=gray!10] (O) -- (A) -- (B) -- (C) -- cycle;
\draw[fill=gray20,opacity=0.4] (D) -- (E) -- (F) -- (G) -- cycle;
\draw[fill=gray!5,opacity=0.6] (C) -- (B) -- (F) -- (G) -- cycle;
\draw[fill=gray!5,opacity=0.8] (A) -- (B) -- (F) -- (E) -- cycle;
\end{tikzpicture}
\qquad
\begin{tikzpicture}
\coordinate (O) at (0,0,0);
\coordinate (A) at (0,\Width,0);
\coordinate (B) at (0,\Width,\Height);
\coordinate (C) at (0,0,\Height);
\coordinate (D) at (\Depth,0,0);
\coordinate (E) at (\Depth,\Width,0);
\coordinate (F) at (\Depth,\Width,\Height);
\coordinate (G) at (\Depth,0,\Height);
\draw[fill=whitegray!20] (O) -- (C) -- (G) -- (D) -- cycle;
\draw[fill=gray!20] (O) -- (A) -- (E) -- (D) -- cycle;
\draw[fill=gray!10] (O) -- (A) -- (B) -- (C) -- cycle;
\draw[fill=gray20,opacity=0.4] (D) -- (E) -- (F) -- (G) -- cycle;
\draw[fill=gray!5,opacity=0.6] (C) -- (B) -- (F) -- (G) -- cycle;
\draw[fill=gray!5,opacity=0.8] (A) -- (B) -- (F) -- (E) -- cycle;
\end{tikzpicture}
\end{document}

enter image description here

  • 1
    I've taken the liberty of indenting all lines of code by four spaces, to let the site's software pretty-print them as computer code. – Mico Jul 20 '15 at 22:40
  • 2
    @Mico did you do this by hand? or using {} in toolsbar? – touhami Jul 20 '15 at 22:59
40

Something like this?

enter image description here

I defined a command \FillCube with an optional argument taking values between 1 and 0, controlling up to where the cube is filled. The default is 1, meaning full (0 means empty).

The code:

\documentclass[varwidth=50cm,border=5pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\Depth}{2}
\newcommand{\Height}{2}
\newcommand{\Width}{2}

\newcommand\FillCube[1][1]{
\coordinate (O) at (0,0,0);
\coordinate (A) at (0,\Width,0);
\coordinate (B) at (0,\Width,\Height);
\coordinate (C) at (0,0,\Height);
\coordinate (D) at (\Depth,0,0);
\coordinate (E) at (\Depth,\Width,0);
\coordinate (F) at (\Depth,\Width,\Height);
\coordinate (G) at (\Depth,0,\Height);
\ifx#10\relax
\else
\draw[fill=blue!40] (O) -- (C) -- (G) -- (D) -- cycle;
\fi
\draw[fill=gray!20,opacity=0.5] (O) -- (C) -- (G) -- (D) -- cycle;
\draw[fill=gray!20] (O) -- (A) -- (E) -- (D) -- cycle;
\draw[fill=blue!40] (O) -- ( $ (O)!#1!(A) $ ) -- ( $ (D)!#1!(E) $ ) -- (D) -- cycle;
\draw[fill=gray!20] (O) -- (A) -- (B) -- (C) -- cycle;
\draw[fill=blue!40] (O) -- ( $ (O)!#1!(A) $ ) -- ( $ (C)!#1!(B) $ ) -- (C) -- cycle;
\draw[fill=gray!20,opacity=0.4] (D) -- (E) -- (F) -- (G) -- cycle;
\draw[fill=blue!40,opacity=0.4] (D) -- ( $ (D)!#1!(E) $ ) -- ( $ (G)!#1!(F) $ ) -- (G) -- cycle;
\draw[fill=gray!20,opacity=0.6] (C) -- (B) -- (F) -- (G) -- cycle;
\draw[fill=blue!40,opacity=0.6] (C) -- ( $ (C)!#1!(B) $ ) -- ( $ (G)!#1!(F) $ ) -- (G) -- cycle;
\if#10\relax
\else
\draw[fill=blue!40,opacity=0.6] ( $ (O)!#1!(A) $ ) -- ( $ (C)!#1!(B) $ ) -- ( $ (G)!#1!(F) $ ) -- ( $ (D)!#1!(E) $ ) -- cycle;
\fi
}
\begin{document}

\begin{tikzpicture}
\foreach[count=\xi] \Valor in {1,0.8,...,0.2,0}
{
\begin{scope}[xshift=\xi*3cm]
\FillCube[\Valor]
\end{scope}
}
\end{tikzpicture}\par\bigskip

\begin{tikzpicture}
\FillCube
\begin{scope}[xshift=3cm]
\FillCube[0.5]
\end{scope}
\begin{scope}[xshift=6cm]
\FillCube[0]
\end{scope}
\end{tikzpicture}

\end{document}

An animation:

enter image description here

The code for the animation:

\documentclass{beamer}
\usepackage{tikz}
\usetikzlibrary{calc}

\newcommand{\Depth}{2}
\newcommand{\Height}{2}
\newcommand{\Width}{2}

\newcommand<>\FillCube[1][1]{
\only#2{\coordinate (O) at (0,0,0);
\coordinate (A) at (0,\Width,0);
\coordinate (B) at (0,\Width,\Height);
\coordinate (C) at (0,0,\Height);
\coordinate (D) at (\Depth,0,0);
\coordinate (E) at (\Depth,\Width,0);
\coordinate (F) at (\Depth,\Width,\Height);
\coordinate (G) at (\Depth,0,\Height);
\ifx#10\relax
\else
\draw[fill=blue!40] (O) -- (C) -- (G) -- (D) -- cycle;
\fi
\draw[fill=gray!20,opacity=0.5] (O) -- (C) -- (G) -- (D) -- cycle;
\draw[fill=gray!20] (O) -- (A) -- (E) -- (D) -- cycle;
\draw[fill=blue!40] (O) -- ( $ (O)!#1!(A) $ ) -- ( $ (D)!#1!(E) $ ) -- (D) -- cycle;
\draw[fill=gray!20] (O) -- (A) -- (B) -- (C) -- cycle;
\draw[fill=blue!40] (O) -- ( $ (O)!#1!(A) $ ) -- ( $ (C)!#1!(B) $ ) -- (C) -- cycle;
\draw[fill=gray!20,opacity=0.4] (D) -- (E) -- (F) -- (G) -- cycle;
\draw[fill=blue!40,opacity=0.4] (D) -- ( $ (D)!#1!(E) $ ) -- ( $ (G)!#1!(F) $ ) -- (G) -- cycle;
\draw[fill=gray!20,opacity=0.6] (C) -- (B) -- (F) -- (G) -- cycle;
\draw[fill=blue!40,opacity=0.6] (C) -- ( $ (C)!#1!(B) $ ) -- ( $ (G)!#1!(F) $ ) -- (G) -- cycle;
\if#10\relax
\else
\draw[fill=blue!40,opacity=0.6] ( $ (O)!#1!(A) $ ) -- ( $ (C)!#1!(B) $ ) -- ( $ (G)!#1!(F) $ ) -- ( $ (D)!#1!(E) $ ) -- cycle;
\fi}
}

\begin{document}

\begin{frame}
\centering
\begin{tikzpicture}
\foreach[count=\xi] \Valor in {1,0.975,...,0.025,0}
  {\FillCube<\xi>[\Valor]}
\end{tikzpicture}
\end{frame}

\end{document}

On a terminal (using ImageMagick):

convert -verbose -delay 12 -loop 0 -density 300 a.pdf a.gif
  • 2
    Nice. The pictures are even prettier if the cube is standing on a vertex (long diagonal vertical) while being filled (not what the OP has asked for ...). – Ethan Bolker Jul 20 '15 at 23:55
  • @EthanBolker Thanks. Good idea. I'll give it a try tomorrow. – Gonzalo Medina Jul 21 '15 at 1:23
  • @EthanBolker Not very practical, though... – cfr Jul 21 '15 at 1:24
  • 2
    @cfr Since I'm a mathematician, that's the best reason to do it :-) – Gonzalo Medina Jul 21 '15 at 1:25
  • 1
    @WChargin It's beamer syntax allowing to define commands (there's a similar syntax for environments) which are overlay-aware. Further details in the beamer documentation under \newcommand. – Gonzalo Medina Jul 21 '15 at 17:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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