积聚
基本设置
使用交集库时,我遇到了一些我不理解的路径名行为。以下以预期的方式工作:
\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
\draw[name path=pos] (0, -1) -- (2, 1);
\draw[name path=neg] (0, 1) -- (2, -1);
\fill[name intersections={of=pos and neg}] (intersection-1) circle (2pt);
\end{tikzpicture}
\end{document}
陷入问题
但我有多条路径要相交,所以让我们稍微改变一下:
\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
\draw[name path=pos] (0, -1) -- (2, 1);
% Only change: A senseless “loop”
\foreach \i in {0} {
\draw[name path=neg] (0, 1) -- (2, -1);
}
\fill[name intersections={of=pos and neg}] (intersection-1) circle (2pt);
\end{tikzpicture}
\end{document}
在我看来这应该是完全等价的,但现在我收到错误消息:
tikz 包错误:我不知道名为“neg”的路径。也许你拼错了。...[red, name interactions={of=pos and neg}]
pgf 包错误:没有已知的名为 Intersection-1 的形状。...ections={of=pos and neg}] (intersection-1)
无论如何都会绘制圆圈,因为 pgf 只是假设的坐标(intersection-1)
为(0, 0)
,但这不是我期望或希望的行为。
一个奇怪的解决方法
通过随后绘制任何东西,我们都可以让它再次顺利运行:
\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
\draw[name path=pos] (0, -1) -- (2, 1);
\foreach \i in {0} {
\draw[name path=neg] (0, 1) -- (2, -1);
}
% Only change: Senseless path of vanishing length
\path (5, -1);
\fill[name intersections={of=pos and neg}] (intersection-1) circle (2pt);
\end{tikzpicture}
\end{document}
问题
我想知道为什么有时候是这样的。
解决方案和解决方法也很有趣,但可能更适合作为这个问题的答案类似问题,尽管现有的答案大多关注的是选项的扩展。
非解释
由于第三种变体没有任何问题,因此从循环中导出路径名不存在一般问题,尽管使用name path global
提供另一种解决方法。
在声明节点时我没有遇到相同的行为,所以这似乎是交叉库的一个相当特殊的问题。
答案1
正如@marmot 在其评论中所建议的那样,这个问题是全球性的与局部性的。
的主体是在一个组中执行的,因此所有以(或等效的)\foreach
命名的路径都应该在组外不可访问,因为它们是用而不是定义的(就像 的情况一样)。name path
name path local
\def
\gdef
name path global
您可以检查问题是否与组相关,而不是特定于\foreach
以下示例中的,其中typeout
用于向控制台显示存储在中的“neg”路径\tikz@intersect@path@name@neg
。
\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{intersections}
\makeatletter
\begin{document}
\begin{tikzpicture}
\draw[name path=pos] (0, -1) -- (2, 1);
{
\draw[name path=neg] (0, 1) -- (2, -1);
\typeout{=== inside === : \meaning\tikz@intersect@path@name@neg}
}
\typeout{=== outside === : \meaning\tikz@intersect@path@name@neg}
\fill[name intersections={of=pos and neg}] (intersection-1) circle (2pt);
\end{tikzpicture}
\end{document}
输出为
=== inside === : macro:->\pgfsyssoftpath@movetotoken {0.0pt}{28.45274pt}\pgfsyssoftpath@linetotoken {56.90549pt}{-28.45274pt} === outside === : undefined ! Package tikz Error: I do not know the path named `neg'. Perhaps you misspelt it.
那么当我们在组外添加一些路径命令时会发生什么?
TikZ 库intersections
重新定义在每个 tikz 命令中执行的路径,如果没有选项\tikz@finish
,则运行 GLOBAL (其中包含最后一个路径的定义)。因此,组外的任何命令都会重新定义当前组中的最后一个路径。\tikz@intersect@namedpaths
name intersections
\path
这是一个错误。这可能是因为我们可以在代码中看到:
% FIXME : it is reasonable to reset this globally as it is global % in its nature. But the reset instruction should be moved to % \endscope or something related. Resetting it here breaks the % manual
我们可以在以下代码中检查所有这些
\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{intersections}
\makeatletter
\begin{document}
\begin{tikzpicture}
\draw[name path=pos] (0, -1) -- (2, 1);
{
\draw[name path=neg] (0, 1) -- (2, -1);
\typeout{=== inside, neg === : \meaning\tikz@intersect@path@name@neg}
}
\typeout{=== outside, before path === : \meaning\tikz@intersect@path@name@neg}
\typeout{=== the tikz@intersect@namedpaths === : \meaning\tikz@intersect@namedpaths}
\path;
\typeout{=== outside, after path === : \meaning\tikz@intersect@path@name@neg}
\fill[name intersections={of=pos and neg}] (intersection-1) circle (2pt);
\end{tikzpicture}
\end{document}
输出为
=== inside, neg === : macro:->\pgfsyssoftpath@movetotoken {0.0pt}{28.45274pt}\pgfsyssoftpath@linetotoken {56.90549pt}{-28.45274pt} === outside, before path === : undefined === the tikz@intersect@namedpaths === : macro:->\def \tikz@intersect@path@name@neg {\pgfsyssoftpath@movetotoken {0.0pt}{28.45274pt}\pgfsyssoftpath@linetotoken{56.90549pt}{-28.45274pt}} === outside, after path === : macro:->\pgfsyssoftpath@movetotoken {0.0pt}{28.45274pt}\pgfsyssoftpath@linetotoken {56.90549pt}{-28.45274pt}
结论
正常行为是,如果您使用 组内 来命名路径name path
(例如 inside \foreach
),则该路径不应在组外可用。如果您想使其在组外可用,则应使用name path global
(如@marmot 在其评论中所指出的那样)。
事实上,使用\path
组外的简单路径使得最后命名的路径在当前组中可用是一个错误。
评论:实际上此错误已报告。