6

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: enter image description here 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
6

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}

enter image description here

  • 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
  • 2
    @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. – user121799 Dec 16 '18 at 14:09

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.