tikzmark 和 tikzexternalize 不兼容吗?

tikzmark 和 tikzexternalize 不兼容吗?

下面是使用 tikzmark 绘制连接树中两个子节点的箭头的 MWE:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{external}
%\tikzexternalize
\usetikzlibrary{tikzmark}
\begin{document}

\begin{tikzpicture} 
  \node {A} 
    child {node {\subnode{end}{B}}}
    child {node {C \subnode{start}{B} E}}; 
\end{tikzpicture}

\begin{tikzpicture}[
  remember picture,
  overlay]
  \draw[->] (start.south) to [out=south west,in=south east] (end.south);
\end{tikzpicture}

\end{document}

正如预期的那样,这会产生以下输出(使用 调用pdflatex-shell-escape

tikzmark 作品

但是,如果%\tikzexternalize取消注释,编译就会失败,并出现以下错误:

! Package pgf Error: No shape named start is known.

tikzmark 和 tikz externalize 是否不兼容?如果是,它们是否从根本上不相容?

编辑后添加:如果从根本上不兼容,是否有其他方法可以执行类似这篇文章中的图像的操作 - 即用(例如)箭头瞄准子节点?

答案1

这是适用于您给出的示例的一种有点黑客的方法。尝试一些更复杂的方法,看看它有多强大。

第一个问题是,当外部化时,TikZ 会调用\nofiles,因此不会将任何内容写入辅助文件。由于tikzmark依赖于写入辅助文件的内容,因此这对于使其与外部化配合使用是一个相当大的障碍。为了实现这一点,我们窃取了https://tex.stackexchange.com/a/75030/86,这也意味着我们在外化时必须使用list and make而不是system call

但这并不能解决所有问题,因为即使将内容写入辅助文件,它也不会正确写入。偏移量可能是由于页面裁剪造成的,但也可能完全是由于其他原因造成的。幸运的是,它是一致的。所以我们需要做的是将子节点放在某个已知的地方(例如,在原点),然后使用它来计算偏移量。然后我们可以根据这个偏移量调整所有其他子节点。

为了避免冲突,我定义了一个新的子节点命令\extsubnode来执行此调整。

\documentclass{article}
%\url{https://tex.stackexchange.com/q/255543/86}
\usepackage{tikz}
\usetikzlibrary{external}
\let\oldnofiles=\nofiles
\let\nofiles=\relax
\tikzexternalize[mode=list and make]
\let\nofiles=\oldnofiles

\usetikzlibrary{tikzmark}

\makeatletter

\tikzset{
  every picture/.style={
    execute at begin picture={%
      \edef\outermostid{\pgfpictureid}%
      \node {\subnode{origin\outermostid}{}};
    }
  }
}

\newcommand\extsubnode[3][]{%
  \begingroup
  \pgfmark{#2}%
  \setbox\pgfnodeparttextbox=\hbox\bgroup #3\egroup
  \def\tikz@shape{rectangle}%
  \def\tikz@anchor{center}%
  \def\tikz@fig@name{#2}%
  \tikzset{every subnode/.try,#1}%
  \pgfpointorigin
  % there is a spurious space inserted by the next point scan so we
  % box it to ignore it
  \setbox\tikz@tempbox=\hbox\bgroup
  \tikz@scan@one@point\pgfutil@firstofone(origin\outermostid)\relax
  \global\pgf@xa=\pgf@x
  \global\pgf@ya=\pgf@y
  \egroup
  \tikz@scan@one@point\pgfutil@firstofone(pic cs:#2)\relax
  \advance\pgf@x by -\pgf@xa
  \advance\pgf@y by -\pgf@ya
  \advance\pgf@x by .5\wd\pgfnodeparttextbox
  \advance\pgf@y by .5\ht\pgfnodeparttextbox
  \advance\pgf@y by -.5\dp\pgfnodeparttextbox
  \pgftransformshift{}%
  \setbox\@tempboxa=\hbox\bgroup
  \pgfutil@ifundefined{pgf@sh@s@\tikz@shape}%
  {\PackageError{pgf}{Unknown shape ``\tikz@shape''}{}}%
  {%
    {%
      \let\pgf@sh@savedmacros=\pgfutil@empty% MW
      \let\pgf@sh@savedpoints=\pgfutil@empty%
      \def\pgf@sm@shape@name{\tikz@shape}% CJ % TT added prefix!
      \csname pgf@sh@s@\tikz@shape\endcsname%
      \pgf@sh@savedpoints%
      \pgf@sh@savedmacros% MW
      \pgftransformshift{%
        \pgf@sh@reanchor{\tikz@shape}{\tikz@anchor}%
        \pgf@x=-\pgf@x%
        \pgf@y=-\pgf@y%
      }%
      \expandafter\pgfsavepgf@process\csname pgf@sh@sa@\tikz@fig@name\endcsname{%
       \pgf@sh@reanchor{\tikz@shape}{\tikz@anchor}% FIXME : this is double work!
      }%
      % Save the saved points and the transformation matrix
      \edef\pgf@node@name{\tikz@fig@name}%
      \ifx\pgf@node@name\pgfutil@empty%
      \else%
        \expandafter\xdef\csname pgf@sh@ns@\pgf@node@name\endcsname{\tikz@shape}%
        \edef\pgf@sh@@temp{\noexpand\gdef\expandafter\noexpand\csname pgf@sh@np@\pgf@node@name\endcsname}%
        \expandafter\pgf@sh@@temp\expandafter{\pgf@sh@savedpoints}%
        \edef\pgf@sh@@temp{\noexpand\gdef\expandafter\noexpand\csname pgf@sh@ma@\pgf@node@name\endcsname}% MW
        \expandafter\pgf@sh@@temp\expandafter{\pgf@sh@savedmacros}% MW
        \pgfgettransform\pgf@temp
        \expandafter\xdef\csname pgf@sh@nt@\pgf@node@name\endcsname{\pgf@temp}%
        \expandafter\xdef\csname pgf@sh@pi@\pgf@node@name\endcsname{\pgfpictureid}%
      \fi%
    }%
  }%
  \egroup
  \box\pgfnodeparttextbox
  \endgroup
}


\makeatother



\begin{document}

\begin{tikzpicture}
  \node {A} 
    child {node[draw] {\extsubnode{end}{B}}}
    child {node {C\extsubnode{start}{B}E}}; 
  \draw[->] (start.south) to [out=south
      west,in=south east] (end.south);
\end{tikzpicture}

\end{document}

答案2

已提交供您参考。下面是一个 MWE,通过使用standalone代替 ,效果非常接近external。主文件 ( test.tex) 如下所示:

\documentclass{article}
\usepackage[mode=buildnew]{standalone}
\begin{document} 
\includestandalone{tree}
\end{document}

tree.tex像这样(基本上粘贴了 Gonzalo Medina 给出的答案这里):

\documentclass[border=20pt]{standalone}

%necessary for tikzmark and xetex to play nicely
\newcount\pdftexversion
\pdftexversion140 \def\pgfsysdriver{pgfsys-dvipdfm.def}

\usepackage{forest}
\usetikzlibrary{tikzmark}
\begin{document}

\begin{forest}
for tree={s sep=20pt}
[A t\subnode{endc}{e}st text
  [B
    [\subnode{enda}{C},
    ] 
  ]
  [D
    [\subnode{endb}{E}
    ]
    [\subnode{startc}{F}
      [G
      ]
      [H
        [\subnode{startb}{John} see \subnode{starta}{x}
        ]
      ] 
    ]
  ] 
]
\end{forest}

\begin{tikzpicture}[
  remember picture,
  overlay,
  >=latex
]
\draw[cyan,thick,->]
  (starta.south) --
  ++(0pt,-10pt) -| 
  (enda.south);
\draw[red!80!black,thick,->]
  (startb.south) --
  ++(0pt,-5pt) -| 
  (endb.south);
\draw[green!80!black,thick,->]
  (startc) to[out=60,in=90,looseness=1.4]
  (endc.north);
\end{tikzpicture}

\end{document}

(这border=20pt是必要的,因为standalone没有考虑移动箭头。)

使用编译主文件latexmk -pvc -xelatex test.tex --shell-escape会得到一些看起来正确的东西。进步了!但是,latexmk然后进入无限循环。原因尚不清楚。修改.latexmkrc为详细的这里似乎没有什么帮助,latexmk-recorder-旗帜呼叫也没有用。

相关内容