8

I want to draw some schematic representations of salts for educational purposes. The figure shows a example which can be generated with the metapost code below. I would like to improve the draws in two ways: first) round the corners of the rectangles; second) improve the triangular slots i.e. the interaction zones (better alignment and other didactic improvements)

The code can generate every kind of salt: Salt(anionCharge, cationCharge, anionName, cationName);

enter image description here

\starttext

\startalignment[middle]
\dontleavehmode
\startMPcode
vardef Ionic (expr p,  n, w, o) = 
pair vec ; path pat;
 if o==1:
 pat := for i=1 upto n: (w,i)--(w,i+.2)--(w/2,i+.35)--(w, i+.60)--endfor(w,n+.8)--(w/2-.2,n+.8)--(w/2-.2,1)--cycle;
else:
 pat := for i=1 upto n: (w,i)--(w,i+.2)--(w/2,i+.35)--(w, i+.60)--endfor(w,n+.8)--(w+w/2+.2,n+.8)--(w+w/2+.2,1)--cycle;
fi;
 pat xscaled 40 yscaled 40
enddef;

def Salt(expr anionCharge, cationCharge, anionName, cationName) =
 path catiao, aniao;
 numeric ania, catia;
 ania := anionCharge; catia := cationCharge;
 catiao := Ionic((0,0),catia,1,1);
   for i=1 upto ania:
      draw catiao shifted (0,(i-1)*40*catia) withpen pencircle scaled 2pt withcolor red;
      fill catiao shifted (0,(i-1)*40*catia) withcolor 0.7white;
      label.lft(cationName, (0,i*40*catia));
   endfor;
 aniao := Ionic((0,0),ania,1,0);
   for i=1 upto catia:
      draw aniao shifted (10,(i-1)*40*ania) withpen pencircle scaled 2pt withcolor blue;
      fill aniao shifted (10,(i-1)*40*ania) withcolor .9white;
      label.rt(anionName, (85,i*40*ania));
   endfor;
enddef;

Salt(3,2,btex PO$_4^{3-}$ etex, btex Ca$^{2+}$ etex);
\stopMPcode
\stopalignment


\stoptext
  • I know veeery different kind of salts. – percusse Nov 16 '15 at 23:22
  • Nice for you. For me, I'm glad if my students write well the structure of few salts. – Jorge Nov 16 '15 at 23:40
8

New Answer

Actually I prefer circle over rectangle

