# Aggregation states in Tikz: draw random circles and connect them randomly

Hey TeX Stackexchange!

I have have a problem with a \tikzpicture in my beamer presentation about nuclear fusion. I want to show a graphic with all four aggregation states including plasma as the fourth state.

This is roughly what I am trying to achieve:

I already coded the first state with the solid molecule structure with a foreach loop but I don't know how to draw the random circles in the other three states. I could — and I do know how — draw all the single circles and connect them together by hand, which would take much effort and time.

But what I want is an automation that draws the circles at random coordinates within the square and also — in the second state — connects them randomly. In the plasma state I also don't want to draw each of the many particles by hand (with defining extra node styles). So I want an automation here too.

On this forum — which I find really helpful! — I couldn't find any fitting question. I do looked up on questions like "Distribute evenly and randomly circles" and "Filling specified area by random dots in TikZ" but the answers didn't work for my purposes (they even don't fulfill the requirements for the third state because the circles were positioned on nearly all over my slide).

So maybe someone of you can help me with this problem and many thanks in advance!

Here is the code I have so far:

\documentclass[12pt, aspectratio=169, xcolor=dvipsnames]{beamer}

\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{mathtools}
\usepackage{cmbright}
\pdfmapfile{=hfbright.map}
\renewcommand*\sfdefault{lmss}
\renewcommand*\ttdefault{lmtt}
\usepackage{tikz}
\usetikzlibrary{calc, shapes.arrows, decorations.pathreplacing}

\usetheme{Luebeck}

\definecolor{bBlue}{rgb}{0.2,0.2,0.7}
\colorlet{bgColor}{blue!12!black}
\colorlet{lightyel}{Goldenrod!50}

\setbeamercolor*{normal text}{fg=white, bg=bgColor}

\setbeamercolor{background canvas}{bg=bgColor}
\setbeamercolor{background canvas}{bg=black!90!blue}
\setbeamercolor{block body}{fg=white, bg=bBlue!30!black}

\setbeamercolor{item projected}{fg=white}
\setbeamercolor{section in toc}{fg=white, bg=bBlue}
{fg=bBlue!90, bg=bgColor}

%-----presentation-----%
\begin{document}

% many other slides...

\begin{frame}[t]{Plasma} \vspace{0.5cm}
\begin{itemize}[<+->] \pause
\item Atome überwinden magnetische Abstoßung $\Rightarrow$ viel Energie
\item \alert{Plasma} = 4. Aggregatzustand der Materie
\end{itemize}

\vfill

\pgfmathsetmacro{\length}{2.6}
\pgfmathsetseed{127}

\begin{center}
\begin{tikzpicture}
\begin{scope}[gray]
\fill[white] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Festkörper};

\foreach \x in {1,...,6} {
\foreach \y in {1,...,6} {
\fill[] (\x * 0.37, \y * 0.37) circle (\rad);
}
}
\draw[thick, step=0.37] (0.37, 0.37) grid (.37*6,.37*6);
\end{scope}

\begin{scope}[xshift=3.4cm, gray]
\fill[white] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Flüssigkeit};

%   \fillrandomly{\length - 0.4}{\length - 0.4}{\rad}{30}{0.37}{0.37}
\end{scope}

\begin{scope}[xshift=6.8cm, gray]
\fill[white] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Gas};

\end{scope}

\begin{scope}[xshift=10.2cm, gray]
\fill[white] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Plasma};

\end{scope}
\end{tikzpicture}
\end{center}

\vfill

\end{frame}

\end{document}


EDIT: Many thanks to @Schrödinger's cat for answering that quick. With some minor tweaks of his answer I updated the above code (it should work now without any errors):

\documentclass[12pt, aspectratio=169, xcolor=dvipsnames]{beamer}

\usepackage[utf8]{inputenc}
\usepackage[german]{babel}
\usepackage[T1]{fontenc}
\usepackage{amsmath}
\usepackage{amsfonts}
\usepackage{amssymb}
\usepackage{mathtools}
\usepackage{cmbright}
\pdfmapfile{=hfbright.map}
\renewcommand*\sfdefault{lmss}
\renewcommand*\ttdefault{lmtt}
\usepackage{tikz}
\usetikzlibrary{calc, shapes.arrows, decorations.pathreplacing}

