众所周知,tikzexternalize 和 tikz-cd 不能很好地互相配合:TikZ 库 cd 和 external 是否彼此不兼容?。现在,我有一个 tikzcd,其条目是 tikzpictures。我能以某种方式将 tikz-cd 中的图片外部化吗?
\documentclass{scrartcl}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,tikz-cd,xstring}
\newcommand{\FilteredBall}[1][abcfghxy]{
\begin{tikzpicture}[every node/.append style={inner sep=1pt}, baseline={(0,-0.2)}]%(current bounding box.center)]
%\fill[white] (0,0) circle (2);
\begin{scope}[gray]
\draw[dashed] (2,0) arc (0:180:2 and 0.6);
\draw (0,0) circle (2) ;
\draw (-2,0) arc (180:360:2 and 0.6);
\end{scope}
\begin{scope}[opacity=.5]
\IfSubStr{#1}{f}{
\begin{scope}
\clip (0,2) arc (90:-90:2) arc (-90:90:.6 and 2);
\shade[ball color=red!70] (0,0) circle[radius=2];
\end{scope}
\begin{scope}
\clip (0,2) arc (90:-90:2) arc (-90:90:1.2 and 2);
\shade[ball color=red!70] (0,0) circle[radius=2];
\end{scope}
}{}
\IfSubStr{#1}{g}{
\begin{scope}
\clip (0,2) arc (90:-90:-2 and 2) arc (-90:90:.6 and 2);
\shade[ball color=blue!60] (0,0) circle[radius=2];
\end{scope}
\begin{scope}
\clip (0,2) arc (90:-90:-2 and 2) arc (-90:90:-1.3 and 2);
\shade[ball color=blue!60] (0,0) circle[radius=2];
\end{scope}
}{}
\IfSubStr{#1}{h}{
\begin{scope}
\clip (0,2) arc (90:-90:-1.2 and 2) arc (-90:90:1.2 and 2);
\shade[ball color=green!70] (0,0) circle[radius=2];
\end{scope}
}{}
\end{scope}
\begin{scope}[thick]
\IfSubStr{#1}{a}{\draw[red] (0,2) arc (90:-90:-1.3 and 2) node[below left, pos=.9] {$a$};}{}
\IfSubStr{#1}{b}{\draw[blue] (0,2) arc (90:-90:1.2 and 2) node[below right, pos=.9] {$b$};}{}
\IfSubStr{#1}{c}{
\IfSubStr{#1}{h}{
\draw[Aqua, densely dotted] (0,2) arc (90:270:-0.6 and 2) node[left=-2pt, midway] {$c$};
}{
\draw[Aqua] (0,2) arc (90:270:-0.6 and 2) node[left=-2pt, midway] {$c$};
}
}{}
\end{scope}
\IfSubStr{#1}{x}{\fill (0,2) circle (0.15);}{}
\IfSubStr{#1}{y}{\fill (0,-2) circle (0.15);}{}
\path
(0,2) arc (90:-90:2) node[text=red, pos=.4, above right] {\IfSubStr{#1}{f}{$f$}{\phantom{{$f$}}}}
(0,2) arc (90:-90:-2 and 2) node[text=blue!50!black, pos=.6,, below left] {\IfSubStr{#1}{g}{$g$}{\phantom{{$g$}}}}
(-.4, .65) node[text=green!50!black] {\IfSubStr{#1}{h}{$h$}{\phantom{{$h$}}}}
(0,2) node[above] {\IfSubStr{#1}{x}{$x$}{\phantom{{$x$}}}}
(0,-2) node[below] {\IfSubStr{#1}{y}{$y$}{\phantom{{$y$}}}};
\end{tikzpicture}
}
\begin{document}
\begin{equation}
\tikzset{every node/.append style={outer sep=2pt}, x=2mm, y=2mm}
\begin{tikzcd}[row sep=tiny, column sep=tiny]
\FilteredBall[xya] \rar["\subseteq", phantom] &
\FilteredBall[xyabh] \rar["\subseteq", phantom] &
\FilteredBall[xyabchg] \rar["\subseteq", phantom] &
\FilteredBall[xyabcfgh]
\\
\FilteredBall[xya] \rar["\subseteq", phantom] &
\FilteredBall[xyab] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyabcg] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyabcfg] \uar["\subseteq", phantom, sloped] &
\\
\FilteredBall[xy] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyb] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xybc] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xybcf] \uar["\subseteq", phantom, sloped] \\
\FilteredBall[xy] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xy] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped]&
\FilteredBall[xyc] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyc] \uar["\subseteq", phantom, sloped].
\end{tikzcd}
\end{equation}
\end{document}
编辑 以下代码基于 Qrrbrbirlbel 的回答,试图将图片与数学混合在一起。红色水平箭头显然是错误的,应该与黑色箭头相同:
\documentclass{scrartcl}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,tikz-cd,xstring}
\usetikzlibrary{fit, external}
%\tikzexternalize
\makeatletter
\pgfkeys{% https://tex.stackexchange.com/a/665688/16595
/utils/temp/.initial/.expand once=\tikzcd,
/utils/temp/.prefix=\ifx\path\tikz@command@path % we're inside a tikzpicture
\let\tikzpicture\scope
\let\endtikzpicture\endscope
\else % we're not inside a tikzpicture, disable externalizing
\tikzexternaldisable
\fi,/utils/temp/.get=\tikzcd}
\makeatother
\tikzset{
cd vcenter/.style={baseline={([yshift=-axis_height]\tikzcdmatrixname)}},
matrix bb node/.style={
fit=(current bounding box), inner sep=0pt,%inner sep=+.3333em,
outer sep=+0pt, shape=rectangle, draw,%path only,
name=\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn},
add bb node/.style={execute at end cell={\node[draw,matrix bb node]{};}}}
\tikzcdset{
no matrix of nodes/.style={
/tikz/add bb node,
/tikz/matrix of nodes/.code=,
/tikz/matrix of math nodes/.code=}}
\newcommand{\FilteredBall}[1][abcfghxy]{
% \tikzset{}
%\fill[white] (0,0) circle (2);
\begin{scope}[every node/.append style={inner sep=2pt}]
\begin{scope}[gray]
\draw[dashed] (2,0) arc (0:180:2 and 0.6);
\draw (0,0) circle (2) ;
\draw (-2,0) arc (180:360:2 and 0.6);
\end{scope}
\begin{scope}[opacity=.5]
\IfSubStr{#1}{f}{
\begin{scope}
\clip (0,2) arc (90:-90:2) arc (-90:90:.6 and 2);
\shade[ball color=red!70] (0,0) circle[radius=2];
\end{scope}
\begin{scope}
\clip (0,2) arc (90:-90:2) arc (-90:90:1.2 and 2);
\shade[ball color=red!70] (0,0) circle[radius=2];
\end{scope}
}{}
\IfSubStr{#1}{g}{
\begin{scope}
\clip (0,2) arc (90:-90:-2 and 2) arc (-90:90:.6 and 2);
\shade[ball color=blue!60] (0,0) circle[radius=2];
\end{scope}
\begin{scope}
\clip (0,2) arc (90:-90:-2 and 2) arc (-90:90:-1.3 and 2);
\shade[ball color=blue!60] (0,0) circle[radius=2];
\end{scope}
}{}
\IfSubStr{#1}{h}{
\begin{scope}
\clip (0,2) arc (90:-90:-1.2 and 2) arc (-90:90:1.2 and 2);
\shade[ball color=green!70] (0,0) circle[radius=2];
\end{scope}
}{}
\end{scope}
\begin{scope}[thick]
\IfSubStr{#1}{a}{\draw[red] (0,2) arc (90:-90:-1.3 and 2) node[below left, pos=.9] {$a$};}{}
\IfSubStr{#1}{b}{\draw[blue] (0,2) arc (90:-90:1.2 and 2) node[below right, pos=.9] {$b$};}{}
\IfSubStr{#1}{c}{
\IfSubStr{#1}{h}{
\draw[Aqua, densely dotted] (0,2) arc (90:270:-0.6 and 2) node[left=-2pt, midway] {$c$};
}{
\draw[Aqua] (0,2) arc (90:270:-0.6 and 2) node[left=-2pt, midway] {$c$};
}
}{}
\end{scope}
\IfSubStr{#1}{x}{\fill (0,2) circle (0.15);}{}
\IfSubStr{#1}{y}{\fill (0,-2) circle (0.15);}{}
\path
(0,2) arc (90:-90:2) node[text=red, pos=.4, above right] {\IfSubStr{#1}{f}{$f$}{\phantom{{$f$}}}}
(0,2) arc (90:-90:-2 and 2) node[text=blue!50!black, pos=.6,, below left] {\IfSubStr{#1}{g}{$g$}{\phantom{{$g$}}}}
(-.4, .65) node[text=green!50!black] {\IfSubStr{#1}{h}{$h$}{\phantom{{$h$}}}}
(0,2) node[above] {\IfSubStr{#1}{x}{$x$}{\phantom{{$x$}}}}
(0,-2) node[below] {\IfSubStr{#1}{y}{$y$}{\phantom{{$y$}}}};
\end{scope}
}
\begin{document}
\begin{equation}
\begin{tikzpicture}[x=2mm, y=2mm, cd vcenter]
\begin{tikzcd}[row sep=tiny, column sep=tiny, no matrix of nodes]
\FilteredBall[xya] \rar["\subseteq", phantom] &
\FilteredBall[xyabh] \rar["\subseteq", phantom] &
\FilteredBall[xyabchg] \rar["\subseteq", phantom] &
\FilteredBall[xyabcfgh]
\\
\FilteredBall[xya] \rar["\subseteq", phantom] &
\FilteredBall[xyab] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyabcg] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyabcfg] \uar["\subseteq", phantom, sloped] &
\\
\FilteredBall[xy] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyb] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xybc] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xybcf] \uar["\subseteq", phantom, sloped] \\
\node[name=A]{$0_{0_{0_0}}$}; \rar[red] \uar &
\node[name=B]{$0^{0^{0^0}}$}; \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped]&
% \FilteredBall[xy] \draw (current bounding box.base) node (B){} circle(2pt); \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped]&
\FilteredBall[xyc] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyc] \uar["\subseteq", phantom, sloped].
\ar[from=A, to=B]
\end{tikzcd}
\end{tikzpicture}
\end{equation}
\end{document}
答案1
由于您实际上并不使用matrix of (math) nodes
该 TikZ-CD 安装,因此我会禁用它,然后您可以\FilteredBall
在每个单元格中使用您的,而不必使用嵌套tikzpictures
。使用我的答案到如何解决 tikz-cd 与外部不兼容的问题您可以将环境放入可以外部化的tikzcd
内部。tikzpicture
我添加了以下/tikz/cd vcenter
密钥我的答案到花括号之间的 TikZcd 存在问题使得矩阵垂直居中。
fit
在每个具有适当名称的单元格末尾创建一个带有库的节点,以便 TikZ-CD 用 绘制“箭头” \subseteq
。此节点围绕单元格的当前边界框,封装单元格中尚未使用选项 绘制的所有内容overlay
。
由于您phantom
已将每个节点都设为相同大小,因此所有单元格都具有相同的大小,因此只需这样做即可使箭头正交绘制。如果单元格大小不相同,则这将稍微复杂一些。
调整该节点的inner xsep
/或/以获得球之间的正确间距。inner ysep
row sep
column sep
更新
由于我们已禁用,因此此 TikZ-CD 内的普通节点现在不太可用matrix of (math) nodes
。不过,当使用单元格内的非唯一节点时,它们并不容易解决,这仍然是可能的,但单元格中的任何内容都需要以\path
或它的某些变体开头。允许可选参数并以 开头的命令在这里不起作用。(不过,在某些情况下,在开头\begin{scope}
有一个空的会有所帮助。)\path;
在这里我们使用一个普通的\node
但带有键的方法matrix node
,以便它应用 TikZ-CD 期望的正确命名方案来与其\arrow
命令一起工作。
TikZ-CD 设置了自己的形状,该形状具有一个固定高度高于基线的asymmetrical rectangle
欺骗性锚点,在放置节点时,其作用与锚点非常相似。我相信这对您而言是可取的,并且不会改变它。形状的真正力量来自于连接节点,其中水平线指向该假中心锚点,该锚点现在与正常数学模式箭头的高度相同(也是括号尖端的位置)。center
axis_height
mid
asymmetrical rectangle
{}
如果单元格仅具有普通节点(TikZ-CD 也应如此使用),则必须使用密钥no bb node
暂时禁用它。好吧,它将变成一个未命名的坐标,但这几乎是一样的。真正禁用它需要更多工作。
说到边界框节点。我添加了一个特殊fit
键来调整 Case 2 的边界框节点我自己的答案在细胞内安装一个asymmetrical rectangle
包裹一切但水平对称于细胞中心的装置,并center
在细胞中心有自己的锚点——包括在是方向,这就是为什么它也要axis_height
考虑。这是必要的,以便垂直箭头真正垂直。
代码
\documentclass{scrartcl}
\usepackage[svgnames]{xcolor}
\usepackage{tikz,tikz-cd,xstring}
\usetikzlibrary{fit, external}
%\tikzexternalize
\makeatletter
\tikzcdset{
fit/.code={% tikz-cd uses an asymmetrical rectangle …
\pgf@process{\pgfpointanchor{\tikz@pp@name{#1}}{east}}\pgf@xa=2\pgf@x
\pgf@process{\pgfpointanchor{\tikz@pp@name{#1}}{west}}\pgf@x=-2\pgf@x
\ifdim\pgf@xa>\pgf@x \pgf@x=\pgf@xa \fi
\pgfkeysalso{/tikz/text width/.expanded=+\the\pgf@x}%
\pgf@process{\pgfpointdiff{\pgfpointanchor{\tikz@pp@name{#1}}{south}}
{\pgfpointanchor{\tikz@pp@name{#1}}{north}}}%
\pgf@ya=.5\pgf@y \pgf@yb=\pgf@ya
\pgfmathaddtolength\pgf@ya{axis_height}%
\pgfmathaddtolength\pgf@yb{-axis_height}%
\pgfkeysalso{/tikz/text height/.expanded=+\the\pgf@ya,
/tikz/text depth/.expanded=+\the\pgf@yb}},
/utils/temp/.initial/.expand once=\tikzcd,
/utils/temp/.prefix=% https://tex.stackexchange.com/a/665688/16595
\ifx\path\tikz@command@path
\let\tikzpicture\scope \let\endtikzpicture\endscope
\else \tikzexternaldisable \fi,/utils/temp/.get=\tikzcd}
\makeatother
\tikzset{
matrix node/.style={
name=\tikzmatrixname-\the\pgfmatrixcurrentrow-\the\pgfmatrixcurrentcolumn},
cd vcenter/.style={baseline={([yshift=-axis_height]\tikzcdmatrixname)}},
matrix bb node/.style={
commutative diagrams/fit=current bounding box, inner sep=0pt,
outer sep=+0pt, shape=asymmetrical rectangle, path only, matrix node},
add bb node/.style={execute at end cell={\node[matrix bb node]{};}},
no bb node/.style={matrix bb node/.style={shape=coordinate}}}
\tikzcdset{
no matrix of nodes/.style={
/tikz/add bb node,
/tikz/matrix of nodes/.code=,
/tikz/matrix of math nodes/.code=}}
\newcommand{\FilteredBall}[1][abcfghxy]{
% \tikzset{}
%\fill[white] (0,0) circle (2);
\begin{scope}[every node/.append style={inner sep=2pt}]
\begin{scope}[gray]
\draw[dashed] (2,0) arc (0:180:2 and 0.6);
\draw (0,0) circle (2) ;
\draw (-2,0) arc (180:360:2 and 0.6);
\end{scope}
\begin{scope}[opacity=.5]
\IfSubStr{#1}{f}{
\begin{scope}
\clip (0,2) arc (90:-90:2) arc (-90:90:.6 and 2);
\shade[ball color=red!70] (0,0) circle[radius=2];
\end{scope}
\begin{scope}
\clip (0,2) arc (90:-90:2) arc (-90:90:1.2 and 2);
\shade[ball color=red!70] (0,0) circle[radius=2];
\end{scope}
}{}
\IfSubStr{#1}{g}{
\begin{scope}
\clip (0,2) arc (90:-90:-2 and 2) arc (-90:90:.6 and 2);
\shade[ball color=blue!60] (0,0) circle[radius=2];
\end{scope}
\begin{scope}
\clip (0,2) arc (90:-90:-2 and 2) arc (-90:90:-1.3 and 2);
\shade[ball color=blue!60] (0,0) circle[radius=2];
\end{scope}
}{}
\IfSubStr{#1}{h}{
\begin{scope}
\clip (0,2) arc (90:-90:-1.2 and 2) arc (-90:90:1.2 and 2);
\shade[ball color=green!70] (0,0) circle[radius=2];
\end{scope}
}{}
\end{scope}
\begin{scope}[thick]
\IfSubStr{#1}{a}{\draw[red] (0,2) arc (90:-90:-1.3 and 2) node[below left, pos=.9] {$a$};}{}
\IfSubStr{#1}{b}{\draw[blue] (0,2) arc (90:-90:1.2 and 2) node[below right, pos=.9] {$b$};}{}
\IfSubStr{#1}{c}{
\IfSubStr{#1}{h}{
\draw[Aqua, densely dotted] (0,2) arc (90:270:-0.6 and 2) node[left=-2pt, midway] {$c$};
}{
\draw[Aqua] (0,2) arc (90:270:-0.6 and 2) node[left=-2pt, midway] {$c$};
}
}{}
\end{scope}
\IfSubStr{#1}{x}{\fill (0,2) circle (0.15);}{}
\IfSubStr{#1}{y}{\fill (0,-2) circle (0.15);}{}
\path
(0,2) arc (90:-90:2) node[text=red, pos=.4, above right] {\IfSubStr{#1}{f}{$f$}{\phantom{{$f$}}}}
(0,2) arc (90:-90:-2 and 2) node[text=blue!50!black, pos=.6,, below left] {\IfSubStr{#1}{g}{$g$}{\phantom{{$g$}}}}
(-.4, .65) node[text=green!50!black] {\IfSubStr{#1}{h}{$h$}{\phantom{{$h$}}}}
(0,2) node[above] {\IfSubStr{#1}{x}{$x$}{\phantom{{$x$}}}}
(0,-2) node[below] {\IfSubStr{#1}{y}{$y$}{\phantom{{$y$}}}};
\end{scope}
}
\begin{document}
\begin{equation}
\begin{tikzpicture}[x=2mm, y=2mm, cd vcenter]
\begin{tikzcd}[row sep=tiny, column sep=tiny, no matrix of nodes]
\FilteredBall[xya] \rar["\subseteq", phantom] &
\FilteredBall[xyabh] \rar["\subseteq", phantom] &
\FilteredBall[xyabchg] \rar["\subseteq", phantom] &
\FilteredBall[xyabcfgh]
\\
\FilteredBall[xya] \rar["\subseteq", phantom] &
\FilteredBall[xyab] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyabcg] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyabcfg] \uar["\subseteq", phantom, sloped] &
\\
\FilteredBall[xy] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyb] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xybc] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xybcf] \uar["\subseteq", phantom, sloped] \\
\tikzset{no bb node} \node[matrix node]{$0_{0_{0_0}}$}; \rar[red] \uar &
\tikzset{no bb node} \node[matrix node]{$0^{0^{0^0}}$}; \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped]&
%& \FilteredBall[xy] \draw (current bounding box.base) node (B){} circle(2pt); \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped]&
\FilteredBall[xyc] \rar["\subseteq", phantom] \uar["\subseteq", phantom, sloped] &
\FilteredBall[xyc] \uar["\subseteq", phantom, sloped].
\end{tikzcd}
\end{tikzpicture}
\end{equation}
\end{document}