我在一个文件中有大约一百个用 chemfig 绘制的分子,我将其视为一种数据库。编译此文件大约需要五分钟。我要写一份五六十页的报告,这些分子将插入该文件中。
我想避免主文件的编译花费很长时间,因此我的问题是:是否可以在主文件中使用数据库中已编译的代码?
编辑:按照 Christian 的建议,我尝试设置 tikzexternalize 库。我明白必须将代码放在chemfig
tikzpicture 环境中并使用 temp 前缀。我正在用这个字符串编译文件:pdflatex --file-line-error --synctex=1 --shell-escape ext
,其中 ext 是文件的名称。
这是我的 MWE:
\documentclass[12pt,twoside,openright]{book}
\usepackage[T1]{fontenc}
\usepackage[applemac]{inputenc}
\usepackage{chemfig,chemnum,}
\usetikzlibrary{external}
\tikzexternalize[prefix=temp/, only named=true]
\begin{document}
\begin{tikzpicture}
\chemname{\chemfig{A=B-C-D}}{\cmpd{example}}
\end{tikzpicture}
\end{document}
我还没有彻底测试过它,但目前它可以正确地为每个分子创建单独的 pdf 图片文件,基本上避免了每次都进行完全重新编译。
一个小问题是它chemname
不再起作用了。有什么想法吗?
答案1
您不能将external
tikzlibrary 与 chemfig 一起使用,因为它的\tikzexternal@laTeX@collect@until@end@tikzpicture
宏在执行时\begin{tikzpicture}
会收集所有内容直到找到\end{tikzpicture}
。
external
当tikzlibrary 与 chemfig 一起使用时会出现一个问题,因为:
- 没有,
\end{tikzpicture}
但是\endtikpicture
; - 和
\begintikpicture
不\endtikpicture
属于同一个宏。
这会导致错误。可以通过在a和\chemfig{<code>}
之间包装 every 来修复此问题,但如果您有许多命令,则这需要时间。\begin{tikzpicture}
\end{tikspicture}
\chemfig
也可以修改 chemfig 代码使其自动执行:
\documentclass{article}
\usepackage{chemfig}
\usetikzlibrary{external}
\tikzexternalize
\makeatletter
\def\CF@chemfig@iii[#1][#2]{%
\edef\CF@tmp@str{\noexpand\begin{tikzpicture}[remember picture,every node/.style={anchor=base,inner sep=\z@,outer sep=\z@,minimum size=\z@\ifx\@empty#2\@empty\else,#2\fi},baseline\ifx\@empty#1\@empty\else,#1\fi]}%
\begingroup
\everyeof{\@nil}\endlinechar\m@ne
\CF@sanitize@catcode
\CF@chemfig@iv
}
\def\CF@chemfig@iv#1{%
\CF@tmp@str
\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\'ebut du dessin 1=trac\'e d'un noeud 2=trac\'e 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}%
\def\CF@default@angle{0}%
\def\CF@default@stringangle{:0}% angle pris par d\'efaut si le champ est vide
\def\CF@default@length{1}%
\let\CF@default@fromatom\@empty% numero de l'atome d'o\`u partent les liaisons par d\'efaut
\let\CF@default@toatom\@empty% num\'ero de l'atome o\`u arrivent les laisons par d\'efaut
\let\CF@default@tikz\@empty
\let\CF@previous@bondangle\empty
\let\CF@joinbond\z@
\let\CF@previous@tikz\empty
\expandafter\assign@tonil\expandafter\CF@remain@molecule\scantokens{#1}%
\expandafter\CF@chemfig@v\expandafter{\CF@remain@molecule}%
\end{tikzpicture}%
\endgroup
\let\CF@split@state\z@
}
\def\CF@chemfig@vi{%
\let\CF@next@action\CF@chemfig@vi% \`a priori, on reboucle
\ifx\CF@remain@molecule\@empty
\let\CF@next@action\empty
\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{-=<>~}% la suite est une liaison
{\ifnum\CF@last@action=\tw@% c'est la deuxi\`eme liaison cons\'ecutive ?
\CF@insert@emptygroup\CF@remain@molecule% ins\`ere 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
\ifnum\CF@cnt@cycle=\@ne
\let\CF@cycle@firsttikz\CF@current@tikz
\unless\ifx\CF@start@offset\@empty\let\CF@cycle@joinlast\z@\fi
\fi
\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\ifCF@incycle\else\ifCF@macrofixedbondlength.\CF@current@angle\fi\fi),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
\ifcat\relax\detokenize\expandafter{\romannumeral-`\.\expandafter\noexpand\CF@remain@molecule}\relax
% s'il ne reste plus rien apr\`es la liaison (sans tenir compte de l'espace devant)-> ins\`ere un groupe vide
\CF@insert@emptygroup\CF@remain@molecule
\fi
}%
{\edef\CF@bond@outnode{\CF@bond@outnode}% \'evalue le l'atome de d\'epart de liaison
\CF@ifx(\CF@toks@a% une parenth\`ese 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 \'etait dans un cycle
\CF@incyclefalse
\aftergroup\CF@chemfig@vi
\def\CF@next@action{\expandafter\CF@chemfig@v\expandafter{\CF@sub@mol}}%
\fi
}%
{\ifx\CF@remain@molecule\@empty
\let\CF@next@action\endgroup
\else% ce qui reste apr\`es le noeud courant n'est pas vide, ne commence pas par "-=~", ni par une parenth\`ese
\CF@ifx*\CF@toks@a% un cycle ?
{\ifnum\CF@last@action=\tw@
\CF@insert@emptygroup\CF@remain@molecule% ins\`ere un groupe vide
\else
\ifCF@incycle\let\CF@last@action\thr@@\fi% on \'etait dans un cycle
\ifnum\CF@last@action=\thr@@\let\CF@lastcycle@num\CF@cycle@num\fi
\CF@expafterarg@ntimes2\CF@if@firsttokmatch{\expandafter\@gobble\CF@remain@molecule}*% un 2\`e "*" ?
{\CF@expafterarg@ntimes2{\def\CF@remain@molecule}{\expandafter\@gobble\CF@remain@molecule}% enl\`eve la 1er \'etoile
\CF@expafterarg@ntimes2\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
\ifx\CF@hook@atomgroup\CF@empty@node
\let\CF@cycle@joinlast\@ne% joindre le dernier
\else
\let\CF@cycle@joinlast\z@
\fi
\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
\aftergroup\CF@chemfig@vi
\def\CF@next@action{\expandafter\CF@chemfig@v\expandafter{\CF@sub@mol}}%
\fi
}%
{\errmessage{Package \CF@package@name\space Error: something went wrong here: \detokenize\expandafter{\CF@remain@molecule}^^JIf 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
}
\makeatother
\begin{document}
\chemname{\chemfig{A=B-C-D}}{example}
\end{document}
您可以检查分子图像是否记录在<name of master file>-image0.pdf
当前目录中的 pdf 文件 ( ) 中。以下是输出:
不过还有一个小问题...由于 a 的边界框C
比其轮廓小,因此裁剪得external
太紧:
为了解决这个问题,您可以增加inner sep
并将其设置为1pt
而不是\z@
(即0pt
):
\edef\CF@tmp@str{\noexpand\begin{tikzpicture}[remember picture,every node/.style={anchor=base,inner sep=1pt,outer sep=\z@,minimum size=\z@\ifx\@empty#2\@empty\else,#2\fi},baseline\ifx\@empty#1\@empty\else,#1\fi]}%