\usetheme{Luebeck}

\definecolor{bBlue}{rgb}{0.2,0.2,0.7}
\colorlet{bgColor}{blue!12!black}
\colorlet{lightyel}{Goldenrod!50}

\setbeamercolor*{normal text}{fg=white, bg=bgColor}

\setbeamercolor{background canvas}{bg=bgColor}
\setbeamercolor{background canvas}{bg=black!90!blue}
\setbeamercolor{block body}{fg=white, bg=bBlue!30!black}

\setbeamercolor{item projected}{fg=white}
\setbeamercolor{section in toc}{fg=white, bg=bBlue}
{fg=bBlue!90, bg=bgColor}

%---- code from Schrödinger's cat -----%

\tikzset{pics/random chains/.style={code={
\tikzset{random chains/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/random chains/##1}}%
\pgfmathsetmacro\xlist{\pv{r}+rnd*(\pv{xmax}-2*\pv{r})}
\pgfmathsetmacro\ylist{\pv{r}+rnd*(\pv{ymax}-2*\pv{r})}
\draw [pic actions] (\xlist,\ylist) circle [radius=\pv{r}];
\foreach \XX in {1,...,\pv{n}}
{\pgfmathsetmacro\x{\pv{r}+rnd*(\pv{xmax}-2*\pv{r})}
\pgfmathsetmacro\y{\pv{r}+rnd*(\pv{ymax}-2*\pv{r})}
\xdef\collision{0}
\foreach \element [count=\YY starting from 0] in \xlist{
\pgfmathsetmacro\checkdistance{sqrt(({\xlist}[\YY]-(\x))^2+({\ylist}[\YY]-(\y))^2)}
\ifdim\checkdistance pt<\pv{R} pt
\xdef\collision{1}
\breakforeach
\fi
}
\ifnum\collision=0
\foreach \element [count=\YY starting from 0] in \xlist{
\pgfmathsetmacro\checkdistance{sqrt(({\xlist}[\YY]-(\x))^2+({\ylist}[\YY]-(\y))^2)}
\ifdim\checkdistance pt<\pv{Rcrit} pt
\draw[shorten >=\pv{r}*1cm,shorten <=\pv{r}*1cm] (\x,\y) --({{\xlist}[\YY]},{{\ylist}[\YY]});
\fi
}
\xdef\xlist{\xlist,\x}
\xdef\ylist{\ylist,\y}
\fi
}
}
},
random chains/.cd,n/.initial=50,% tries
xmax/.initial=2.6,% width
ymax/.initial=2.6,% height
R/.initial=0.45,% grace distance, should be greater than 2*r
Rcrit/.initial=0.6,% critical distance, closer objects will be connected
/tikz/molecules/.cd,
1/.style={draw=gray},
2/.style={}
}

%----- presentation -----%
\begin{document}

% many other slides...

\begin{frame}[t]{Plasma}

\vfill

\pgfmathsetmacro{\length}{2.6}

\begin{center}
\begin{tikzpicture}
\begin{scope}[gray]
\fill[white] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Festkörper};

\foreach \x in {1,...,6} {
\foreach \y in {1,...,6} {
\fill[] (\x * 0.37, \y * 0.37) circle (\rad);
}
}
\draw[thick, step=0.37] (0.37, 0.37) grid (.37*6,.37*6);
\end{scope}

\path (0,3.5); % simple way to add some distance
\pgfmathsetseed{496}

\begin{scope}[xshift=3.4cm]
\draw[fill=white] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Flüssigkeit};
\draw[] (0,0) pic[fill=gray,draw=gray]{random chains} rectangle ++(\length,\length);
\end{scope}

\begin{scope}[xshift=6.8cm]
\draw[fill=white] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Gas};
\draw (0,0) pic[fill=gray]{random chains={Rcrit=0.3}} rectangle ++(\length,\length);
\end{scope}

