有没有办法将TikZ
库cd
和external
一起使用?
这不起作用:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{cd, external}
\tikzexternalize
\begin{document}
\begin{tikzcd}
A \arrow[rd] \arrow[r, "\varphi"] & B \\ & C
\end{tikzcd}
\end{document}
错误:
Runaway argument?
! File ended while scanning use of \tikzexternal@laTeX@collect@until@end@tikzpicture.
我正在使用TikZ/PGF
版本 3.0.0 和tikz-cd
版本 0.9b。
答案1
这个问题和环境扩展和 Tikz 外部库的问题。因为 TeX 看不到\end{tikzpicture}
内部\end{tikzcd}
。解决方案环境扩展和 Tikz 外部库的问题。是将所有内容打包在宏中,以确保在 TeX 开始吞噬之前扩展自定义的环境结束,从而\end{tikzpicture}
显示隐藏的内容。 上面问题中的改编并不相同,因为它添加了一个额外的内容\end{tikzpicture}
而不是解压隐藏的内容,这会导致 TikZ 图片嵌套,这不是一个好主意。
(尽管如此,仅仅因为某件事不是一个好主意,并不意味着它不是最好的主意,只是应该极其谨慎地使用它。)
如果您的所有图片都是tikzcd
环境,那么似乎正确的解决方案可能是告诉 TeX 查找tikzcd
而不是tikzpicture
。这是一个合理的尝试,因为第一件事\begin{tikzcd}
是启动一个tikzpicture
,最后一件事是结束它。但是,我尝试将外部化代码中的\end{tikzcd}
所有 s 更改为 的实验没有成功,所以我暂时放弃了这个(最好是对适用于 的外部化库进行改编tikzpicture
tikzcd
任何环境,而不仅仅是tikzpicture
s)。
这是您对我对链接问题的回答的改编,它不是将环境包装tikzcd
在 中,而是tikzpicture
简单地暴露内部tikzpicture
。好吧,除了它没有,因为内部tikzpicture
写为\tikzpicture ... \endtikzpicture
不匹配,所以我们必须重新定义tikzcd
环境以将\tikzpicture
和\endtikzpicture
变成\begin{tikzpicture}
和\end{tikzpicture}
。它并不优雅,但它确实避免了嵌套问题。
\documentclass{article}
%\url{https://tex.stackexchange.com/q/171931/86}
\usepackage{tikz}
\usepackage{environ}
\usetikzlibrary{cd,external}
\tikzexternalize
\makeatletter
\def\tikzcd@[#1]{%
\begin{tikzpicture}[/tikz/commutative diagrams/.cd,every diagram,#1]%
\ifx\arrow\tikzcd@arrow%
\pgfutil@packageerror{tikz-cd}{Diagrams cannot be nested}{}
\fi%
\let\arrow\tikzcd@arrow%
\let\ar\tikzcd@arrow%
\def\rar{\tikzcd@xar{r}}%
\def\lar{\tikzcd@xar{l}}%
\def\dar{\tikzcd@xar{d}}%
\def\uar{\tikzcd@xar{u}}%
\def\urar{\tikzcd@xar{ur}}%
\def\ular{\tikzcd@xar{ul}}%
\def\drar{\tikzcd@xar{dr}}%
\def\dlar{\tikzcd@xar{dl}}%
\global\let\tikzcd@savedpaths\pgfutil@empty%
\matrix[/tikz/matrix of \iftikzcd@mathmode math \fi nodes,
/tikz/every cell/.append code={\tikzcdset{every cell}},
/tikz/commutative diagrams/.cd,every matrix]%
\bgroup}
\def\endtikzcd{%
\pgfmatrixendrow\egroup%
\pgfextra{\global\let\tikzcdmatrixname\tikzlastnode};%
\tikzcdset{\the\pgfmatrixcurrentrow-row diagram/.try}%
\begingroup%
\tikzcd@enablequotes%
\tikzcd@patcherrmsg%
\tikzcd@savedpaths%
\endgroup%
\end{tikzpicture}%
\ifnum0=`{}\fi}
\NewEnviron{mytikzcd}[1][]{%
\def\@temp{\tikzcd@[#1]\BODY}%
\expandafter\@temp\endtikzcd
}
\makeatother
\def\temp{&} \catcode`&=\active \let&=\temp
\begin{document}
\begin{mytikzcd}
A \arrow{rd} \arrow{r}{\phi} & B \\ & C
\end{mytikzcd}
\begin{mytikzcd}
A \arrow{rd} \arrow{r}{\phi} & B \\ & C
\end{mytikzcd}
\end{document}
答案2
当我最初回答这个问题时,external
是唯一可用的选项。幸运的是,现在情况不再如此。您附近的 CTAN 镜像现在提供两个新的外部化选项:memoize
和robust-externalize
。
这是一个使用的解决方案memoize
,tikzcd
设置得益于memoize
的作者。
\documentclass{article}
\usepackage{memoize}
\mmzset{%
path={dir=memos},
mkdir,
% Sašo Živanović: https://chat.stackexchange.com/transcript/message/64689784#64689784
auto={tikzcd}{memoize,verbatim},
}
\usepackage{tikz}
\usetikzlibrary{cd}
\begin{document}
\begin{tikzpicture}
\node at (0,0) {node};
\end{tikzpicture}
\begin{tikzcd}
A \arrow[rd] \arrow[r, "\varphi"] & B \\ & C
\end{tikzcd}
\end{document}
经过一次编译后,图像将成memoized
为主 PDF 制作的一部分。此时,它们除了在文档中的适当位置生成外,还显示为额外页面。
在第二次编辑中,外部人员被提取到单独的 PDF 文件中,现在包含在主 PDF 中,无需重新编译。只有当图像代码发生变化或满足某些进一步条件时,才会重新编译图像代码。(例如,如果您删除 PDF 或指示重新memoize
编译或其他。)
原始答案
此解决方案不允许您外部化使用tikzcd
环境生成的图表,但允许您外部化其他 tikz
图片在您的文档中。它基于tikz
手册第 50.8.2 节(第 627-8 页)中提到的解决方法。为了使其使用更方便,etoolbox
用于修补tikzcd
环境。本质上,这会在环境开始时关闭外部化tikzcd
,然后在环境结束时将其重新打开。
\documentclass{article}
\usepackage{etoolbox,tikz}
\usetikzlibrary{external}
\tikzexternalize
\usetikzlibrary{cd}
\AtBeginEnvironment{tikzcd}{\tikzexternaldisable}
\AtEndEnvironment{tikzcd}{\tikzexternalenable}
\begin{document}
\begin{tikzpicture}
\node at (0,0) {node};
\end{tikzpicture}
\begin{tikzcd}
A \arrow[rd] \arrow[r, "\varphi"] & B \\ & C
\end{tikzcd}
\end{document}
第一次运行时,pdflatex --shell-escape <filename>.tex
包括以下输出:
===== 'mode=convert with system call': Invoking 'pdflatex -shell-escape -halt-o
n-error -interaction=batchmode -jobname "<filename>-figure0" "\def\tikzexternalreal
job{<filename>}\input{<filename>}"' ========
<filename>-figure0.pdf
看起来像这样:
后续运行包括输出:
===== Image '<filename>-figure0' is up-to-date. ======
PDF 将外部化的图像与动态<filename>-figure0.pdf
生成的图像结合在一起:tikzcd
这有多大帮助取决于你的图片所占的比例tikzcd
。如果答案是 100%,那显然毫无用处。另一方面,如果答案低于 100%,那可能还是有用的。
答案3
以下是一个与external
库配合使用的解决方案,我之前从未想到过。
我们可以将tikzcd
环境放在 的节点内tizkpicture
:
\begin{tikzpicture}
\node {\begin{tikzcd}
A \arrow[rd] \arrow[r, "\varphi"] & B \\ & C
\end{tikzcd}};
\end{tikzpicture}
为了获得正确的间距和对齐,以下选项似乎有效:
\begin{tikzpicture}[baseline=(current bounding box.west)]
\node[inner sep=0, outer sep=0] {\begin{tikzcd}
A \arrow[rd] \arrow[r, "\varphi"] & B \\ & C
\end{tikzcd}};
\end{tikzpicture}
\documentclass{article}
\usepackage{tikz, environ}
\usetikzlibrary{cd, external}
\tikzexternalize
\def\temp{&} \catcode`&=\active \let&=\temp
\NewEnviron{mycd}[1][]{%
\begin{tikzpicture}[baseline=(current bounding box.west)]
\node[inner sep=0, outer sep=0] {\begin{tikzcd}[#1]
\BODY
\end{tikzcd}};
\end{tikzpicture}}
\begin{document}
\begin{equation}
\begin{mycd}[row sep=huge]
A \arrow[rd] \arrow[r, "\varphi"] & B \\ & C
\end{mycd}
\end{equation}
\end{document}
我仍然觉得这很卑鄙。有没有更好的解决方案?
答案4
我必须调整马可·瓦里斯科的答案,以便在更改时自动重建图形。此外,我让人造 tikzpicture 的基线位于 tikzcd 基线的高度上。
\documentclass{article}
\usepackage{tikz, environ, etoolbox}
\usetikzlibrary{cd, external}
\tikzexternalize
% activate the following such that you can check the macro expansion in
% *-figure0.md5 manually
%\tikzset{external/up to date check=diff}
\def\temp{&} \catcode`&=\active \let&=\temp
\newcommand{\mytikzcdcontext}[2]{
\begin{tikzpicture}[baseline=(maintikzcdnode.base)]
\node (maintikzcdnode) [inner sep=0, outer sep=0] {\begin{tikzcd}[#2]
#1
\end{tikzcd}};
\end{tikzpicture}}
\NewEnviron{mytikzcd}[1][]{%
% In the following, we need \BODY to expanded before \mytikzcdcontext
% such that the md5 function gets the tikzcd content with \BODY expanded.
% Howerver, expand it only once, because the \tikz-macros aren't
% defined at this point yet. The same thing holds for the arguments to
% the tikzcd-environment.
\def\myargs{#1}%
\edef\mydiagram{\noexpand\mytikzcdcontext{\expandonce\BODY}{\expandonce\myargs}}%
\mydiagram%
}
\begin{document}
\begin{equation}
\begin{mytikzcd}[row sep=huge,baseline = (B.base)]
A \arrow[rd] \arrow[r, "\varphi"] & |[alias=B]| B \\ & C
\end{mytikzcd}
\hbox{sharing a baseline with } B
\end{equation}
\end{document}