积聚

积聚

积聚

基本设置

使用交集库时,我遇到了一些我不理解的路径名行为。以下以预期的方式工作:

\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 pathname path local\def\gdefname 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@namedpathsname 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组外的简单路径使得最后命名的路径在当前组中可用是一个错误。

评论:实际上此错误已报告

相关内容