以下代码可在 DVI 和 PDF 格式中编译。但是,如果我在命令后绘制任何内容\end{scope}
,它将无法在 DVI 中编译,并且我会收到以下错误消息:
Latex> ! Undefined control sequence.
Latex> \tikz@intersect@namedpaths ...t@path@name@line \x
\endcsname {\pgfsyssoftpat...
PDF 记录了相同的错误,但编译通过,图像被渲染。是什么导致了这个错误?我还有很多东西要补充到这个图中!
更新:根据要求,我添加了一个随机绘制命令\draw (0,0) circle [radius=1cm];
,然后触发了错误。使用path name global=line \x
并不能解决问题。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{intersections,backgrounds}
\begin{document}
\begin{tikzpicture}
%axis
\draw (-.5,0) -- (6.5,0);
%curve
\draw[yshift=1cm,name path=curve] (-.5,0) %vertically shiftable
to[out=70,in=180] (.7,1.5)
to[out=0,in=180] (2,.5)
to[out=0,in=180] (4.5,2.5)
to[out=0,in=160] (6.5,1);
%rectangles
\begin{scope}[on background layer]
\foreach \x in {0,1,2,5}{
\path[name path=line \x] (\x,0) -- (\x,4);
\path[name intersections={of=curve and line \x, by={isect \x}}];
\draw[fill=gray!50] (isect \x) rectangle (\x+1,0);
\draw[fill] (isect \x) circle [radius=2pt];
}
\end{scope}
\draw (0,0) circle [radius=1cm]; % Won't compile with this added draw
\end{tikzpicture}
\end{document}
答案1
我认为这是intersections
TikZ 库中的一个错误。虽然它不会在 CVS 版本的 TikZ 中产生错误,但底层错误仍然存在。
当 TikZ 命名路径时,它必须将该路径保存到宏中。由于路径在处理过程中可能会发生相当大的变化,因此保存它的最佳时间是在最后。因此,交集库会挂接到最后\tikz@finish
调用的宏中。因此,它将所有必要的交集代码存储到宏中,\tikz@intersect@namedpaths
然后在最后执行该宏。代码的添加如下所示:
\def\tikz@intersect@finish{%
\ifx\tikz@intersect@namedpaths\pgfutil@empty%
\else%
\tikz@intersect@namedpaths%
\let\tikz@intersect@namedpaths=\pgfutil@empty%
\fi%
}
\tikz@finish
这与所有其他东西的运行有关。
问题在于\let
。宏\tikz@intersect@namedpaths
定义全球。这是因为在路径内部,可能会涉及各种分组,而 TikZ 不想为此烦恼。所以它全局定义了这一点。然而,它只会清除它本地。通常情况下,这是可以的,因为清除发生在与命令相同的级别\path
。但在这种情况下,这意味着scope
当范围结束时,\tikz@intersect@namedpaths
将恢复到其先前的状态全球的\path[name path=line \x] (\x,0) -- (\x,4);
值。这是它在保存名为 的路径时所具有的值line \x
。因此,当\draw
执行范围后的命令时,该命令\tikz@intersect@namedpaths
不为空,因此会被处理。
这绝对是一个错误,因为这意味着范围内部命名的任何路径现在都可以在其外部使用 - 因此,如果在范围之前和范围内部使用相同的路径名,则范围之后的路径就是在内部定义的路径,而不是前一个路径。
代码中出现投诉的原因是,在早期版本的 TikZ 中,宏\tikz@intersect@namedpaths
会按指定的方式存储路径名。因此它将路径名(在您的示例中)存储为line \x
。这意味着当在范围之外的命令\tikz@intersect@namedpaths
中执行时\draw
,它会尝试找出的含义\x
并失败,因为它不再定义。更高版本的 TikZ 首先扩展路径名,这意味着line \x
存储为,例如line 1
。这就是为什么在更高版本的 TikZ 中不再产生错误,或者在将路径名传递给代码之前扩展路径名时(这就是所做的.expanded
)不再产生错误的原因。但是,底层错误仍然存在,并且仍然可以通过查看保存的路径来检测到。
真正的解决方法是将 的重置\tikz@intersect@namedpaths
变成全局重置。这很简单:将其添加\global
到 前面\let
。因此,正确的解决方案是将以下内容添加到您的序言中:
\makeatletter
\def\tikz@intersect@finish{%
\ifx\tikz@intersect@namedpaths\pgfutil@empty%
\else%
\tikz@intersect@namedpaths%
\global\let\tikz@intersect@namedpaths=\pgfutil@empty%
\fi%
}
\makeatother
这是一个显示路径持久性的示例。关键是蓝色圆圈。这应该位于下部路径的交汇处,但由于在范围内使用相同的名称,它被转移到上部路径(因为我们需要\tikz@intersect@namedpaths
处理一个额外的路径命令之后)。\tikz@intersect@finish
按照我描述的方式重新定义可以解决这个问题。
\documentclass{article}
%\url{http://tex.stackexchange.com/q/150598/86}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
\draw[name path=abc] (-3,-3) -- (3,3);
\draw[name path=def] (3,-3) -- (-3,3);
\draw[green, ultra thick, name intersections={of=abc and def}] (intersection-1) circle[radius=6pt];
\begin{scope}
\draw[name path=abc] (-3,-2) -- (2,3);
\draw[green, ultra thick, name intersections={of=abc and def}] (intersection-1) circle[radius=6pt];
\end{scope}
\path (0,0); % needed to invoke \tikz@intersect@namedpath from inside the scope
\draw[blue, ultra thick, name intersections={of=abc and def}] (intersection-1) circle[radius=10pt];
\end{tikzpicture}
\makeatletter
\def\tikz@intersect@finish{%
\ifx\tikz@intersect@namedpaths\pgfutil@empty%
\else%
\tikz@intersect@namedpaths%
\global\let\tikz@intersect@namedpaths=\pgfutil@empty%
\fi%
}
\makeatother
\begin{tikzpicture}
\draw[name path=abc] (-3,-3) -- (3,3);
\draw[name path=def] (3,-3) -- (-3,3);
\draw[green, ultra thick, name intersections={of=abc and def}] (intersection-1) circle[radius=6pt];
\begin{scope}
\draw[name path=abc] (-3,-2) -- (2,3);
\draw[green, ultra thick, name intersections={of=abc and def}] (intersection-1) circle[radius=6pt];
\end{scope}
\path (0,0); % needed to invoke \tikz@intersect@namedpath from inside the scope
\draw[blue, ultra thick, name intersections={of=abc and def}] (intersection-1) circle[radius=10pt];
\end{tikzpicture}
\end{document}