\begin{scope}[xshift=10.2cm]
\draw[fill=white,] (0,0) rectangle (\length,\length);
\node[white, above] at (\length / 2, \length) {\small Plasma};
\draw (0,0) pic[fill=gray]{random chains={n=80,Rcrit=0.3}} rectangle ++(\length,\length);

\foreach \X [count=\Z starting from 0] in \xlist {
\pgfmathsetmacro{\Y}{{\ylist}[\Z]}
\pgfmathrandominteger{\rin}{0}{4}
\ifcase\rin
\or
\draw (\X,\Y)[fill=cyan] circle[radius=\rad] node[scale=0.8]{$+$};
\or
\draw (\X,\Y)[fill=green!70!black] circle[radius=\rad] node[scale=0.8]{$-$};
\or
\draw (\X,\Y)[fill=yellow] circle[radius=\rad] node[scale=0.8]{$*$};
\or
node[fill=red,draw,inner sep=0.3pt,circle,scale=0.4]{$e^-$};
\fi
}
\end{scope}
\end{tikzpicture}
\end{center}

\vfill

\end{frame}

\end{document}


• My compliments for the question. Peraphs I have added many packages. \usepackage{amsmath} \usepackage{amsfonts} \usepackage{amssymb} \usepackage{mathtools}. You can put only \usepackage{mathtools} and \usepackage{amssymb}. – Sebastiano Jan 8 '20 at 22:11
• This can help you: tex.stackexchange.com/questions/87497/… – Raoul Kessels Jan 8 '20 at 22:15
• @RaoulKessels I already looked at this question — you may see the comment in my code with \fillrandomly — but this didn't work in my purpose because the circles are drawn widely outside the white rectangle. I even added two new parameters to this command for the starting point for the rectangle but this also didn't work. – LaTeXUser365 Jan 8 '20 at 22:21
• If you use the answer in that question, you just have to increase the rectangle size with the radius of the circles to have them all inside: \draw (-#3,-#3) rectangle (#1+#3,#2+#3); instead of \draw (0,0) rectangle (#1,#2); (at the beginning of the macro) – Raoul Kessels Jan 8 '20 at 22:34
• @RaoulKessels I will check this tomorrow evening ;-) . Thank you for your answer! – LaTeXUser365 Jan 8 '20 at 23:02

This is based on Jake's answer but comes with a twist: if the circles are closer than a critical value, Rcrit, they get connected. It also implements the code in form of a pic. The parameters are given by pgf keys. They are the radius of the circles r, the minimal distance R (which obviously needs to be at least twice the radius), Rcrit, the number of attempt to place a circle, n, which controls the number of circles, and the box dimensions xmax and ymax.

