# How to stop overlap between different circles randomly generated

This question is similar to this question tikz: Distribute evenly and randomly circles (which is also where I got some of the code for this TiKz picture) but is different. I wish to draw multiple circles that do not overlap but some of these circles are different. Currently this is my code:

\documentclass{article}
\usepackage{tikz}
\usepackage[margin=0.5in]{geometry}
\newcommand{\fillrandomly}[5]{
\xdef\xlist{4}
\xdef\ylist{4}
\pgfmathsetmacro\diametersqr{(#3*2)^2}
\foreach \i in {1,...,#4}{
\foreach \k in {1,...,20}{
\pgfmathsetmacro\x{rnd*#1}
\pgfmathsetmacro\y{rnd*#2}
\xdef\collision{0}
\foreach \element [count=\i] in \xlist{
\pgfmathtruncatemacro\j{\i-1}
\pgfmathsetmacro\checkdistancesqr{ ( ({\xlist}[\j]-(\x))^2 + ({\ylist}[\j]-(\y))^2 ) }
\ifdim\checkdistancesqr pt<\diametersqr pt
\xdef\collision{1}
\breakforeach
\fi
}
\ifnum\collision=0
\xdef\xlist{\xlist,\x}
\xdef\ylist{\ylist,\y}
\draw (\x,\y) circle [radius=#3] node[anchor=center] {#5};
\breakforeach
\fi
}
}
}
\begin{document}
\begin{figure}
\begin{tikzpicture}
\begin{scope}[xshift=0.2cm,yshift=0.2cm]
\fillrandomly{3.6}{3.8}{0.15}{12}{$-$}
\fillrandomly{3.6}{3.8}{0.15}{12}{$+$}
\end{scope}
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {concentrated strong acid};

\begin{scope}[xshift=5cm]
\foreach \X in {1,...,3}
{\draw (2+1.8*rand,2+1.9*rand) circle (0.15) node[anchor=center] {$+$};
\draw (2+1.8*rand,2+1.9*rand) circle (0.15) node[anchor=center] {$-$};}
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {dilute strong acid};
\end{scope}
\begin{scope}[xshift=10cm]
\begin{scope}[xshift=0.2cm,yshift=0.2cm]
\fillrandomly{3.6}{3.8}{0.15}{8}{$-$}
\fillrandomly{3.6}{3.8}{0.15}{8}{$+$}
\end{scope}
\foreach \X in {1,...,8}
{
\draw[fill=black!10]  (2+1.8*rand,2+1.9*rand) circle (0.15);
}
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {concentrated weak acid};
\end{scope}
\begin{scope}[xshift=15cm]
\foreach \X in {1,...,2}
{\draw (2+1.8*rand,2+1.9*rand) circle (0.15) node[anchor=center] {$+$};
\draw (2+1.8*rand,2+1.9*rand) circle (0.15) node[anchor=center] {$-$};}
\draw[fill=black!10]  (2+1.8*rand,2+1.9*rand) circle (0.15);
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {dilute weak acid};
\end{scope}
\draw[fill=black!10] (0,-1) circle (0.15) node[right=0.1cm] {Unionised};
\draw (0,-1.5) circle (0.15) node[anchor=center] {$+$} node[right=0.1cm] {Positive Ion};
\draw (0,-2) circle (0.15) node[anchor=center] {$-$} node[right=0.1cm] {Negative Ion};
\end{tikzpicture}
\vspace{-2cm}
\caption{Concentrated and dilute solutions of weak and strong acids}
\end{figure}
\end{document}


Which produces this image: I am unsure how to stop overlapping between the three different types of circles especially in the first and third beaker counting from the left. XeLaTeX answer please

• Lualatex ok?... – JPi Dec 16 '18 at 12:23
• Sorry I prefer XeLaTeX, forgot to mention – sab hoque Dec 16 '18 at 12:23

It is clear why this happens: you draw two or more independent samples, so if you say e.g.

\fillrandomly{3.6}{3.8}{0.15}{12}{$-$}
\fillrandomly{3.6}{3.8}{0.15}{12}{$+$}


the + ions do not know about the - ones. But it is very simple to fix it. Just make the reset of the collision list not part of the \fillrandomly, but do it whenever you start a new group. That is, I redefined \fillrandomly such that it does not reset the collision list, and added a command \resetlists that issues the reset. I also defined an ion style that gets changed along the way such that one can add the filled ions.

\documentclass{article}
\usepackage{tikz}
\usepackage[margin=0.5in]{geometry}
\newcommand{\resetlists}{\xdef\xlist{4}\xdef\ylist{4}}
\newcommand{\fillrandomly}[5]{
\pgfmathsetmacro\diametersqr{(#3*2)^2}
\foreach \i in {1,...,#4}{
\foreach \k in {1,...,20}{
\pgfmathsetmacro\x{rnd*#1}
\pgfmathsetmacro\y{rnd*#2}
\xdef\collision{0}
\foreach \element [count=\i] in \xlist{
\pgfmathtruncatemacro\j{\i-1}
\pgfmathsetmacro\checkdistancesqr{ ( ({\xlist}[\j]-(\x))^2 + ({\ylist}[\j]-(\y))^2 ) }
\ifdim\checkdistancesqr pt<\diametersqr pt
\xdef\collision{1}
\breakforeach
\fi
}
\ifnum\collision=0
\xdef\xlist{\xlist,\x}
\xdef\ylist{\ylist,\y}
\draw[ion] (\x,\y) circle [radius=#3] node[anchor=center] {#5};
\breakforeach
\fi
}
}
}
\begin{document}
\begin{figure}
\begin{tikzpicture}
\begin{scope}[xshift=0.2cm,yshift=0.2cm]
\resetlists
\tikzset{ion/.style={}}
\fillrandomly{3.6}{3.8}{0.15}{12}{$-$}
\fillrandomly{3.6}{3.8}{0.15}{12}{$+$}
\end{scope}
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {concentrated strong acid};

% 2
\begin{scope}[xshift=5cm]
\foreach \X in {1,...,3}
{\draw (2+1.8*rand,2+1.9*rand) circle (0.15) node[anchor=center] {$+$};
\draw (2+1.8*rand,2+1.9*rand) circle (0.15) node[anchor=center] {$-$};}
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {dilute strong acid};
\end{scope}

% 3
\begin{scope}[xshift=10cm]
\begin{scope}[xshift=0.2cm,yshift=0.2cm]
\resetlists
\tikzset{ion/.style={}}
\fillrandomly{3.6}{3.8}{0.15}{8}{$-$}
\fillrandomly{3.6}{3.8}{0.15}{8}{$+$}
\tikzset{ion/.style={fill=black!10}}
\fillrandomly{3.6}{3.8}{0.15}{8}{}
\end{scope}
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {concentrated weak acid};
\end{scope}

%4
\begin{scope}[xshift=15cm]
\begin{scope}[xshift=0.2cm,yshift=0.2cm]
\resetlists
\tikzset{ion/.style={}}
\fillrandomly{3.6}{3.8}{0.15}{2}{$-$}
\fillrandomly{3.6}{3.8}{0.15}{2}{$+$}
\tikzset{ion/.style={fill=black!10}}
\fillrandomly{3.6}{3.8}{0.15}{1}{}
\end{scope}
\draw (0,5) -- (0,1);
\draw (0,1) .. controls (0,0) and (0,0) .. (1,0);
\draw (1,0) -- (3,0);
\draw (3,0) .. controls (4,0) and (4,0) .. (4,1);
\draw (4,1) -- (4,5);
\draw[densely dashed] (0,5) .. controls (0,4.5) and (0,4.5) .. (0.5,4.5);
\draw[densely dashed] (0.5,4.5) -- (3.5,4.5);
\draw[densely dashed] (3.5,4.5) .. controls (4,4.5) and (4,4.5) .. (4,5);
\node[anchor=center] at (2,-0.5) {dilute weak acid};
\end{scope}
\draw[fill=black!10] (0,-1) circle (0.15) node[right=0.1cm] {Unionised};
\draw (0,-1.5) circle (0.15) node[anchor=center] {$+$} node[right=0.1cm] {Positive Ion};
\draw (0,-2) circle (0.15) node[anchor=center] {$-$} node[right=0.1cm] {Negative Ion};
\end{tikzpicture}
\vspace{-2cm}
\caption{Concentrated and dilute solutions of weak and strong acids}
\end{figure}
\end{document}


• I may have misunderstood something, but is the only thing that was changed was the addition of an ion style. I can't see where the cahnge was made to prevent the resetting of the list? I like to understand the code before I use it – sab hoque Dec 16 '18 at 14:04
• @sabhoque No, the original code has \xdef\xlist{4}\xdef\ylist{4} part of \fillrandomly. This resets the collision list, i.e. the list of previous positions of ions. Whenever a new ion is placed, \fillrandomly checks if the would-be ion overlaps with one of the previous ones. If not, the ion is drawn. All I did was not to reset the list automatically. So in the first example the + ions also know where the - ions were. I only reset the list when I switch to the next container. The ion style allows you to draw the shaded circles with \fillrandomly, too. – marmot Dec 16 '18 at 14:09