3

Using chemfig with the beamer class, I need to show the two "single bonds" of a double bond in different colors. It should be possible to change these colors for a given double bond on different slides, as well as for different double bonds in the same molecule.

\documentclass{beamer}
\usepackage{chemfig}
\begin{document}
\begin{frame}<1-4>{}
    \alt<1>{\def\blue{white}}{\def\blue{blue}}
    \alt<1-2>{\def\red{white}}{\def\red{red}}
    \alt<1-3>{\def\green{white}}{\def\green{green}}
    \chemfig[][scale=0.65]{OH-[::150](=[::-60]O)-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]=^[::60](-[::60,,,,\red]-[::-60,,,,\red]=^[::60,,,,\red](-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green])-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red])-[::-60]=^[::60](-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue])-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60]}
\end{frame}
\end{document}

enter image description here

I need that (starting from the right) the lower part of the first black double bond be red, the lower part of the second black double bond be blue and the right part of the red double bond be green. But on some slides, I need some of them (of the double bond halves) to be white (or better transparent – simply invisible), together with the molecule branches starting at them.

Does anyone know a hint?

Many thanks

Tomáš

1
  • Thanks Kurt for the editing. My apology for having found the editing help too late.
    – arecuk
    Sep 23, 2015 at 9:46

2 Answers 2

4

This feature is not hard coded in chemfig but with decorations, it becomes easy:

