% __________________________________________________________________ % | | % | | % | chemfig v0.3a | % | | % | January 8, 2011 | % | | % |__________________________________________________________________| % % This is chemfig.sty, the code of the "chemfig" package. % % Maintainer: Christian Tellechea % E-mail : unbonpetit@gmail.com % Comments, bug reports and suggestions are welcome. % Licence : Released under the LaTeX Project Public License v1.3c or % later, see http://www.latex-project.org/lppl.txt % Copyright : Christian Tellechea 2010-2011 % % The "chemfig" package consists of the 6 following files: % chemfig.sty (this file) % README % chemfig_doc_en.tex, chemfig_doc_en.pdf (english manual) % chemfig_doc_fr.tex, chemfig_doc_fr.pdf (manual in french) % % -------------------------------------------------------------------- % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % % % http://www.latex-project.org/lppl.txt % % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % -------------------------------------------------------------------- % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Christian Tellechea % -------------------------------------------------------------------- \newcommand*\CF@ver {0.3a} \newcommand*\CF@date {2011/01/08} \newcommand*\CF@fr@date {8 Janvier 2011} \newcommand*\CF@en@date {January 08, 2011} \newcommand*\CF@package@name{chemfig} \ProvidesPackage\CF@package@name[\CF@date\space v\CF@ver\space Draw molecule with an easy syntax] \NeedsTeXFormat{LaTeX2e} \RequirePackage{tikz} \newcount\CF@cnt@atomingroup \newcount\CF@cnt@groupnumber \newcount\CF@cnt@atomnumber \newcount\CF@cnt@cycle \newif\ifCF@incycle \newif\ifCF@cyclearc \newif\if@CF@definesubmol \newdimen\CF@dimax \newdimen\CF@dimbx \newdimen\CF@dimay \newdimen\CF@dimby \newbox\CF@lewis@box \newbox\CF@box@boxa \newbox\CF@box@boxb \newbox\CF@stuff@box \newcommand*\printatom[1]{\ensuremath{\mathrm{#1}}} \newcommand\CF@node@content{\expandafter\printatom\expandafter{\csname atom@\number\CF@cnt@atomnumber\endcsname\CF@node@strut}} \newcommand\chemskipalign{% \ifx\CF@bond@outcontentsaved\@empty% sauf si un \chemskipalign a été fait à l'atome précédent \global\let\CF@bond@outcontentsaved\CF@bond@outcontent% sauvegarder l'atome d'où vient la liaison \fi \let\CF@node@strut\@empty } \def\CF@empty@node{{}} \expandafter\let\expandafter\CF@char@triplebond\string~ \def\CF@cycle@inraduiscoeff{0.75}% coeff multiplicateur du rayon des arcs dans les cycles \newcommand*\setcrambond[3]{% \def\CF@cram@basewidth{#1}% \ifx\@empty#2\@empty\def\CF@cram@dashlength{1pt}\else\def\CF@cram@dashlength{#2}\fi \ifx\@empty#3\@empty\def\CF@cram@dashsep{2pt}\else\def\CF@cram@dashsep{#3}\fi} \setcrambond{}{}{} \newcommand*\setatomsep{\def\CF@atom@sep}% espacement des atomes liés \setatomsep{} \newcommand*\setbondoffset{\def\CF@bond@offset}% offset des liaisons \setbondoffset{2pt} \newcommand*\setdoublesep{\def\CF@double@sep} \setdoublesep{2pt} \newcommand*\CF@read@manual{Please, read the manual.} \newcommand*\definesubmol{\@CF@definesubmoltrue\CF@def@submol} \newcommand*\redefinesubmol{\@CF@definesubmolfalse\CF@def@submol} \newcommand*\CF@def@submol[1]{% \begingroup \def\CF@tmp@str{#1}% \catcode`[\@ne\catcode`]\tw@ \futurelet\CF@toks@a\CF@test@nxttok } \newcommand*\CF@test@nxttok{% \if[\noexpand\CF@toks@a \expandafter\expandafter\expandafter\CF@grab@optalias\expandafter\expandafter\expandafter{\expandafter\CF@tmp@str\expandafter}% \else \CF@swap@fi \expandafter\endgroup \expandafter\CF@def@submol@i\expandafter{\CF@tmp@str}{}% \fi } \newcommand*\CF@grab@optalias[2]{% \endgroup \begingroup \everyeof{\@nil}\endlinechar\m@ne \expandafter\assign@tonil\expandafter\CF@tmp@str\scantokens{#2}% \CF@expand@second{\endgroup\CF@def@submol@i{#1}}\CF@tmp@str } \newcommand*\CF@def@submol@i[3]{% #1 nom, #2 = code si liaison arrive de droite , #3 = code si liaison arrive de gauche \ifcat\relax\expandafter\noexpand\@car#1\@nil% si #1 est une séquence de contrôle \expandafter\ifdefined\@car#1\@nil \if@CF@definesubmol \PackageWarning\CF@package@name{The macro \expandafter\string\@car#1\@nil\space is already defined, the previous definition is lost.}% \fi \fi \ifx\@empty#2\@empty \expandafter\def\@car#1\@nil{\@empty#3}% \else \expandafter\def\@car#1\@nil{% \romannumeral \ifdim\CF@current@angle pt>90pt \ifdim\CF@current@angle pt<270pt \expandafter\expandafter\expandafter\@firstoftwo \else \expandafter\expandafter\expandafter\@secondoftwo \fi \else \expandafter\@secondoftwo \fi {\z@#2}{\z@#3}}% \fi \else \ifcsname CF@@#1\endcsname \if@CF@definesubmol \PackageWarning\CF@package@name{The submol "#1" is already defined, the previous definition is lost.}% \fi \fi \ifx\@empty#2\@empty \expandafter\def\csname CF@@#1\endcsname{\@empty#3}% "\@empty" car tout ça sera 1-développé lorsque rencontrée \else \expandafter\def\csname CF@@#1\endcsname{% \romannumeral% donnera le développement souhaité en 1 coup \ifdim\CF@current@angle pt>90pt \ifdim\CF@current@angle pt<270pt \expandafter\expandafter\expandafter\@firstoftwo \else \expandafter\expandafter\expandafter\@secondoftwo \fi \else \expandafter\@secondoftwo \fi {\z@#2}{\z@#3}}% \fi \fi } \newcommand*\CF@if@integer[1]{% \begingroup \afterassignment\CF@after@integer \CF@cnt@cycle0#1\relax } \def\CF@after@integer#1\relax{% \endgroup \ifx\@empty#1\@empty\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } \def\CF@swap@fi#1\fi{\fi#1} \def\CF@gobble@tonil#1\@nil{} \newcommand*\CF@expafterarg@ntimes[3][1]{% \CF@expafterarg@ntimes@i{#1}{#3}% \expandafter\CF@swap@arg\expandafter{\CF@tmp@str}{#2}% } \newcommand*\CF@expafterarg@ntimes@i[2]{% \ifnum#1=\z@ \def\CF@tmp@str{#2}% \else \CF@swap@fi \expandafter\CF@expafterarg@ntimes@i\expandafter{\number\numexpr#1-1\expandafter}\expandafter{#2}% \fi } \newcommand*\CF@swap@arg[2]{#2{#1}} \newcommand*\CF@expand@second[2]{\expandafter\CF@swap@arg\expandafter{#2}{#1}} \newcommand*\CF@swap@two[2]{#2#1} \newcommand*\CF@expand@afterfirst[2]{\expandafter\CF@swap@two\expandafter{#2}{#1}} \newcommand*\CF@edef@second[2]{% \edef\CF@tmp@str{#2}% \expandafter\CF@swap@two\expandafter{\CF@tmp@str}{#1}% } \newcommand*\CF@add@tocs[2]{\expandafter\def\expandafter#1\expandafter{#1#2}} \newcommand*\CF@expadd@tocs[2]{\expandafter\CF@add@tocs\expandafter#1\expandafter{#2}} \newcommand*\CF@edefadd@tocs[2]{% \edef\CF@tmp@str{#2}% \expandafter\CF@add@tocs\expandafter#1\expandafter{\CF@tmp@str}% } \newcommand*\CF@if@firsttokmatch[2]{% est ce que #1 et #2 commencent par les mêmes tokens ? \futurelet\CF@toks@a\CF@gobble@tonil#1\relax\@nil \futurelet\CF@toks@b\CF@gobble@tonil#2\relax\@nil \ifx\CF@toks@a\CF@toks@b\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi } \newcommand*\CF@if@firsttokin[1]{% teste si le token qui commence #1 appartient aux tokens mis dans #2 \futurelet\CF@toks@a\CF@gobble@tonil#1\relax\@nil \CF@if@firsttokin@i } \newcommand*\CF@if@firsttokin@i[1]{% \ifx\@empty#1\@empty \expandafter\@secondoftwo \else \futurelet\CF@toks@b\CF@gobble@tonil#1\relax\@nil \ifx\CF@toks@a\CF@toks@b \expandafter\expandafter\expandafter\@firstoftwo \else \CF@swap@fi\CF@swap@fi \expandafter\CF@if@firsttokin@i\expandafter{\@gobble#1}% \fi \fi } \newcommand*\CF@if@instr[2]{% \def\CF@if@instr@i##1#2##2\@nil{\ifx\@empty##2\@empty\expandafter\@secondoftwo\else\expandafter\@firstoftwo\fi}% \CF@if@instr@i#1\@@nil#2\@nil } \def\CF@after@space#1 #2\@nil{#2} \newcommand*\CF@seek@node[3]{% cherche un noeud au début de #1 l'assigne dans la sc #2 et met le reste dans #3 \let#2\@empty \def#3{#1}% \futurelet\CF@toks@a\CF@gobble@tonil#1\relax\@nil \ifx\CF@toks@a\@sptoken\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\expandafter\CF@seek@node@i\expandafter{\CF@after@space#1\@nil}#2#3}% ignore l'espace qui commence un groupe d'atome {\CF@seek@node@i{#1}#2#3}% } \newcommand*\CF@seek@node@i[3]{% \ifx\@empty#1\@empty \let#3\@empty \else \futurelet\CF@toks@a\CF@gobble@tonil#1\relax\@nil \ifx\CF@toks@a\@sptoken\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\CF@add@tocs#2{ }% \CF@swap@fi\expandafter\CF@seek@node@i\expandafter{\CF@after@space#1\@nil}#2#3% }% {\ifx\CF@toks@a\bgroup\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\CF@expadd@tocs#2{\expandafter{\@car#1\@nil}}% \CF@swap@fi\expandafter\CF@seek@node@i\expandafter{\@gobble#1}#2#3% }% {\CF@if@firsttokin@i{-=(*<>!\CF@char@triplebond}% {\def#3{#1}}% {\CF@expadd@tocs#2{\@car#1\@nil}% \CF@swap@fi\expandafter\CF@seek@node@i\expandafter{\@gobble#1}#2#3% }% }% }% \fi } % on sait que #1 commence par -,=,~,<,>. On analyse cette liaison % #2 reçoit le type de liaisons (1 pour -, 2 pour =, 3 pour ~) \newcommand*\CF@bond@findnum[2]{% \futurelet\CF@toks@a\CF@gobble@tonil#1\@nil \edef#2{% \ifx-\CF@toks@a1% \else \ifx=\CF@toks@a2% \else \ifx\CF@char@triplebond\CF@toks@a3% \else \ifx>\CF@toks@a4% \else \ifx<\CF@toks@a5% \else0% si 0 --> il y a une erreur non dûe à l'utilisateur \fi \fi \fi \fi \fi}% \ifnum#2>\thr@@% si c'est une liaison de Cram \expandafter\futurelet\expandafter\CF@toks@a\expandafter\CF@gobble@tonil\@gobble#1\@nil% chope le caractère suivant \ifx:\CF@toks@a \edef#2{\number\numexpr#2+2}% si c 'est un ":", signe du pointillé, ajoute 2 \else \ifx|\CF@toks@a \edef#2{\number\numexpr#2+4}% si c 'est un "|", signe du triangle évidé, ajouter 4 \fi \fi \fi } \def\CF@analyse@bondoffset#1,#2\@nil{% \def\CF@start@offset{#1}\def\CF@end@offset{#2}% } \expandafter\def\expandafter\CF@grab@bondoffset\string#(#1)#2\@nil{% \ifx\@empty#1\@empty \else \CF@if@instr{#1},% {\CF@analyse@bondoffset#1\@nil}% {\def\CF@start@offset{#1}}% \fi \def\CF@remain@afterbond{#2}% } \newcommand*\CF@analyse@bond[2]{% \CF@bond@findnum{#1}#2% \expandafter\def\expandafter\CF@remain@afterbond\expandafter{\@gobble#1}%mange le premier signe de la liaison \let\CF@doublebond@type\z@ \ifnum#2=\tw@% si c'est une double liaison, regarde s'il y a un + ou - derrière \expandafter\futurelet\expandafter\CF@toks@a\expandafter\CF@gobble@tonil\@gobble#1\@nil \ifx^\CF@toks@a \let\CF@doublebond@type\@ne \expandafter\def\expandafter\CF@remain@afterbond\expandafter{\@gobbletwo#1}% mange le "^" \else \ifx_\CF@toks@a \let\CF@doublebond@type\tw@ \expandafter\def\expandafter\CF@remain@afterbond\expandafter{\@gobbletwo#1}% mange le "_" \fi \fi \else \ifnum#2>5 % si c'est une laision de Cram pointillée ou triangle évidé \expandafter\def\expandafter\CF@remain@afterbond\expandafter{\@gobbletwo#1}% mange un caractère de plus \fi \fi \expandafter\expandafter\expandafter\CF@if@firsttokmatch\expandafter\expandafter\expandafter{\expandafter\CF@remain@afterbond\expandafter}\string##% {\expandafter\CF@grab@bondoffset\CF@remain@afterbond\@nil}% \relax \expandafter\expandafter\expandafter\CF@if@firsttokmatch\expandafter\expandafter\expandafter{\expandafter\CF@remain@afterbond\expandafter}\string @% {\expandafter\CF@grab@movearg\CF@remain@afterbond\@nil}% \relax \expandafter\CF@if@firsttokmatch\expandafter{\CF@remain@afterbond}[% {\expandafter\CF@analyse@optarg\CF@remain@afterbond\@nil\CF@remain@afterbond}% {\let\CF@current@stringangle\CF@default@stringangle \let\CF@current@length\CF@default@length \let\CF@current@fromatom\CF@default@fromatom \let\CF@current@toatom\CF@default@toatom \let\CF@current@tikz\CF@default@tikz \let\CF@movebond@name\@empty }% \ifCF@incycle \pgfmathparse{360/\CF@cycle@num+\CF@initcycle@angle}% \edef\CF@current@stringangle{::+\pgfmathresult}% \def\CF@initcycle@angle{0}% \let\CF@current@length\CF@default@length% et on ignore la longueur de liaison spécifiée \fi \expandafter\CF@set@bondangle\expandafter{\CF@current@stringangle}\CF@current@angle } \newcommand*\CF@set@bondangle[2]{% le code de la direction est contenu dans #1, en sortie, #2 contient l'angle \ifx\@empty#1\@empty% \let#2\CF@default@angle \else \if:\expandafter\noexpand\@car#1\@nil \if:\expandafter\expandafter\expandafter\noexpand\expandafter\@car\@gobble#1\@nil \pgfmathparse{\CF@previous@angle+\expandafter\@gobble\@gobble#1}% \let#2\pgfmathresult \else \expandafter\def\expandafter#2\expandafter{\@gobble#1} \fi% puis normalise l'angle entre 0 et 360 \ifdim\ifdim#2pt<\z@-\fi#2pt>360pt % si |#2|>360 \pgfmathparse{#2-360*floor(#2/360)}% \ifdim\pgfmathresult pt<\z@\pgfmathparse{\pgfmathresult+360}\fi \let#2\pgfmathresult \else \ifdim\pgfmathresult pt<\z@ \pgfmathparse{#2+360}% \let#2\pgfmathresult \fi \fi \else \ifnum#1>7 \pgfmathparse{#1-floor(#1/8)*8}% \ifdim\pgfmathresult pt<\z@\pgfmathparse{\pgfmathresult+8}\fi \edef#2{\ifcase\expandafter\CF@int@part\pgfmathresult\@nil0\or45\or90\or135\or180\or225\or270\or315\else-1\fi}% angle =-1 --> erreur \else \edef#2{\ifcase#1 0\or45\or90\or135\or180\or225\or270\or315\else-1\fi}% \fi \fi \fi } \def\CF@int@part#1.#2\@nil{#1 } \def\CF@analyse@movearg#1,#2\@nil#3{% \def#3{#1}\def\CF@movebond@coeff{#2}% } % Argument limités légitimes ici car #2 (qui est ce qui suit "@{}" dans l'argument optionnel) ne DOIT % pas commencer par une accolade. \expandafter\def\expandafter\CF@grab@movearg\string @#1#2\@nil{% \CF@if@instr{#1},% {\CF@analyse@movearg#1\@nil\CF@movebond@name}% {\def\CF@movebond@name{#1}\def\CF@movebond@coeff{0.5}}% \def\CF@remain@optarg{#2}% } \newcommand*\CF@testempty@andassign[3]{\ifx\@empty#2\@empty\let#1#3\else\def#1{#2}\fi} \def\CF@sanitize@lastitem#1,\@empty#2\@nil{#1} \def\CF@parse@optlist#1,#2,#3,#4,#5\@nil{% \CF@testempty@andassign\CF@current@stringangle{#1}\CF@default@stringangle \CF@testempty@andassign\CF@current@length{#2}\CF@default@length \CF@testempty@andassign\CF@current@fromatom{#3}\CF@default@fromatom \CF@testempty@andassign\CF@current@toatom{#4}\CF@default@toatom \expandafter\CF@testempty@andassign\expandafter\CF@current@tikz\expandafter{\CF@sanitize@lastitem#5,\@empty\@nil}\CF@default@tikz }% \def\CF@analyse@optarg[#1]#2\@nil#3{% \ifx\@empty#1\@empty \else \CF@expand@afterfirst{\CF@if@firsttokmatch{#1}}{\string @}% {\CF@grab@movearg#1\@nil}% {\let\CF@movebond@name\@empty \def\CF@remain@optarg{#1}}% \expandafter\CF@parse@optlist\CF@remain@optarg,\@empty,\@empty,\@empty,\@empty\@nil \def#3{#2}% \fi } \newcommand*\CF@seek@submol{% \expandafter\CF@if@firsttokmatch\expandafter{\CF@remain@molecule}!% {\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter \CF@remain@molecule\expandafter\expandafter\expandafter{\expandafter\@gobble\CF@remain@molecule}% enlève le ``!'' \ifcat\relax\expandafter\expandafter\expandafter\noexpand\expandafter\@car\CF@remain@molecule\@nil \CF@expafterarg@ntimes[5]{\def\CF@insert@submol}{\expandafter\@car\CF@remain@molecule\@nil}% \else \CF@expafterarg@ntimes[3]{\def\CF@insert@submol}{\csname CF@@\expandafter\@car\CF@remain@molecule\@nil\endcsname}% \fi \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\CF@remain@molecule\expandafter\expandafter\expandafter {\csname CF@insert@submol\expandafter\expandafter\expandafter\endcsname\csname @gobble\expandafter\endcsname\CF@remain@molecule}% \CF@seek@submol }% \relax } \newcommand*\CF@insert@emptygroup[1]{% insère {} au début de la sc #1 \expandafter\def\expandafter#1\expandafter{\expandafter{\expandafter}#1}% } \newcommand*\CF@make@other[1]{% \ifx\@empty#1\@empty \else \expandafter\@makeother\@car#1\@nil \CF@swap@fi \expandafter\CF@make@other\expandafter{\@gobble#1}% \fi } \newcommand*\chemfig[1][]{\def\CF@tmp@str{#1}\chemfig@optarg} \newcommand*\chemfig@optarg[1][]{% \edef\CF@tmp@str{[remember picture,every node/.style={anchor=base,inner sep=0pt,outer sep=0pt,minimum size=0pt\ifx\@empty#1\@empty\else,#1\fi},baseline\unless\ifx\CF@tmp@str\@empty,\CF@tmp@str\fi]}% \expandafter\tikzpicture\CF@tmp@str \begingroup \let\CF@hook@list\@empty \ifx\CF@atom@sep\@empty\def\CF@atom@sep{3em}\fi \ifx\CF@cram@basewidth\@empty\def\CF@cram@basewidth{1.5ex}\fi \CF@incyclefalse \CF@cnt@groupnumber\z@ \let\CF@last@action\z@% 0=début du dessin 1=tracé d'un noeud 2=tracé d'une liaison \let\CF@start@offset\@empty \let\CF@end@offset\@empty \let\CF@bond@outcontentsaved\@empty \def\CF@cycle@anglecorrection{180/\CF@cycle@num}% \everyeof{\@nil}\endlinechar\m@ne \CF@make@other{[]:(),-=~!?<>;*|##@}% \CF@chemfig@i } \newcommand*\CF@chemfig@i[1]{% \CF@chemfig@ii{#1}% \endtikzpicture \let\CF@split@state\z@ } \newcommand*\CF@chemfig@ii[1]{% #1 est le code de la molécule \ifnum\CF@last@action=\thr@@ \ifCF@incycle \def\CF@default@angle{0}% \else \ifnum\CF@cnt@cycle=\z@% si c'est le début d'un cycle \pgfmathparse{\CF@previous@angle+180+\CF@cycle@anglecorrection}% on met la liaison à +180° + correction \else \pgfmathparse{\CF@previous@angle-90+180/\CF@cycle@num}% sinon à la bissectrice du sommet du cycle \fi \let\CF@default@angle\pgfmathresult \fi \let\CF@default@stringangle\@empty \else \def\CF@default@angle{0}% \def\CF@default@stringangle{:0}% angle pris par défaut si le champ est vide \fi \let\CF@current@angle\CF@default@angle \ifCF@incycle\else\def\CF@default@length{1}\fi% longueur de la liaison par défaut sauf pour un cycle où on prend celle en cours \let\CF@default@fromatom\@empty% numero de l'atome d'où partent les liaisons par défaut \let\CF@default@toatom\@empty% numéro de l'atome où arrivent les laisons par défaut \let\CF@default@tikz\@empty \if[\expandafter\noexpand\@car#1\@nil \CF@analyse@optarg#1\@nil\CF@remain@molecule \expandafter\CF@set@bondangle\expandafter{\CF@current@stringangle}\CF@current@angle \let\CF@default@angle\CF@current@angle \let\CF@previous@angle\CF@current@angle \unless\ifx\@empty\CF@current@stringangle\let\CF@default@angle\CF@current@angle\fi \unless\ifx\@empty\CF@current@length\let\CF@default@length\CF@current@length\fi \unless\ifx\@empty\CF@current@fromatom\let\CF@default@fromatom\CF@current@fromatom\fi \unless\ifx\@empty\CF@current@toatom\let\CF@default@toatom\CF@current@toatom\fi \unless\ifx\@empty\CF@current@tikz\let\CF@default@tikz\CF@current@tikz\fi \else \def\CF@remain@molecule{#1}% on prend tout puisque pas d'argument optionnel au début \fi% après l'argument entre crochet au début, on passe à la suite \ifCF@incycle% si on commence un cycle \let\CF@current@angle\CF@previous@angle \else \let\CF@current@angle\CF@default@angle \fi \edef\CF@default@stringangle{:\CF@default@angle}% \let\CF@current@length\CF@default@length \let\CF@current@fromatom\CF@default@fromatom \let\CF@current@toatom\CF@default@toatom \let\CF@current@tikz\CF@default@tikz \ifnum\CF@last@action=\z@ \let\CF@previous@angle\CF@default@angle \node(CF@node){}; \expandafter\CF@if@firsttokin\expandafter{\CF@remain@molecule}{-=(*\CF@char@triplebond?<>}% {\CF@insert@emptygroup\CF@remain@molecule}% \relax \fi \CF@chemfig@iii } \newcommand*\CF@chemfig@iii{% \let\CF@next@action\CF@chemfig@iii% à prioi, on reboucle \ifx\CF@remain@molecule\@empty \let\CF@next@action\endgroup \else \CF@seek@submol \expandafter\CF@seek@node\expandafter{\CF@remain@molecule}\CF@current@atomgroup\CF@remain@molecule \ifx\@empty\CF@current@atomgroup% pas de noeud pour commencer ? \def\CF@bond@outnode{n\CF@last@groupnumber-% \ifx\CF@current@fromatom\@empty \ifdim\CF@current@angle pt<90pt \number\CF@cnt@atomingroup \else\ifdim\CF@current@angle pt>270pt \number\CF@cnt@atomingroup\else1\fi \fi \else\CF@current@fromatom \fi}% \expandafter\futurelet\expandafter\CF@toks@a\expandafter\CF@gobble@tonil\CF@remain@molecule\relax\@nil \CF@if@firsttokin@i{-=<>\CF@char@triplebond}% la suite est une liaison {\ifnum\CF@last@action=\tw@% c'est la deuxième liaison consécutive ? \CF@insert@emptygroup\CF@remain@molecule% insère un groupe vide \edef\CF@bond@outnode{\CF@bond@outnode}% \else \ifCF@incycle\advance\CF@cnt@cycle\@ne\fi \expandafter\CF@analyse@bond\expandafter{\CF@remain@molecule}\CF@bond@type \edef\CF@bond@outnode{\CF@bond@outnode}% \let\CF@remain@molecule\CF@remain@afterbond \ifCF@incycle \ifnum\CF@cnt@cycle=\CF@cycle@num\relax \expandafter\expandafter\expandafter\@firstoftwo \else \expandafter\expandafter\expandafter\@secondoftwo \fi \else \expandafter\@secondoftwo \fi {\let\CF@next@action\endgroup \CF@draw@bond\CF@bond@type{\CF@bond@outnode}{\CF@hook@cycle}\CF@previous@atomgroup\CF@hook@atomgroup }% {\node[at=(\CF@bond@outnode),shift=(\ifcase\CF@split@state\or180-\or-\fi\CF@current@angle:\CF@current@length*\CF@atom@sep)](CF@node){}; \let\CF@previous@angle\CF@current@angle \let\CF@last@action\tw@ }% \fi \ifx\CF@remain@molecule\@empty% plus rien après la liaison -> insère un groupe vide \CF@insert@emptygroup\CF@remain@molecule \fi }% {\edef\CF@bond@outnode{\CF@bond@outnode}% évalue le l'atome de départ de liaison \ifx(\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi% une parenthèse pour commencer ? {\ifnum\CF@last@action=\tw@% il y avait une liaison juste avant ? \CF@insert@emptygroup\CF@remain@molecule \else \expandafter\CF@grab@submol\expandafter{\CF@remain@molecule}% \begingroup \ifCF@incycle\let\CF@last@action\thr@@\fi% on était dans un cycle \CF@incyclefalse \aftergroup\CF@chemfig@iii \def\CF@next@action{\expandafter\CF@chemfig@ii\expandafter{\CF@sub@mol}}% \fi }% {\ifx\CF@remain@molecule\@empty \let\CF@next@action\endgroup \else% ce qui reste après le noeud courant n'est pas vide, ne commence pas par "-=~", ni par une parenthèse \ifx*\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi% un cycle ? {\ifnum\CF@last@action=\tw@ \CF@insert@emptygroup\CF@remain@molecule% insère un groupe vide \else \ifCF@incycle\let\CF@last@action\thr@@\fi% on était dans un cycle \ifnum\CF@last@action=\thr@@\let\CF@lastcycle@num\CF@cycle@num\fi \CF@expafterarg@ntimes[2]\CF@if@firsttokmatch{\expandafter\@gobble\CF@remain@molecule}*% un 2è "*" ? {\CF@expafterarg@ntimes[2]{\def\CF@remain@molecule}{\expandafter\@gobble\CF@remain@molecule}% enlève la 1er étoile \CF@expafterarg@ntimes[2]\CF@if@firsttokmatch{\expandafter\@gobble\CF@remain@molecule}[% un crochet ensuite ? {\expandafter\CF@cycle@parsepreamblewithoptarg\CF@remain@molecule\@nil% \begingroup inclus }% {\def\CF@cyclearc@startangle{0}\def\CF@cyclearc@endangle{360}% \let\CF@cyclearc@directtikz\@empty \expandafter\CF@cycle@parsepreamble\CF@remain@molecule\@nil% \begingroup inclus }% \CF@cyclearctrue }% {\expandafter\CF@cycle@parsepreamble\CF@remain@molecule\@nil% \begingroup inclus \CF@cyclearcfalse }% \CF@cnt@cycle\z@ \edef\CF@hook@cycle{\CF@bond@outnode}% \let\CF@hook@atomgroup\CF@previous@atomgroup \CF@incycletrue \ifnum\CF@last@action=\thr@@ \pgfmathparse{360/\CF@lastcycle@num-180}% c'est un cycle dans un cycle \else \pgfmathparse{-180/\CF@cycle@num-90+\CF@cycle@anglecorrection}% \fi \let\CF@initcycle@angle\pgfmathresult \ifCF@cyclearc% on doit tracer l'arc de cercle dans le cycle ? \pgfmathparse{\CF@cycle@inraduiscoeff*\CF@current@length*\CF@atom@sep/(2*tan(180/\CF@cycle@num))}% \let\CF@cyclearc@radius\pgfmathresult \pgfmathparse{\CF@current@angle+\CF@initcycle@angle+180/\CF@cycle@num+90} \let\CF@cyclearc@initangle\pgfmathresult \pgfmathparse{\CF@current@length*\CF@atom@sep/(2*sin(180/\CF@cycle@num))}% \node[at=(\CF@bond@outnode),shift=(\CF@cyclearc@initangle:\pgfmathresult pt)](arccenter){};% le centre de l'arc \node[at=(arccenter),shift=(\CF@cyclearc@startangle:\CF@cyclearc@radius pt)](initarc){};% le début de l'arc \expandafter\draw\expandafter[\CF@cyclearc@directtikz](initarc) arc (\CF@cyclearc@startangle:\CF@cyclearc@endangle:\CF@cyclearc@radius pt); \fi \aftergroup\CF@chemfig@iii \def\CF@next@action{\expandafter\CF@chemfig@ii\expandafter{\CF@sub@mol}}% \fi }% {\PackageError\CF@package@name{Something went wrong at this point: \detokenize\expandafter{\CF@remain@molecule}}{If you think it's a bug, please, send a Minimal Example to the author.}}% \fi}% }% \else \CF@expand@second{\CF@expand@second{\CF@expand@second\CF@draw@atomgroup\CF@current@angle}\CF@current@toatom}\CF@current@atomgroup \fi \fi \CF@next@action } \def\CF@cycle@parsepreamble*#1#2\@nil{% \ifnum#1<\thr@@ \PackageError\CF@package@name{A cycle must be at least a triangle.}{} \fi \def\CF@remain@molecule{#2}% \expandafter\CF@grab@submol\expandafter{\CF@remain@molecule}% \begingroup \def\CF@cycle@num{#1}% } \def\CF@cycle@parsepreamblewithoptarg*[#1]#2#3\@nil{% \CF@cycle@parseoptarg#1,\@empty,\@empty,\@empty\@nil \CF@cycle@parsepreamble*#2#3\@nil } \def\CF@cycle@parseoptarg#1,#2,#3\@nil{% \ifx\@empty#1\@empty\def\CF@cyclearc@startangle{0}\else\def\CF@cyclearc@startangle{#1}\fi \ifx\@empty#2\@empty\def\CF@cyclearc@endangle{360}\else\def\CF@cyclearc@endangle{#2}\fi \expandafter\def\expandafter\CF@cyclearc@directtikz\expandafter{\CF@sanitize@lastitem#3,\@empty\@nil}% } \newcommand*\CF@grab@submol[1]{% \begingroup \catcode`(\@ne\catcode`)\tw@ \expandafter\expandafter\expandafter \endgroup \expandafter\CF@grab@submol@i\scantokens{\relax#1}% le \relax sert à meubler pour ne pas que l'argument délimité n'enlève les accolades } \def\CF@grab@submol@i#1\@nil{% \expandafter\assign@tonil\expandafter\CF@remain@molecule\scantokens\expandafter\expandafter\expandafter{\expandafter\@gobble\@gobble#1}% \expandafter\assign@tonil\expandafter\CF@sub@mol\scantokens\expandafter\expandafter\expandafter{\expandafter\@car\@gobble#1\@nil}% } \def\assign@tonil#1#2\@nil{\def#1{#2}} \newcommand*\CF@ifcar@isupperletter[1]{% \ifcat\relax\noexpand#1% \let\CF@next\@secondoftwo% faux si c'est une sc \else \ifnum`#1<`A \let\CF@next\@secondoftwo \else \ifnum`#1>`Z \let\CF@next\@secondoftwo \else \let\CF@next\@firstoftwo \fi \fi \fi \CF@next } % Créé 4 noeuds au dessus et au dessous des noeuds #1 et #2 % à une distance de #3 du noeud #1 et #4 du noeud #2 \newcommand*\CF@create@normnodes[4]{% \ifx\@empty#3\@empty\else \node[at=(#1),xshift=#3*\CF@norm@x,yshift=#3*\CF@norm@y](#11){}; \node[at=(#1),xshift=-#3*\CF@norm@x,yshift=-#3*\CF@norm@y](#12){}; \fi \ifx\@empty#4\@empty\else \node[at=(#2),xshift=#4*\CF@norm@x,yshift=#4*\CF@norm@y](#21){}; \node[at=(#2),xshift=-#4*\CF@norm@x,yshift=-#4*\CF@norm@y](#22){}; \fi } \newcommand*\CF@compute@nodevect[2]{% \pgfextractx\CF@dimax{\pgfpointanchor{#1}{center}}% \pgfextracty\CF@dimay{\pgfpointanchor{#1}{center}}% \pgfextractx\CF@dimbx{\pgfpointanchor{#2}{center}}% \pgfextracty\CF@dimby{\pgfpointanchor{#2}{center}}% \pgfmathparse{veclen(\CF@dimbx-\CF@dimax,\CF@dimby-\CF@dimay)}\let\CF@len@vector\pgfmathresult \pgfmathparse{(\CF@dimay-\CF@dimby)/\CF@len@vector}\let\CF@norm@x\pgfmathresult \pgfmathparse{(\CF@dimbx-\CF@dimax)/\CF@len@vector}\let\CF@norm@y\pgfmathresult } \newcommand*\CF@draw@bond[5]{% #1=type de liaison #2 et #3:nom de noeuds de début et fin #4 et #5: contenu des atomes de début et fin \edef\CF@start@offset{% \ifx\CF@start@offset\@empty \ifx#4\CF@empty@node0pt\else\ifx#4\@empty0pt\else\CF@bond@offset\fi\fi \else \CF@start@offset \fi }% \edef\CF@end@offset{% \ifx\CF@end@offset\@empty \ifx#5\CF@empty@node0pt\else\ifx#5\@empty0pt\else\CF@bond@offset\fi\fi \else \CF@end@offset \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 nœud sur la liaison \path(#2@@)--(#3@@)coordinate[overlay,pos=\CF@movebond@coeff](\CF@movebond@name); \let\CF@movebond@name\@empty \fi \ifcase#1\relax \PackageError\CF@package@name{Unknown bond type, this error should not occur}{If you think it's a bug, send a Minimal Example to the author.}% \or% 1 = liaison simple \CF@draw@bond@i(#2@@)--(#3@@); \or% 2 = liaison double \ifCF@incycle \ifnum\CF@doublebond@type=\z@ \let\CF@doublebond@type\@ne \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(#2@@1)--(#3@@1); \CF@draw@bond@i(#2@@2)--(#3@@2); \or \CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep \CF@draw@bond@i(#2@@)--(#3@@); \begingroup% ajuste éventuellement les longueurs des liaisons doubles \ifCF@incycle \ifdim\CF@start@offset=\z@ \CF@add@tocs\CF@current@tikz{,shorten <=\CF@doublebond@lengthcorrection pt}% \fi \ifdim\CF@end@offset=\z@ \CF@add@tocs\CF@current@tikz{,shorten >=\CF@doublebond@lengthcorrection pt}% \fi \fi \CF@draw@bond@i(#2@@1)--(#3@@1); \endgroup \or \CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep \CF@draw@bond@i(#2@@)--(#3@@); \begingroup% ajuste éventuellement les longueurs des liaisons doubles \ifCF@incycle \ifdim\CF@start@offset=\z@ \CF@add@tocs\CF@current@tikz{,shorten <=-\CF@doublebond@lengthcorrection pt}% \fi \ifdim\CF@end@offset=\z@ \CF@add@tocs\CF@current@tikz{,shorten >=-\CF@doublebond@lengthcorrection pt}% \fi \fi \CF@draw@bond@i(#2@@2)--(#3@@2); \endgroup \fi \or% 3 = liaison triple \CF@create@normnodes{#2@@}{#3@@}\CF@double@sep\CF@double@sep \CF@draw@bond@i(#2@@)--(#3@@); \CF@draw@bond@i(#2@@1)--(#3@@1); \CF@draw@bond@i(#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@tikz,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--(#2@@1); \or% 5 = liaison Cram pleine de #3 vers #2 \CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}% \expandafter\filldraw\expandafter[\CF@current@tikz,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--(#3@@1); \or% 6 = liaison Cram pointillée 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@tikz,dash pattern=on \CF@cram@dashlength off \CF@cram@dashsep,line width=\CF@cram@basewidth](#2@@)--(#3@@); \endscope \or% 7 = liaison Cram pointillée 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@tikz,dash pattern=on \CF@cram@dashlength off \CF@cram@dashsep,line width=\CF@cram@basewidth](#3@@)--(#2@@); \endscope \or% 8 = liaison Cram triangle évidé de #2 vers #3 \CF@create@normnodes{#2@@}{#3@@}{\CF@cram@basewidth/2}{}% \expandafter\draw\expandafter[\CF@current@tikz,line join=bevel](#2@@1)--(#2@@2)--(#3@@)--(#2@@1); \or% 9 = liaison Cram triangle évidé de #3 vers #1 \CF@create@normnodes{#3@@}{#2@@}{\CF@cram@basewidth/2}{}% \expandafter\draw\expandafter[\CF@current@tikz,line join=bevel](#3@@1)--(#3@@2)--(#2@@)--(#3@@1); \else \PackageError\CF@package@name{Unknown bond type, this error should not occur}{If you think it's a bug, send a Minimal Example to the author.}% \fi \let\CF@start@offset\@empty \let\CF@end@offset\@empty } \newcommand*\CF@draw@bond@i{\expandafter\draw\expandafter[\CF@current@tikz]} \newcommand*\CF@hook@drawall{% dessine tous les crochets contenus dansla sc \CF@hook@draw \unless\ifx\CF@hook@drawlist\@empty \expandafter\CF@hook@drawfirst\CF@hook@drawlist\@nil% trace un lien de crochet à crochet \expandafter\CF@hook@drawall \fi } \def\CF@hook@drawfirst[#1,#2,#3]#4#5#6#7#8\@nil% {% \def\CF@hook@drawlist{#8}% \begingroup \def\CF@current@tikz{#3}% \def\CF@hook@startcontent{#6}\def\CF@hook@endcontent{#7}% \CF@if@integer{#2}% {\CF@draw@bond{#2}{#4}{#5}\CF@hook@startcontent\CF@hook@endcontent}% {\CF@bond@findnum{#2}\CF@bond@currentnum \CF@draw@bond\CF@bond@currentnum{#4}{#5}\CF@hook@startcontent\CF@hook@endcontent }% \endgroup } \def\CF@extract@atom#1-#2\@nil{#2}% transforme le bound@outnode en n° de l'atome \newcommand*\setnodestyle{\def\CF@node@style} \setnodestyle{} \expandafter\def\expandafter\CF@gobble@movearg\string @#1#2\@nil#3% {% \expandafter\def\csname atom@\number\CF@cnt@atomnumber\endcsname{#2}% \CF@if@instr{#1},% {\CF@analyse@movearg#1\@nil#3\let\CF@movebond@coeff\@empty}% {\def#3{#1}}% \ifx\@empty#2\@empty\let\CF@node@strut\@empty\fi }% \newcommand*\hflipnext{\let\CF@split@state\@ne} \newcommand*\vflipnext{\let\CF@split@state\tw@} \let\CF@split@state\z@ \newcommand*\CF@draw@atomgroup[3]{% #1=angle d'arrivée de la liaison #2=numero atome sur lequel arrive la liaison #3=groupe d'atomes \expandafter\let\expandafter\CF@bond@outcontent% assigne le contenu de l'atome d'où part la liaison \csname \ifdefined\CF@bond@outnode atom@\expandafter\CF@extract@atom\CF@bond@outnode\@nil \else @empty% \fi \endcsname \global\advance\CF@cnt@groupnumber\@ne \let\CF@current@atom\@empty \global\let\CF@hook@drawlist\@empty \CF@cnt@atomingroup\z@ \CF@if@firsttokmatch{#3}?{\CF@draw@atomgroup@i{{}#3}}{\CF@draw@atomgroup@i{#3}}% \def\CF@current@atomgroup{#3}% \CF@remove@movearg\CF@current@atomgroup% enlève les "@{}" \CF@if@instr{#3}?% {\CF@remove@hook\CF@current@atomgroup \ifx\@empty\CF@current@atomgroup\let\CF@current@atomgroup\CF@empty@node\fi}% \relax \ifx\@empty#2\@empty% \else \ifnum#2<\@ne \PackageWarning\CF@package@name{No atom found at position #2.}{Pershaps you mispelled the optional argument of the bond.}% \else \ifnum#2>\CF@cnt@atomingroup \PackageError\CF@package@name{No atom found at position #2.}{Pershaps you mispelled the optional argument of the bond.}% \fi \fi \fi \edef\CF@hook@atomnumber{% \ifx\@empty#2\@empty%\relax \ifdim#1pt>90pt \ifdim#1pt<270pt \number\CF@cnt@atomingroup\else1\fi \else1% \fi \else#2% \fi}% \CF@cnt@atomnumber\CF@hook@atomnumber \ifx\CF@current@atomgroup\CF@empty@node \let\CF@node@strut\@empty \else \ifx\@empty\CF@bond@outcontentsaved \def\CF@node@strut{\vphantom\CF@bond@outcontent}% \else \def\CF@node@strut{\vphantom\CF@bond@outcontentsaved}% \fi \fi \edef\CF@opt@string{anchor=\ifnum\CF@last@action=\z@ base\else center\fi,at=(CF@node),\CF@node@style}% premier atome de la molécule affiché \loop \unless\ifnum\CF@cnt@atomnumber>\CF@cnt@atomingroup \expandafter\expandafter\expandafter\futurelet\expandafter\expandafter\expandafter\CF@toks@a\expandafter\expandafter\expandafter \CF@gobble@tonil\csname atom@\number\CF@cnt@atomnumber\endcsname\@nil \expandafter\ifx\string @\CF@toks@a% l'atome courant commence par un "@" \expandafter\expandafter\expandafter\CF@gobble@movearg\csname atom@\number\CF@cnt@atomnumber\endcsname\@nil\CF@moveatom@name \expandafter\node\expandafter[\CF@opt@string,overlay](\CF@moveatom@name){\phantom{\CF@node@content}};% \let\CF@moveatom@name\@empty \fi \expandafter\node\expandafter[\CF@opt@string](n\number\CF@cnt@groupnumber-\number\CF@cnt@atomnumber){\CF@node@content};% \let\CF@node@strut\@empty \advance\CF@cnt@atomnumber\@ne \edef\CF@opt@string{anchor=base \ifnum\CF@split@state=\@ne east\else west\fi,at=(n\number\CF@cnt@groupnumber-\number\numexpr\CF@cnt@atomnumber-1.base \ifnum\CF@split@state=\@ne west\else east\fi),\CF@node@style}% \repeat \CF@cnt@atomnumber\CF@hook@atomnumber \ifnum\CF@last@action=\tw@% s'il faut tracer une liaison \gdef\CF@cycle@anglecorrection{0}% alors c'est qu'un cycle ne peut pas commencer la molécule : annulation de la correction d'angle \CF@draw@bond\CF@bond@type{\CF@bond@outnode}{n\number\CF@cnt@groupnumber-\number\CF@cnt@atomnumber}\CF@previous@atomgroup\CF@current@atomgroup \fi \let\CF@last@action\@ne% met la dernière action à 1 : affichage d'un noeud \loop \ifnum\CF@cnt@atomnumber>\@ne \advance\CF@cnt@atomnumber\m@ne \edef\CF@opt@string{anchor=base \ifnum\CF@split@state=\@ne west\else east\fi,at=(n\number\CF@cnt@groupnumber-\number\numexpr\CF@cnt@atomnumber+1.base \ifnum\CF@split@state=\@ne east\else west\fi),\CF@node@style}% \expandafter\expandafter\expandafter\futurelet\expandafter\expandafter\expandafter\CF@toks@a\expandafter\expandafter\expandafter \CF@gobble@tonil\csname atom@\number\CF@cnt@atomnumber\endcsname\@nil \expandafter\ifx\string @\CF@toks@a% l'atome courant commence par un "@" \expandafter\expandafter\expandafter\CF@gobble@movearg\csname atom@\number\CF@cnt@atomnumber\endcsname\@nil\CF@moveatom@name \expandafter\node\expandafter[\CF@opt@string,overlay](\CF@moveatom@name){\phantom{\CF@node@content}};% \let\CF@moveatom@name\@empty \fi \expandafter\node\expandafter[\CF@opt@string](n\number\CF@cnt@groupnumber-\number\CF@cnt@atomnumber){\CF@node@content};% \repeat \CF@hook@drawall \edef\CF@last@groupnumber{\number\CF@cnt@groupnumber}% \let\CF@previous@atomgroup\CF@current@atomgroup } \expandafter\def\expandafter\CF@keep@movearg\string @#1#2\@nil{\expandafter\def\expandafter\CF@current@atom\expandafter{\string @{#1}}} \newcommand*\CF@draw@atomgroup@i[1]{% transforme #1 en un groupe d'atomes \ifx\@empty#1\@empty \expandafter\let\csname atom@\number\CF@cnt@atomingroup\endcsname\CF@current@atom \else \advance\CF@cnt@atomingroup\@ne \futurelet\CF@toks@a\CF@gobble@tonil#1\@nil \expandafter\ifx\string @\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\CF@keep@movearg#1\@nil \CF@swap@fi \CF@remove@movearg@i#1\@nil\CF@after@movearg \expandafter\CF@draw@atomgroup@ii\expandafter{\CF@after@movearg}% }% {\CF@swap@fi \let\CF@current@atom\@empty \CF@draw@atomgroup@ii{#1}% }% \fi } \newcommand*\CF@draw@atomgroup@ii[1]{% \ifx\@empty#1\@empty \expandafter\let\csname atom@\number\CF@cnt@atomingroup\endcsname\CF@current@atom \else \futurelet\CF@toks@a\CF@gobble@tonil#1\@nil \ifx\bgroup\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\CF@expadd@tocs\CF@current@atom{\expandafter{\@car#1\@nil}}% \expandafter\CF@draw@atomgroup@iii\expandafter{\@gobble#1}% }% {\ifx\@sptoken\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\CF@add@tocs\CF@current@atom{ }% \expandafter\CF@draw@atomgroup@iii\expandafter{\CF@after@space#1\@nil}% }% {\CF@expadd@tocs\CF@current@atom{\@car#1\@nil}% \expandafter\CF@draw@atomgroup@iii\expandafter{\@gobble#1}% }% }% \fi } % enlève tous les "@{nom}" de la sc #1 \def\CF@remove@movearg#1% {% \CF@expand@afterfirst{\expandafter\CF@if@instr\expandafter{#1}}{\string @}% {\expandafter\CF@remove@movearg@i#1\@nil#1% \CF@remove@movearg#1}% \relax } % enlève le premier "@{}" de l'argument et l'assigne à #2 \def\CF@remove@movearg@i#1\@nil#2% {% \expandafter\def\expandafter\CF@remove@movearg@ii\expandafter##\expandafter1\string @{% \expandafter\def\expandafter#2\expandafter{\@gobble##1}% mange le \relax \CF@remove@movearg@iii\relax }% \def\CF@remove@movearg@iii##1\@nil{\CF@expadd@tocs#2{\@gobbletwo##1}}% mange le \relax et le \CF@remove@movearg@ii\relax#1\@nil } \newcommand*\CF@draw@atomgroup@iii[1]{% transforme #1 en un groupe d'atomes \ifx\@empty#1\@empty% \expandafter\let\csname atom@\number\CF@cnt@atomingroup\endcsname\CF@current@atom \let\CF@current@atom\@empty \else \futurelet\CF@toks@a\CF@gobble@tonil#1\@nil \expandafter\ifx\string @\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\expandafter\let\csname atom@\number\CF@cnt@atomingroup\endcsname\CF@current@atom \let\CF@current@atom\@empty \CF@swap@fi\CF@draw@atomgroup@i{#1}% }% {\ifx|\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\expandafter\let\csname atom@\number\CF@cnt@atomingroup\endcsname\CF@current@atom \let\CF@current@atom\@empty \CF@swap@fi\expandafter\CF@draw@atomgroup@i\expandafter{\@gobble#1}% }% {\ifx\@sptoken\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\CF@add@tocs\CF@current@atom{ }% \CF@swap@fi\expandafter\CF@draw@atomgroup@iii\expandafter{\CF@after@space#1\@nil}% }% {\ifx\bgroup\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\CF@expadd@tocs\CF@current@atom{\expandafter{\@car#1\@nil}}% \CF@swap@fi\expandafter\CF@draw@atomgroup@iii\expandafter{\@gobble#1}% }% {\expandafter\CF@ifcar@isupperletter\expandafter{\@car#1\@nil}% {\expandafter\let\csname atom@\number\CF@cnt@atomingroup\endcsname\CF@current@atom \let\CF@current@atom\@empty \CF@swap@fi\CF@draw@atomgroup@i{#1}% }% {\ifx?\CF@toks@a\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\expandafter\CF@if@firsttokmatch\expandafter{\@gobble#1}[% un crochet après le "?" {\expandafter\CF@grab@optarg\@gobble#1\@nil\CF@after@hook}% {\expandafter\CF@grab@optarg\expandafter[\expandafter]\@gobble#1\@nil\CF@after@hook}% \CF@expand@second{\CF@expand@second\CF@if@instr\CF@hook@list}{\expandafter(\CF@hook@currentname)}% crochet déjà défini ? {\expandafter\CF@hook@parselist\expandafter{\CF@hook@currentname}% va chercher les caractéristiques du crochet sauvegardé \CF@edefadd@tocs\CF@hook@drawlist{% [\CF@hook@currentname,\CF@hook@currentlink,\CF@hook@currenttikz]{\CF@hook@savedcoord}{n\number\CF@cnt@groupnumber-\number\CF@cnt@atomingroup}}% \CF@expadd@tocs\CF@hook@drawlist{\expandafter{\CF@hook@savedcontent}}% \CF@expadd@tocs\CF@hook@drawlist{\expandafter{\CF@current@atom}}% ajoute les 4 arguments à la liste des crochets à tracer \global\let\CF@hook@drawlist\CF@hook@drawlist }% {\CF@edefadd@tocs\CF@hook@list{(\CF@hook@currentname)|n\number\CF@cnt@groupnumber-\number\CF@cnt@atomingroup|}% \CF@expadd@tocs\CF@hook@list{\CF@current@atom|}% \global\let\CF@hook@list\CF@hook@list }% \CF@swap@fi\expandafter\CF@draw@atomgroup@iii\expandafter{\CF@after@hook}% }% {\CF@expadd@tocs\CF@current@atom{\@car#1\@nil}% \CF@swap@fi\expandafter\CF@draw@atomgroup@iii\expandafter{\@gobble#1}% }% }% }% }% }% }% \fi } \def\CF@kook@defaultname{a} \def\CF@hook@defaultlink{-} \def\CF@hook@defaulttikz{} \def\CF@hook@parseoptarg#1,#2,#3\@nil{% \CF@testempty@andassign\CF@hook@currentname{#1}\CF@kook@defaultname \CF@testempty@andassign\CF@hook@currentlink{#2}\CF@hook@defaultlink \CF@testempty@andassign\CF@hook@currenttikz{#3}\CF@hook@defaulttikz } \def\CF@grab@optarg[#1]#2\@nil#3{% \CF@hook@parseoptarg#1,,\@nil \def#3{#2}% } \newcommand*\CF@hook@parselist[1]{% #1 est le nom du noeud à retrouver \def\CF@hook@parselist@i##1(#1)|##2|##3|##4\@nil{% \def\CF@hook@savedcoord{##2}\def\CF@hook@savedcontent{##3}% }% \expandafter\CF@hook@parselist@i\CF@hook@list\@nil } \def\CF@remove@hook#1{% enlève tous les crochets (et leurs arguments optionnels) de la sc #1 \expandafter\CF@if@instr\expandafter{#1}{?[}% {\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter#1% \expandafter\expandafter\expandafter{\expandafter\CF@remove@opthook#1\@nil}% \CF@remove@hook#1% }% {\CF@remove@hook@i#1}% } \def\CF@remove@hook@i#1{% \expandafter\CF@if@instr\expandafter{#1}?% {\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter#1% \expandafter\expandafter\expandafter{\expandafter\CF@remove@singlehook#1\@nil}% \CF@remove@hook@i#1% }% \relax } \def\CF@remove@opthook#1?[#2]#3\@nil{#1#3} \def\CF@remove@singlehook#1?#2\@nil{#1#2} \newcommand*\setlewis[4][0.3ex]{% \def\CF@lewis@widthdouble{#1}% \ifx\@empty#2\@empty\def\CF@lewis@offset{0.4ex}\else\def\CF@lewis@offset{#2}\fi \ifx\@empty#3\@empty\def\CF@lewis@length{1.5ex}\else\def\CF@lewis@length{#3}\fi \ifx\@empty#4\@empty\def\CF@lewis@style{}\else\def\CF@lewis@style{#4}\fi } \setlewis{}{}{} \newcommand*\lewis{\begingroup\@makeother;\@makeother:\CF@lewis@i} \newcommand\CF@lewis@i[1]{\CF@lewis@ii#1\@nil} \def\CF@lewis@ii#1,#2\@nil% {% \setbox\CF@lewis@box\hbox{\printatom{#2}}% \def\CF@lewis@remainpos{#1}% \let\CF@lewis@previouspos\@empty \loop \unless\ifx\CF@lewis@remainpos\@empty \edef\CF@lewis@currentpos{\expandafter\@car\CF@lewis@remainpos\@nil}% \edef\CF@lewis@remainpos{\expandafter\@gobble\CF@lewis@remainpos}% \pgfmathparse{\wd\CF@lewis@box/2+\ifcase\CF@lewis@currentpos\space1\or1\or0\or-1\or-1\or-1\or0\or1\fi*(\wd\CF@lewis@box/2+\CF@lewis@offset)}% \let\CF@lewis@x\pgfmathresult \pgfmathparse{\ht\CF@lewis@box/2+\ifcase\CF@lewis@currentpos\space0\or1\or1\or1\or0\or-1\or-1\or-1\fi*(\ht\CF@lewis@box/2\ifnum\CF@lewis@currentpos>4 +\dp\CF@lewis@box\fi+\CF@lewis@offset)}% \let\CF@lewis@y\pgfmathresult \edef\CF@lewis@xoffset{\ifcase\CF@lewis@currentpos\space 0\or0.70711\or1\or0.70711\or0\or-0.70711\or-1\or-0.70711\fi}% \edef\CF@lewis@yoffset{\ifcase\CF@lewis@currentpos\space -1\or-0.70711\or0\or0.70711\or1\or0.70711\or0\or-0.70711\fi}% \pgfmathparse{veclen(\CF@lewis@xoffset,\CF@lewis@yoffset)}\let\CF@len@normvec\pgfmathresult \edef\CF@lewis@diagmul{\ifcase\CF@lewis@currentpos\space1\or0\or1\or0\or1\or0\or1\or0\fi}% annule l'offset pour les diagonales \if.\expandafter\@car\CF@lewis@remainpos\relax\@nil \edef\CF@lewis@remainpos{\expandafter\@gobble\CF@lewis@remainpos}% \tikz \draw[overlay,fill,black] (\CF@lewis@x pt-\CF@lewis@yoffset*\CF@lewis@diagmul*0.1ex, \CF@lewis@y pt+\CF@lewis@xoffset*\CF@lewis@diagmul*0.1ex)circle(0.15ex);% \else \if|\expandafter\@car\CF@lewis@remainpos\relax\@nil \edef\CF@lewis@remainpos{\expandafter\@gobble\CF@lewis@remainpos}% \expandafter\tikz\expandafter\draw\expandafter[\CF@lewis@style,overlay]% (\CF@lewis@x-\CF@lewis@length*\CF@lewis@xoffset/2 pt,\CF@lewis@y-\CF@lewis@length*\CF@lewis@yoffset/2 pt)-- ([xshift=-\CF@lewis@yoffset*\CF@lewis@widthdouble,yshift=\CF@lewis@xoffset*\CF@lewis@widthdouble]\CF@lewis@x-\CF@lewis@xoffset*\CF@lewis@length/2 pt,\CF@lewis@y-\CF@lewis@yoffset*\CF@lewis@length/2 pt)-- ([xshift=-\CF@lewis@yoffset*\CF@lewis@widthdouble,yshift=\CF@lewis@xoffset*\CF@lewis@widthdouble]\CF@lewis@x+\CF@lewis@length*\CF@lewis@xoffset/2 pt,\CF@lewis@y+\CF@lewis@length*\CF@lewis@yoffset/2 pt)-- (\CF@lewis@x+\CF@lewis@length*\CF@lewis@xoffset/2 pt,\CF@lewis@y+\CF@lewis@length*\CF@lewis@yoffset/2 pt)--cycle;% \else \if:\expandafter\@car\CF@lewis@remainpos\relax\@nil \edef\CF@lewis@remainpos{\expandafter\@gobble\CF@lewis@remainpos}% \tikz \draw[overlay,fill,black] (\CF@lewis@x pt-\CF@lewis@yoffset*\CF@lewis@diagmul*0.2ex-.2em*\CF@lewis@xoffset/\CF@len@normvec,\CF@lewis@y pt+\CF@lewis@xoffset*\CF@lewis@diagmul*0.2ex-.2em*\CF@lewis@yoffset/\CF@len@normvec)circle(0.15ex)% (\CF@lewis@x pt-\CF@lewis@yoffset*\CF@lewis@diagmul*0.2ex+.2em*\CF@lewis@xoffset/\CF@len@normvec,\CF@lewis@y pt+\CF@lewis@xoffset*\CF@lewis@diagmul*0.2ex+.2em*\CF@lewis@yoffset/\CF@len@normvec)circle(0.15ex);% \else \expandafter\tikz\expandafter\draw\expandafter[\CF@lewis@style,overlay]% (\CF@lewis@x-\CF@lewis@length*\CF@lewis@xoffset/2 pt,\CF@lewis@y-\CF@lewis@length*\CF@lewis@yoffset/2 pt)--% (\CF@lewis@x+\CF@lewis@length*\CF@lewis@xoffset/2 pt,\CF@lewis@y+\CF@lewis@length*\CF@lewis@yoffset/2 pt);% \fi \fi \fi \repeat \box\CF@lewis@box \endgroup } \newcommand*\chembelow[3][1.5pt]{% \setbox\CF@box@boxa\hbox{\printatom{#2}}\setbox\CF@box@boxb\hbox{\printatom{#3}}% \vtop{% \hbox{\printatom{#2}}% \hrule width0pt depth0pt height#1\relax \hbox{% \hskip\dimexpr(\wd\CF@box@boxa-\wd\CF@box@boxb)/\tw@ \printatom{#3}% \hskip\dimexpr(\wd\CF@box@boxa-\wd\CF@box@boxb)/\tw@ }% \vskip-\dimexpr\ht\CF@box@boxb+\dp\CF@box@boxb+#1\relax }% } \newcommand*\chemabove[3][1.5pt]{% \setbox\CF@box@boxa\hbox{\printatom{#2}}\setbox\CF@box@boxb\hbox{\printatom{#3}}% \vtop{% \hbox{\printatom{#2}}% \hrule width0pt depth0pt height-\dimexpr#1+\ht\CF@box@boxa+\ht\CF@box@boxb+\dp\CF@box@boxb\relax \hbox{% \hskip\dimexpr(\wd\CF@box@boxa-\wd\CF@box@boxb)/\tw@ \printatom{#3}% \hskip\dimexpr(\wd\CF@box@boxa-\wd\CF@box@boxb)/\tw@ }% }% } %%%%%% les signes et les flèches \newcommand*\chemsign[2][0.5em]{\hbox{\kern#1\relax#2\kern#1}} \newcommand*\setchemrel[3]{% \ifx\@empty#1\@empty\def\CF@chemrel@vsep{2pt}\else\def\CF@chemrel@vsep{#1}\fi \ifx\@empty#2\@empty\def\CF@chemrel@hsep{0.7em}\else\def\CF@chemrel@hsep{#2}\fi \ifx\@empty#3\@empty\def\CF@chemrel@length{4em}\else\def\CF@chemrel@length{#3}\fi } \setchemrel{}{}{} \newcommand*\chemrel[1][]{\def\CF@stuff@above{#1}\CF@chemchemrel@i} \newcommand*\CF@chemchemrel@i[1][]{\def\CF@stuff@below{#1}\CF@chemchemrel@ii\CF@stuff@above\CF@stuff@below} \newcommand*\CF@chemchemrel@ii[3]{% \def\CF@equi@chars{<>}\def\CF@chemrel@chars{#3}% \def\CF@chemrel@stuff {\leavevmode\kern\CF@chemrel@hsep \tikzpicture[every node/.style={anchor=base,inner sep=0pt,outer sep=0pt,minimum size=0pt},baseline]% \CF@if@instr{#3}{<>}% {\node[yshift=-1pt] at(0,0)(chemrel@start){\vphantom I};\node[yshift=-1pt] at(\CF@chemrel@length,0)(chemrel@end){\vphantom I};% \expandafter\draw\expandafter[\CF@remove@equichars#3,\@nil-](chemrel@end)--(chemrel@start);\fill (chemrel@start)--++(4pt,-1.75pt)--+(-1.5pt,1.75pt)--cycle;% \node[yshift=1pt] at(0,0)(chemrel@start){\vphantom I};\node[yshift=1pt] at(\CF@chemrel@length,0)(chemrel@end){\vphantom I};% \expandafter\draw\expandafter[\CF@remove@equichars#3,\@nil-](chemrel@start)--(chemrel@end);\fill(chemrel@end)--++(-4pt,1.75pt)--+(1.5pt,-1.75pt)--cycle; }% {\node at(0,0)(chemrel@start){\vphantom I};\node at(\CF@chemrel@length,0)(chemrel@end){\vphantom I};% \draw[#3](chemrel@start)--(chemrel@end);% }% \endtikzpicture \kern\CF@chemrel@hsep }% \ifx#1\@empty \ifx#2\@empty\CF@chemrel@stuff \else\chembelow[\CF@chemrel@vsep]\CF@chemrel@stuff{\hbox{#2}}% \fi \else \ifx#2\@empty\chemabove[\CF@chemrel@vsep]\CF@chemrel@stuff{\hbox{#1}}% \else\chemabove[\CF@chemrel@vsep]{\chembelow[\CF@chemrel@vsep]\CF@chemrel@stuff{\hbox{#2}}}{\hbox{#1}}% \fi \fi } \def\CF@remove@equichars#1<>#2\@nil{#1#2} \newcommand\chemmove[2][]{% \ifx\@empty#2\@empty \expandafter\@gobble \else \expandafter\@firstofone \fi {\expandafter\tikzpicture\romannumeral\ifx\@empty#1\@empty\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi {\z@[remember picture,overlay]}{\z@[remember picture,overlay,#1]}#2 \endtikzpicture }% } \newcommand*\chemnameinit[1]{% \setbox\CF@stuff@box\hbox{#1}% \edef\CF@dp@max{\the\dp\CF@stuff@box}% } \chemnameinit{} \def\CF@parse@molname#1\\#2\@nil{% \hbox to\CF@wd@stuffbox{\hss#1\hss}% \ifx\@empty#2\@empty \else \CF@swap@fi \CF@parse@molname#2\@nil \fi } \newcommand*\chemname[3][1.5ex]{% \setbox\CF@stuff@box\hbox{#2}% \edef\CF@wd@stuffbox{\the\wd\CF@stuff@box}\edef\CF@dp@stuffbox{\the\dp\CF@stuff@box}% \leavevmode \ifdim\CF@dp@max<\CF@dp@stuffbox\let\CF@dp@max\CF@dp@stuffbox\fi \vtop{% \box\CF@stuff@box \nointerlineskip \kern\dimexpr#1+\CF@dp@max-\CF@dp@stuffbox\relax \CF@parse@molname#3\\\@nil }% } \endinput ###################################################################### # Historique # ###################################################################### v0.1 2010/06/23 - Première version publique sur le CTAN ---------------------------------------------------------------------- v0.2 2010/08/31 - Ajout de la documentation en anglais. - Correction de bugs. - \printatom est désormais une macro publique. - Les espaces sont permis dans les molécules. Ils seront ignorés par défaut puisque les atomes sont composés en mode math par \printatom - Une paire de Lewis peut être représentée ":". - Dans les cycles, une correction de la longueur du trait déporté des liaisons doubles est fait de telle sorte que si l'on écrit \chemfig{*5(=====)}, on obtient deux polygones réguliers concentriques. - La séquence de contrôle \setnodestyle permet de spécifier le style des nœuds dessinés par tikz. ---------------------------------------------------------------------- v0.3 2010/11/21 - Amélioration de \definesubmol qui accepte les séquences de contrôle. On peut aussi choisir un alias dont la substitution est différente selon l'orientation de la liaison qui lui arrive dessus. - Le caractère "|" force la fin d'un atome. Si on écrit "D|ef" alors, chemfig verra deux atomes "D" et "ef". - Le caractère "#" est reconnu lorsqu'il suit un caractère de liaison. Il doit être suivi d'un argument entre parenthèses qui contient l'offset de début et de fin qui s'appliqueront à cette liaison. - La macro \chemfig admet un argument optionnel qui sera passé à l'environnement tikzpicture dans lequel elle est dessinée. - Mise en place de la représentation des mécanismes réactionnels avec la synatxe "@{}" devant un atome ou "@{,}" au tout début de l'argument d'une liaison. Cette syntaxe permet de placer un nœud (au sens de tikz) qui deviendra l'extrémité des flèches des mécanismes. Le tracé des flèches est faite par la macro \chemmove dont l'argument optionnel devient celui de l'environnement tikspicture dans lequel sont faites les flèches. - Pour le mécanisme d'alignement vertical via le \vphantom, la commande \chemskipalign permet d'ignorer le groupe d'atomes dans lequel elle est écrite. - La commande \chemname permet d'afficher un nom sous une molécule. la commande \chemnameinit initialise la plus grande profondeur rencontrée. - La commande \lewis a été modifiée de telle sorte que les dessins des décorations soient proportionnels à la taille de la police. ---------------------------------------------------------------------- v0.3a 2011/01/08 - Correction d'un bug dans l'argument optionnel de \definesubmol lorsque celui-ci comporte des crochets. - Mise à jour du manuel en anglais. - Ajout de \vflipnext et \hflipnext pour retourner horizontalement ou verticalement la prochaine molécule.