Dynamische Füllhöhe eines Glases

Meine ersten Schritte in Foren habe ich vor ungefähr 5 1/2 Jahren auf dem Matheplaneten gemacht. In einer meiner ersten Antworten sollte damals ein Befehl definiert werden, mit dem ein unterschiedlich hoch gefülltes Wasserglas gezeichnet werden kann und der deshalb die relative Füllhöhe, also einen Wert zwischen 0 und 1, als Argument erwartet:

\Glas{<relative fuellhoehe>}

Der Pfad für das leere Glas war bereits vorgegeben:

\draw[very thick] (0,2) — (0.25,0) — (1.5,0) — (1.75,2);

glasleer

Zur besseren Übersicht habe ich hier ein Gitternetz (Linienabstand: 0.25 cm) darunter gelegt und den Koordinatenursprung markiert.

Damaliger Lösungsvorschlag:

\documentclass{scrartcl}
\usepackage{tikz}
\newcommand{\Glas}[1]{%
 \begin{tikzpicture}%
  \clip(0,2) -- (0.25,0) -- (1.5,0) -- (1.75,2)--cycle;
  \fill[blue!50!black] (0,0)rectangle(1.75,2*#1);
  \draw[very thick] (0,2) -- (0.25,0) -- (1.5,0) -- (1.75,2);
 \end{tikzpicture}%
}
\begin{document}
\Glas{1} %volles Glas
\Glas{0.5} %halbe Füllhöhe
\end{document}

Zunächst wird der Zeichenbereich mit \clip auf die Fläche des Glases beschnitten und anschließend ein Rechteck mit der oberen Glasbreite als Breite und dem Produkt von relativer Füllhöhe (Argument von \Glas) und Glashöhe als Höhe dunkelblau gefüllt. Durch das vorangegangene Beschneiden ist automatisch nur der gefüllte Teil des Glases sichtbar. Das Glas selbst kann erst ganz zum Schluss gezeichnet werden, damit es nicht von der Füllung verdeckt wird.

fuellhoehe_alt

 

Da der Pfad nur aus geraden Strecken besteht, könnte man das gewünschte – wie so oft bei TikZ – auch anders erreichen. Aber die Variante  mit dem Beschneiden des Zeichenbereiches hat den Vorteil, dass sie auch funktioniert, wenn das Glas keinen geraden Rand mehr hat.

An meinem Code von damals stört mich allerdings, dass ich den Pfad mehrmals angegeben habe. Deshalb ändere ich jetzt nicht nur die Form, sondern definiere mir gleich noch einen eigenen Befehl für den Pfad:

\newcommand\glasrand{(0,2) to[out=-60,in=140] (0.5,0) --
                     (1,0) to[out=40,in=240] (1.5,2)}

glasleer_neu

Damit ich auch beim Füllen keine Koordinaten angeben muss, die ich ja ändern müsste, wenn das Glas eine andere Form bekommt, verwende ich für das Füllen den Knoten current bounding box mit den Ankern south west und north east, wobei ich letzteren entsprechend der relativen Füllhöhe skaliere. Und weil es schöner aussieht, wird das Wasser heller gezeichnet und bekommt noch eine Schattierung.

\documentclass[margin=5mm,varwidth]{standalone}
\usepackage{tikz}
\newcommand\glasrand{(0,2) to[out=-60,in=140] (0.5,0) --
                     (1,0) to[out=40,in=240] (1.5,2)}
\newcommand{\Glas}[2][]{%
  \begin{tikzpicture}[#1]%
    \clip\glasrand;
    \fill[shade,top color=blue!80!green!10,bottom color=blue!60!green!50]
      (current bounding box.south west)
      rectangle([yscale=#2]current bounding box.north east);
    \draw[very thick,blue!40!black]\glasrand;
  \end{tikzpicture}%
}
\begin{document}
\Glas{1}
\Glas{0.5}
\end{document}

Ergebnis:

fuellhoehe_neu

Mit einer \foreach Schleife

\foreach \i in {0,...,10}{\Glas[scale=.5]{1-\i/10}\ }

kann ich mir auch gleich eine ganze Serie unterschiedlich gefüllter Gläser ausgeben lassen, die ich hier über das optionale Argument von \Glas skaliere.

fuellhoehe_neu_serie

Nachtrag: Änderungsmöglichkeiten für die Glasform

Da der Rand des Glases in dem Makro \glasrand gespeichert ist, kann man diesen mit Hilfe von \renewcommand jederzeit ändern. Nimmt man die Änderung innerhalb einer Gruppe, dann wirkt sie nur lokal.

Möchte man dagegen viele verschieden geformte Gläser zeichnen, kann es sinnvoller sein, den Pfad als weiteres Argument an den Befehl \Glas zu übergeben. Also

\newcommand{\Glas}[3][]{%
   \begin{tikzpicture}[#1]%
     \clip#3;
     \fill[shade,top color=blue!80!green!10,bottom color=blue!60!green!50]
       (current bounding box.south west)
       rectangle([yscale=#2]current bounding box.north east);
     \draw[very thick,blue!40!black]#3;
   \end{tikzpicture}%
}

und dann

\Glas{0.4}{%
  (0,2) to[out=-60,in=140] (0.5,0) -- (1,0) to[out=40,in=240] (1.5,2)}

Posted

in

,

by

Tags:

Comments

2 responses to “Dynamische Füllhöhe eines Glases”

  1. Stefan

    Sehr schön erklärt! Die Reihenfolge clip / fill / draw merke ich mir gleich als geschickten Weg. Kann man eigentlich \glasrand auch bei der ersten Verwendung als path benennen und weiter verwenden, alternativ zur Makro-Definition?

  2. Elke

    Ich habe oben noch was zu den Änderungsmöglichkeiten für den \glasrand ergänzt.