\tikzset{
    c/.style={violet},
    a/.style={olive},
    er/.store in=\er,er=.2,
    nodes={white,font=\Huge}
}
\def\msm#1#2{\pgfmathsetmacro#1{#2}\xdef#1{#1}}
\makeatletter
\def\salt{\pgfutil@ifnextchar[{\saltopt}{\saltopt[]}}
\def\saltopt[#1]#2^#3+#4Å#5^#6-#7Å{{
    \tikzset{#1,#2/.try,#5/.try}
    \msm\cc{max(#3.0,1)}\msm\ac{max(#6.0,1)}
    \msm\tt{\cc*\ac/gcd(\cc,\ac)}\msm\htt{floor(\tt/2)+1}
    \msm\cn{\tt/\cc}\msm\an{\tt/\ac}
    \msm\cr{#4}\msm\ar{#7}\msm\tr{\ar+\cr}
    % prepare center ions, four cases
    \ifodd\an\ifodd\cn % both odd
        \xdef\cx{-\cr}\xdef\cy{0}\xdef\ax{\ar}\xdef\ay{0}
        \fill[c](\cx,\cy)circle(\cr)node(C0){$\mathrm{#2}^{#3+}$};
        \fill[a](\ax,\ay)circle(\ar)node(A0){$\mathrm{#5}^{#6-}$};
    \else % anion number odd
        \msm\cx{\ar-sqrt(\tr*\tr-\cr*\cr)}\msm\cy{\cr}\xdef\ax{\ar}\xdef\ay{0}
        \fill[c](\cx,\cy)circle(\cr)node(C+0){$\mathrm{#2}^{#3+}$}(\cx,-\cy)circle(\cr)node(C-0){$\mathrm{#2}^{#3+}$};
        \fill[a](\ax,\ay)circle(\ar)node(A0){$\mathrm{#5}^{#6-}$};
    \fi\else % cation number odd
        \xdef\cx{-\cr}\xdef\cy{0}\msm\ax{sqrt(\tr*\tr-\ar*\ar)-\cr}\msm\ay{\ar}
        \fill[c](\cx,\cy)circle(\cr)node(C0){$\mathrm{#2}^{#3+}$};
        \fill[a](\ax,\ay)circle(\ar)node(A+0){$\mathrm{#5}^{#6-}$}(\ax,-\ay)circle(\ar)node(A-0){$\mathrm{#5}^{#6-}$};
    \fi
    % draw ions and electrons
    \xdef\ao{0}\xdef\co{0}\xdef\eo{0}
    \foreach\e in{\htt,...,\tt}{
        \msm\am{mod(\e,\ac)}\msm\cm{mod(\e,\cc)}
        % need new electron
            \msm\para{\ar+(2*\eo+1)*\er}
            \msm\ex{\ax+\para*(\cx-\ax)/\tr}
            \msm\ey{\ay+\para*(\cy-\ay)/\tr}
            \msm\eo{int(\eo+1)}
            \ifdim\ey pt=0pt
                \fill[a](\ex,\ey)circle(\er)node(e00\eo){};
                \ifodd\tt\ifnum\eo>1
                    \msm\eo{int(\eo+1)}
                    \fill[a](\ex-2*\er,\ey)circle(\er)node(e00\eo){};
                \fi\else
                    \msm\eo{int(\eo+1)}
                    \fill[a](\ex-2*\er,\ey)circle(\er)node(e00\eo){};
                \fi
            \else
                \fill[a](\ex,\ey)circle(\er)node(e+\ao+\co+\eo){}(\ex,-\ey)circle(\er)node(e-\ao-\co-\eo){};
            \fi
        \ifdim\e pt<\tt pt
        \ifdim\am pt=0pt % need new anion
            \msm\para{2*\ar*\ar/\tr}
            \msm\perp{sqrt(4*\ar*\ar-\para*\para)}
            \msm\axnew{\ax+(\para*(\cx-\ax)+\perp*(\cy-\ay))/\tr}
            \msm\aynew{\ay+(\para*(\cy-\ay)+\perp*(\ax-\cx))/\tr}
            \xdef\ax{\axnew}\xdef\ay{\aynew}
            \msm\ao{int(\ao+1)}\xdef\eo{0}
            \fill[a](\ax,\ay)circle(\ar)node(A+\ao){$\mathrm{#5}^{#6-}$}(\ax,-\ay)circle(\ar)node(A-\ao){$\mathrm{#5}^{#6-}$};
        \else\ifdim\cm pt=0 pt % need new cation
            \msm\para{2*\cr*\cr/\tr}
            \msm\perp{sqrt(4*\cr*\cr-\para*\para)}
            \msm\cxnew{\cx+(\para*(\ax-\cx)+\perp*(\cy-\ay))/\tr}
            \msm\cynew{\cy+(\para*(\ay-\cy)+\perp*(\ax-\cx))/\tr}
            \xdef\cx{\cxnew}\xdef\cy{\cynew}
            \msm\co{int(\co+1)}\xdef\eo{0}
            \fill[c](\cx,\cy)circle(\cr)node(C+\co){$\mathrm{#2}^{#3+}$}(\cx,-\cy)circle(\cr)node(C-\co){$\mathrm{#2}^{#3+}$};
        \fi\fi\fi
    }
}}
\tikz{\salt Xk^ +2Å Cd^ -3Å}
\tikz{\salt Xk^2+2Å Cd^2-3Å}
\tikz{\salt Xk^3+2Å Cd^3-3Å}

\tikz{\salt Xk^1+2Å Cd^2-3Å}
\tikz{\salt Xk^2+2Å Cd^4-3Å}
\tikz{\salt Xk^3+2Å Cd^6-3Å}

\tikz{\salt Xk^ +2Å Cd^3-3Å}
\tikz{\salt Xk^ +2Å Cd^4-3Å}
\tikz{\salt Xk^ +2Å Cd^5-3Å}

\tikz{\salt Xk^2+2Å Cd^3-3Å}
\tikz{\salt Xk^2+2Å Cd^5-3Å}
\tikz{\salt Xk^2+2Å Cd^7-3Å}

Collection of salts

\tikz{
    \salt                            Xk^2+3Å Cd^ -2Å
    \salt[shift={(12,0)}]            Xk^4+3Å Cd^3-2Å
    \salt[shift={(-4,15)},rotate=-60]Xk^6+3Å Cd^5-2Å
    \salt[shift={(-6,-18)},rotate=60]Xk^8+3Å Cd^7-2Å
}

A huge salt

\tikz{\salt[rotate=90]Xk^29+12Å Cd^12-5Å}


The canonical way to adjust the size of ions is to specify it directly in

\salt[er=.2]Xk^29+12Å Cd^12-5Å

Where 12Å and is then translated to 12cm and 5cm. Å comes from angstrom, as you probably had guessed it. To adjust the size of electron, pass er=.2 in the option.

Since I added an optional argument to \salt, you can pass any TikZ styles to it. As shown above it could be shift= and rotate. It could also be scale=, c/.style= or color/font specification.

You may, in addition, add \tikzset{Xk/.style={c/.style=black}} so that every time Xk is drawn, it is colored black.


Old Answer

Like this?

\documentclass[tikz,border=9]{standalone}
\begin{document}
    \def\salt#1^#2+#3^#4-{
        \pgfmathsetmacro\cationcharge{max(0#2,1)}
        \pgfmathsetmacro\anioncharge{max(0#4,1)}
        \pgfmathsetmacro\totaltransfer{\cationcharge*\anioncharge/gcd(\cationcharge,\anioncharge)}
        \pgfmathsetmacro\halftransfer{max(\totaltransfer/2,2)}
        \pgfmathsetmacro\anionnumber{\totaltransfer/\anioncharge}
        \pgfmathsetmacro\cationnumber{\totaltransfer/\cationcharge}
        \pgfmathsetmacro\w{.1}
        \pgfmathsetmacro\x{.1}
        \pgfmathsetmacro\y{.2}
        \pgfmathsetmacro\z{.5}
        \tikz{
            % draw anion
            \foreach\c in{1,...,\cationnumber}
                \fill[rounded corners,yellow](-\w,\c*\cationcharge)+(0,-\x)rectangle node[black]{$\mathrm{#1}^{#2+}$}+(-\halftransfer,-\cationcharge+\x);
            % draw cation
            \foreach\a in{1,...,\anionnumber}
                \fill[rounded corners,lime](\w,\a*\anioncharge)+(0,-\x)rectangle node[black]{$\mathrm{#3}^{#4-}$}+(\halftransfer,-\anioncharge+\x);
            % draw transfer
            \foreach\e in{1,...,\totaltransfer}{
                \fill[white](-\w,\e-.5)+(0,\y)--+(-\z,0)--+(0,-\y);
                \fill[lime](\w,\e-.5)+(0,\y)--+(-\z,0)--+(0,-\y);
            }
        }
    }
    \salt Na^+Cl^-
    \salt Ca^2+Cl^-
    \salt Ca^2+SO_4^2-
    \salt Ca^2+PO_4^3-

Or this

\def\salt#1^#2+#3^#4-{
    \pgfmathsetmacro\cationcharge{max(0#2,1)}
    \pgfmathsetmacro\anioncharge{max(0#4,1)}
    \pgfmathsetmacro\totaltransfer{\cationcharge*\anioncharge/gcd(\cationcharge,\anioncharge)}
    \pgfmathsetmacro\halftransfer{max(\totaltransfer/2,2)}
    \pgfmathsetmacro\anionnumber{\totaltransfer/\anioncharge}
    \pgfmathsetmacro\cationnumber{\totaltransfer/\cationcharge}
    \pgfmathsetmacro\w{.1}
    \pgfmathsetmacro\x{.1}
    \pgfmathsetmacro\y{.1}
    \pgfmathsetmacro\z{.2}
    \tikz{
        % draw anion
        \foreach\c in{1,...,\cationnumber}
            \fill[rounded corners,yellow](-\w,\c*\cationcharge)+(0,-\x)rectangle node[black]{$\mathrm{#1}^{#2+}$}+(-\halftransfer,-\cationcharge+\x);
        % draw transfer
        \foreach\e in{1,...,\totaltransfer}{
            \fill[white](-\w,\e-.5)+(-\y,0)circle(\z);
            \fill[lime](\w,\e-.5)+(-\y,0)circle(\z);
        }
        % draw cation
        \foreach\a in{1,...,\anionnumber}
            \fill[rounded corners,lime](\w,\a*\anioncharge)+(0,-\x)rectangle node[black]{$\mathrm{#3}^{#4-}$}+(\halftransfer,-\anioncharge+\x);
    }
}
\salt Na^+Cl^-
\salt Ca^2+Cl^-
\salt Ca^2+SO_4^2-
\salt Ca^2+PO_4^3-
  • I would like to add some emotional content to each ion to improve the memory (Papez circuit). Perhaps adding a specific background image to each ion representation. In this case the salt function call should be \salt Na^+Cl- NaImage ClImage. – Jorge Nov 17 '15 at 14:05
  • @Jorge Well, If the image of element Xy is always XyImage.png then you can replace node{$\mathrm{#1}^{#2+}$} by node{\includegraphics{#1.png}}. No need the fifth and sixth arguments. – Symbol 1 Nov 17 '15 at 14:16
  • Thanks again. I found a little bug when a call \salt Ca^2+SO_4^2-. In this call tikz draw two calcium sulphate molecules. I think that the \totaltransfer should be the Least Common Multiple and not the product of the anion and cation valences. – Jorge Nov 17 '15 at 21:20
  • @Jorge I forgot most of the details... But is not it possible to have \totaltransfer a multiple of the lcm? – Symbol 1 Nov 18 '15 at 1:33
  • The circles are a great idea. Amazing solution. Thanks again. – Jorge Nov 18 '15 at 17:46

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.