在 TikZ & PGF 手册 3.0.1a 版本的 TikZ 部分的几个不同上下文中提到了暂时中止当前路径的构建:
- 命令描述
\pgfextra{<code>}
,第 162 页暂时停止道路建设,并
〈code〉
执行。然后恢复道路建设。 - 路径操作的描述
\path ... pic
,第 252 页当遇到 a 时
pic
,当前路径被暂停,并开始新的内部范围。 - 路径操作的描述
\path ... graph
,第 262 页当在路径上遇到此命令时,当前路径的构造将暂停(类似于
edge
命令或node
命令)。在本地范围内,首先使用以下命令使用〈options〉
键路径执行.../tikz/graphs
这到底是什么意思?
敲击建议可以使用手册第 972 页的 PGF 部分中描述的环境来实现此概念pgfinterruptpath
。也许可以,但不能天真地实现。事实上,天真的实现会将
\draw (-1,0) graph{ O[red] } -- (1,0);
渲染结果为
进入
\pgfmoveto{\pgfpoint{-1cm}{0cm}}
\begin{pgfinterruptpath}
\pgfsetfillcolor{red}
\pgfnode{rectangle}{center}{O}{}{\pgfusepath{discard}}
\end{pgfinterruptpath}
\pgflineto{\pgfpoint{1cm}{0cm}}
\pgfusepath{stroke}
渲染结果为
请注意,在前一张图片中,图形位于路径的顶部,而在后一张图片中,则反之亦然。
答案1
正如 Mark Wibrow 所写一条评论、\pgfextra
和并不都采用相同的“路径暂停”方法。路径暂停有两种方法:pic
和所采用的方法。其他路径组件:和在某种程度上被 TikZ“引擎”视为特殊类型的s,特别是,它们的“路径暂停”方法类似于s所采用的方法。graph
\pgfextra
node
edge
graph
pic
node
node
下面的解释非常粗略地近似了源代码中实际发生的情况。代码片段仅用于说明目的;它们不是从源代码中逐字复制的,而是对实际实现进行极端、几乎荒谬的简化的结果。那些想了解 TikZ 是如何真的实现的话,应该读一下源代码。
该\pgfextra
方法
当\pgfextra{<body>}
“执行”时,路径解析器会暂时将控制权移交给顶层 TikZ 图片解析器。但是,这不会关闭任何现有的 TeX 作用域或启动任何新的作用域,并且引擎的内部状态保持不变,因此在控制权易手时,迄今为止沿路径创建的所有内部数据结构都保持不变。
一旦顶级解析器完成处理<body>
,控制权将返回到路径解析器,后者在\pgfextra{<body>}
命令后立即开始执行。与之前一样,此控制切换不涉及 TeX 范围的创建或销毁,也不会影响引擎的状态。
这些解释可以更正式地重新表述如下。假设调用顶级 TikZ 图片解析器\tikz@parser
并接受一个参数(\def\tikz@parser#1{...}
),并且调用 TikZ 路径解析器\path@parser
。然后执行路径
\path <before> \pgfextra{<extra>} <after>;
过程如下。
路径语句扩展为
\path@parser <before> \pgfextra{<extra>} <after>;
路径解析器连续扫描输入,因此上面那行代码最终简化为
\path@parser \pgfextra{<extra>} <after>;
这扩展为
\tikz@parser{<extra>} \path@parser <after>;
该node
方法
节点被排版到 TeX 框中,并保存到 TeX 框寄存器中。节点可以保存到两个框之一:前景框或背景框。behind path
指定了该选项的所有节点都将附加到背景框,而其余节点将附加到前景框。
在路径的末尾,两个框的内容(由低级排版指令(又名\special
s)组成)被写入 dvi 文件:首先是背景框,然后是正常路径,最后是前景框。
路径按文本顺序处理。由于节点和正常路径构造操作可以在文本上混合,因此必须采取预防措施,以免节点的路径被视为正常路径的自然延续。因此,当首次处理节点时,会打开 TeX 范围,将当前路径的副本保存到本地“私有变量”,并重置当前路径,即设置为空路径。同样,路径选项也会保存并重置。
当节点完成排版到适当的 TeX 框时,TeX 范围将关闭,并且恢复保存的路径和选项。
更正式地说,路径的执行
\path <before> node <node specification> <after>;
过程如下。
路径语句扩展为
\path@parser <before> node <node specification> <after>;
路径解析器连续扫描输入,因此上面那行代码最终简化为
\path@parser node <node specification> <after>;
这扩展为
\begin{pgfinterruptpath}% \def\options{}% \ifx<current node is `behind path`>% \setbox\bg@box\hbox{\unbox\bg@box<typeset current node per specs>}% \else% \setbox\fg@box\hbox{\unbox\fg@box<typeset current node per specs>}% \fi% \end{pgfinterruptpath}% \path@parser<after>;
请注意,
pgfinterruptpath
环境会自动用一对围绕其身体\begingroup ... \endgroup
。