\documentclass{beamer}
\usepackage{tikz}
\tikzset{pics/random chains/.style={code={
\tikzset{random chains/.cd,#1}
\def\pv##1{\pgfkeysvalueof{/tikz/random chains/##1}}%
\pgfmathsetmacro\xlist{\pv{r}+rnd*(\pv{xmax}-2*\pv{r})}
\pgfmathsetmacro\ylist{\pv{r}+rnd*(\pv{ymax}-2*\pv{r})}
\draw [pic actions] (\xlist,\ylist) circle [radius=\pv{r}];
\foreach \XX in {1,...,\pv{n}}
{\pgfmathsetmacro\x{\pv{r}+rnd*(\pv{xmax}-2*\pv{r})}
\pgfmathsetmacro\y{\pv{r}+rnd*(\pv{ymax}-2*\pv{r})}
\xdef\collision{0}
\foreach \element [count=\YY starting from 0] in \xlist{
\pgfmathsetmacro\checkdistance{sqrt(({\xlist}[\YY]-(\x))^2+({\ylist}[\YY]-(\y))^2)}
\ifdim\checkdistance pt<\pv{R} pt
\xdef\collision{1}
\breakforeach
\fi
}
\ifnum\collision=0
\foreach \element [count=\YY starting from 0] in \xlist{
\pgfmathsetmacro\checkdistance{sqrt(({\xlist}[\YY]-(\x))^2+({\ylist}[\YY]-(\y))^2)}
\ifdim\checkdistance pt<\pv{Rcrit} pt
\draw[shorten >=\pv{r}*1cm,shorten <=\pv{r}*1cm] (\x,\y) --({{\xlist}[\YY]},{{\ylist}[\YY]});
\fi
}
\xdef\xlist{\xlist,\x}
\xdef\ylist{\ylist,\y}
\fi
}
}
},
random chains/.cd,n/.initial=50,% tries
xmax/.initial=3,% width
ymax/.initial=3,% height
R/.initial=0.45,% grace distance, should be greater than 2*r
Rcrit/.initial=0.6,% critical distance, closer objects will be connected
/tikz/molecules/.cd,
1/.style={draw},
2/.style={}
}

\begin{document}

\begin{frame}[t]
\frametitle{Random chains}
\centering
\begin{tikzpicture}
\path (0,3.5); % simple way to add some distance
\pgfmathsetseed{496}
\draw (0,0) pic[fill=gray!60]{random chains} rectangle ++(3,3)
(3.5,0) pic[fill=gray!60]{random chains={Rcrit=0.3}} rectangle ++(3,3);
\begin{scope}[xshift=7cm]
\draw  pic[fill=gray!60]{random chains={n=80,Rcrit=0.3}} rectangle ++(3,3);
\foreach \X [count=\Z starting from 0] in \xlist
{\pgfmathsetmacro{\Y}{{\ylist}[\Z]}
\pgfmathrandominteger{\rin}{0}{4}
\ifcase\rin
\or
\draw (\X,\Y)[fill=cyan] circle[radius=0.15cm] node[scale=0.8]{$+$};
\or
\draw (\X,\Y)[fill=green!70!black] circle[radius=0.15cm] node[scale=0.8]{$-$};
\or
\draw (\X,\Y)[fill=yellow] circle[radius=0.15cm] node[scale=0.8]{$*$};
\or
node[fill=red,draw,inner sep=0.3pt,circle,scale=0.4]{$e^-$};
\fi}
\end{scope}
\end{tikzpicture}
\end{frame}
\end{document}


If you want to have more circles, decrease R, if you want less, increase it. If you want more connections, increase Rcrit, if you make it smaller than R, there will be none, as you see in the middle and right inlays.

With the same preamble

\begin{frame}[t]
\frametitle{Random chains}
\centering
\begin{tikzpicture}
\pgfmathsetseed{496}
\draw foreach \X in {0,3.5,7}
{foreach \Y in {0,-3.5}
{ (\X,\Y) pic[fill=gray!60]{random chains} rectangle ++(3,3)}};
\end{tikzpicture}
\end{frame}


produces

I did not have the passion to embed this in your document (also because it is neither minimal nor working, at least on my machine). Yet you should be able to add this to any working beamer document that loads tikz.

• First of all: Many thanks for your answer and the effort! You said that you couldn't get my code running. I think you may have the problem because I only put the packages in the preamble in the code above and forgot to put the code for the command visible on. I'll now added the whole preamble to my code above so that it should be working. – LaTeXUser365 Jan 9 '20 at 16:55
• @LaTeXUser365 Nope, I get errors like ! Package filehook Error: Detected 'scrlfile' package with unknown definition o f \InputIfFileExists. Use the 'force' option of 'filehook' to overwrite it... Also you seem to have copied parts of my answer to the question. This may make it very hard for others to understand what's going on since not it seems that my answer only repeats what you already have. Please make the code as minimal as possible and try to avoid merging in stuff from answers you get. You can always ask a new question, in which you can use codes from earlier answers. – user194703 Jan 9 '20 at 17:02
• Yeah, I'm sorry for that! Right now I am trying to implement your code in my presentation. It worked quite well. I only have to make some minor tweaks like the rectangle fill and the sections over those. When I'm finished I will update my whole code so that everybody can run it without any problems. But your answer was exactly what I was looking for! – LaTeXUser365 Jan 9 '20 at 17:18