\documentclass{article}
\usepackage{chemfig}
\usetikzlibrary{decorations.markings}
\makeatletter
\tikzset{clrdbl/.style args={#1 and #2}{%
        draw=none,%
        decoration={%
            markings,%
            mark=at position 0 with {\coordinate (CFstart@) at (0,0);},
            mark=at position 1 with {%
                \draw[color=#1]([yshift=\CF@double@sep/2]CFstart@)--(0,\CF@double@sep/2);
                \draw[color=#2]([yshift=-\CF@double@sep/2]CFstart@)--(0,-\CF@double@sep/2);
                }
            },
        postaction={decorate}
    }
}
\makeatother
\begin{document}
\chemfig{A=B-[,,,,clrdbl=red and blue]C-[,,,,clrdbl=green and purple]D}
\end{document}

enter image description here

Edit: Here is another solution for any bond. It does not redefine anything in the chemfig code:

\documentclass{article}
\usepackage{chemfig}
\makeatletter
\tikzset{clrdbl/.code 2 args={\tikzset{color=#1}\global\CF@add@tocs\CF@current@bondstyle{,color=#2}}}
\makeatother
\begin{document}
\chemfig{A-[:-30]=^[:30,,,,clrdbl={red}{blue}]-[:-30]=^[:30,,,,clrdbl={green}{purple}]-[:-30]=^[:30]D}
\end{document}

enter image description here

2
  • Thanks for the answer. Unfortunately, it does not solve my problem. Your solution is good for bonds between atoms containing letters, but I need it in chains of bonds only. In such chains, I do not like the double bonds with the bond axis in between the two "single bonds", I prefer those shifted using =^ or =_. However, I like the way you work with parameterized styles and find your answer useful for me in this aspect.
    – arecuk
    Sep 23, 2015 at 10:02
  • The edited version is excellent, thank you! It does exactly what I needed. For completeness, I tried to use it also for triple bonds (not needed now), without success – I didn't find how to tell chemfig which one of the two side bonds should be colored with a given color. I originally wanted to resolve it and only then to react here, but I gave up for the moment. After two months, I do not remember everything exactly, so I'll report the code (hopefully) some time later.
    – arecuk
    Nov 20, 2015 at 11:25
0

OK, I found a solution that works for me. It seems to work with normal double bonds (=), shifted double bonds (=^ and =_) and even with triple bonds.

  1. First, we have to redefine three macros of the chemfig package.
    • We copy them (from chemfig.tex) to a file, let’s call it bondsredef.tex, which should be \input at some point after \usepackage{chemfig} but before the commands \enablebondjoin or \disablebondjoin, if you use them.
    • In the original, the macros are defined using the command \CF@def which rejects to define one macro more then once, so we need to use the simple \def instead.
    • For easier orientation, only the redefinition of the macros \CF@draw@bond and \CF@draw@axisbond@nojoin are shown in the code below, the \CF@draw@axisbond@join is just described.
    • What happens in the redefinitions? In all three macros, the macro \CF@draw@bond@i is used (directly or indirectly), which uses TiKZ to draw a bond. We tell to all its instances to use the styles left single bond, right single bond or axis single bond. To achieve this, we
      • modify the \CF@draw@bond definition by replacing \CF@draw@bond@i by \CF@draw@bond@i[left single bond] or by \CF@draw@bond@i[right single bond] as shown in the code. This solves the color change for the left and right parts of the normal double (and triple) bonds, as well as for the left or right part (the non-axial ones) of the double bonds shifted by =^ or =_.
      • modify the \CF@draw@axisbond@nojoin and \CF@draw@axisbond@join definitions by simply replacing all the instances of \CF@draw@bond@i by \CF@draw@bond@i[axis single bond]. This solves the color change for the axial part of shifted double bonds, as well as for the middle "single bond" of triple bonds (and for the real single bonds if you want).
      • define the styles left single bond, right single bond and axis single bond in the first line of our bondsredef.tex file as empty styles.
    • input the file as mentioned above. The commands \enablebondjoin or \disablebondjoin, if you use them, must occur after inputting the file, because they map the \CF@draw@axisbond macro to \CF@draw@axisbond@nojoin or \CF@draw@axisbond@join by means of \let. If this is not done after our redefinitions, \CF@draw@axisbond would remain mapped to the original macros as defined in chemfig.tex.
  2. Second, for double and triple bonds to be changed, we define the corresponding style(s) in the fifth optional argument of the bonds in our document. In beamer, to change the colors between different slides of a frame, we use macros like \red (or any name) instead of the color names like red. These macros are defined using the beamer macro \alt defining the color in dependence on the overlay specification.

Now, the code. First, the bondsredef.tex:

\tikzset{left single bond/.style={}}\tikzset{right single bond/.style={}}\tikzset{axis single bond/.style={}}
\makeatletter
\def\CF@draw@bond#1#2#3#4#5{% #1=type de liaison #2 et #3:nom de noeuds de d\'ebut et fin #4 et #5: contenu des atomes de d\'ebut et fin
    \CF@set@offset\CF@start@offset#4%
\CF@set@offset\CF@end@offset#5%
\let\CF@current@bondstyle\CF@bond@style
\unless\ifx\CF@current@tikz\@empty\CF@expadd@tocs\CF@current@bondstyle{\expandafter,\CF@current@tikz}\fi
\path(#2)--(#3)coordinate[pos=0](#2@)coordinate[pos=1](#3@);%
\CF@compute@nodevect{#2@}{#3@}%
\pgfmathparse{\CF@start@offset/\CF@len@vector}\let\CF@start@coeff\pgfmathresult
\pgfmathparse{1-\CF@end@offset/\CF@len@vector}\let\CF@end@coeff\pgfmathresult
\path(#2@)--(#3@)coordinate[pos=\CF@start@coeff](#2@@)coordinate[pos=\CF@end@coeff](#3@@);%
\unless\ifx\CF@movebond@name\@empty% on doit poser un noeud sur la liaison
    \path(#2@@)--(#3@@)coordinate[overlay,pos=\CF@movebond@coeff](\CF@movebond@name);
    \let\CF@movebond@name\@empty
\fi
\ifcase#1\relax
    \errmessage{Package \CF@package@name\space Error: unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}%
\or% 1 = liaison simple
    \CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe
\or% 2 = liaison double
    \ifCF@incycle
        \ifnum\CF@doublebond@type=\z@
            \let\CF@doublebond@type\@ne
        \fi
        \ifnum\CF@split@state>\z@
            \let\CF@doublebond@type\tw@
        \fi
        \pgfmathparse{\CF@double@sep*tan(180/\CF@cycle@num)}%
        \let\CF@doublebond@lengthcorrection\pgfmathresult
    \fi
    \ifcase\CF@doublebond@type
        \CF@create@normnodes{#2@@}{#3@@}{\CF@double@sep/2}{\CF@double@sep/2}%
        \CF@draw@bond@i[left single bond](#2@@1)--(#3@@1);
        \CF@draw@bond@i[right single bond](#2@@2)--(#3@@2);
        \let\CF@joinbond\z@
    \or
        \CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep
        \CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe\CF@draw@bond@i(#2@@)--(#3@@);
        \begingroup% ajuste \'eventuellement les longueurs des liaisons doubles
            \ifCF@incycle
                \ifdim\CF@start@offset=\z@
                    \CF@edefadd@tocs\CF@current@bondstyle{,shorten <=\CF@doublebond@lengthcorrection pt}%
                \fi
                \ifdim\CF@end@offset=\z@
                    \CF@edefadd@tocs\CF@current@bondstyle{,shorten >=\CF@doublebond@lengthcorrection pt}%
                \fi
            \fi
            \CF@draw@bond@i[left single bond](#2@@1)--(#3@@1);
        \endgroup
    \or
        \CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep
        \CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe\CF@draw@bond@i(#2@@)--(#3@@);
        \begingroup% ajuste \'eventuellement les longueurs des liaisons doubles
            \ifCF@incycle
                \ifdim\CF@start@offset=\z@
                    \CF@edefadd@tocs\CF@current@bondstyle{,shorten \ifnum\CF@split@state=\z@<=-\else>=\fi\CF@doublebond@lengthcorrection pt}%
                \fi
                \ifdim\CF@end@offset=\z@
                    \CF@edefadd@tocs\CF@current@bondstyle{,shorten \ifnum\CF@split@state=\z@>=-\else<=\fi\CF@doublebond@lengthcorrection pt}%
                \fi
            \fi
            \CF@draw@bond@i[right single bond](#2@@2)--(#3@@2);
        \endgroup
    \fi
\or% 3 = liaison triple
    \CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep
    \CF@draw@axisbond{#2}{#3}% trace la liaison simple dans l'axe\CF@draw@bond@i(#2@@)--(#3@@);
    \CF@draw@bond@i[left single bond](#2@@1)--(#3@@1);
    \CF@draw@bond@i[right single bond](#2@@2)--(#3@@2);
\or% 4 = liaison Cram pleine de #2 vers #3
    \CF@create@normnodes{#2@@}{#3@@}{\CF@cram@basewidth/2}{}%
    \expandafter\filldraw\expandafter[\CF@current@bondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--(#2@@1);
    \let\CF@joinbond\z@
\or% 5 = liaison Cram creuse de #3 vers #2
    \CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}%
    \expandafter\filldraw\expandafter[\CF@current@bondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--(#3@@1);
    \let\CF@joinbond\z@
\or% 6 = liaison Cram pointill\'ee de #2 vers #3
    \scope
        \CF@create@normnodes{#2@@}{#3@@}{\CF@cram@basewidth/2}{}%
        \clip(#2@@1)--(#2@@2)--(#3@@)--(#2@@1);
        \expandafter\draw\expandafter[\CF@current@bondstyle,dash pattern=on \CF@cram@dashlength off \CF@cram@dashsep,line width=\CF@cram@basewidth](#2@@)--(#3@@);
    \endscope
    \let\CF@joinbond\z@
\or% 7 = liaison Cram pointill\'ee de #3 vers #2
    \scope
        \CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}%
        \clip(#3@@1)--(#3@@2)--(#2@@)--(#3@@1);
        \expandafter\draw\expandafter[\CF@current@bondstyle,dash pattern=on \CF@cram@dashlength off \CF@cram@dashsep,line width=\CF@cram@basewidth](#3@@)--(#2@@);
    \endscope
    \let\CF@joinbond\z@
\or% 8 = liaison Cram triangle \'evid\'e de #2 vers #3
    \CF@create@normnodes{#2@@}{#3@@}{\CF@cram@basewidth/2}{}%
    \expandafter\draw\expandafter[\CF@current@bondstyle,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--(#2@@1);
    \let\CF@joinbond\z@
\or% 9 = liaison Cram triangle \'evid\'e de #3 vers #1
    \CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}%
    \expandafter\draw\expandafter[\CF@current@bondstyle,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--(#3@@1);
    \let\CF@joinbond\z@
\else
    \errmessage{Package \CF@package@name\space Error: unknown bond type, this error should not occur^^JIf you think it's a bug, send a Minimal Example to the author}%
\fi
\let\CF@start@offset\@empty
\let\CF@end@offset\@empty
\let\CF@previous@tikz\CF@current@tikz
\let\CF@previous@bondangle\CF@previous@angle
\def\CF@previous@bond{#1}%
}
%===============================================
\def\CF@draw@axisbond@nojoin#1#2{\CF@draw@bond@i[axis single bond](#1@@)--(#2@@);}

\def\CF@draw@axisbond@join#1#2{%
...
very long definition that I do not copy
...
}  

Now, the document:

\documentclass{beamer}  
\usepackage{chemfig}
\input{bondsredef}
\begin{document}
\begin{frame}<1-4>{}
    \alt<1>{\def\blue{white}}{\def\blue{blue}}
    \alt<1-2>{\def\red{white}}{\def\red{red}}
    \alt<1-3>{\def\green{white}}{\def\green{green}}
    \chemfig[][scale=0.65]{OH-[::150](=[::-60]O)-[::60]~[::-60,,,,left single bond/.style={blue},axis single bond/.style={red},right single bond/.style={green}]-[::60]-[::-60]-[::60]-[::-60]-[::60]-[::-60]=^[::60,,,,left single bond/.style={\red}](-[::60,,,,\red]-[::-60,,,,\red]=^[::60,,,,\red,left single bond/.style={\green}](-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green]-[::-60,,,,\green]-[::60,,,,\green])-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red]-[::60,,,,\red]-[::-60,,,,\red])-[::-60]=^[::60,,,,left single bond/.style={\blue}](-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue]-[::60,,,,\blue]-[::-60,,,,\blue])-[::-60]-[::60]-[::-60]-[::60]-[::-60]-[::60]}
\end{frame}
\end{document}  

Finally, its result: enter image description here

3
  • However, I am not sure whether it may not cause problems in some situations due to the styles hardcoded in the macros.
    – arecuk
    Sep 23, 2015 at 11:51
  • And, of course, I know that the triple bond is in wrong binding angle!
    – arecuk
    Sep 23, 2015 at 11:54
  • A very complicated solution, involving code redefintion.
    – unbonpetit
    Sep 23, 2015 at 16:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .