foreach 路径操作 - 对语法感到困惑

foreach 路径操作 - 对语法感到困惑

梅威瑟:

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \draw (0:2) foreach \a in {30,60,...,330} { -- (\a:2) } -- cycle;
  %\draw foreach \a in {0,30,...,330} { (\a:2) -- } cycle;
\end{tikzpicture}
\end{document}

第一个版本可以工作,注释掉的第二个版本则不行(虽然我认为它会更优雅)。使用路径操作时,允许和不允许的规则是什么foreach?手册在这方面相当简短。

答案1

每个foreach语句都不能以“--”结尾。这是因为出于某种原因,tikz 将其每个 foreach speps 用作完成的语句(在本例中)。

因此你不会写:

\draw (0:2)--;

因为结果对于编译器来说不太好,而且你不知道期望的输出是什么。

下面的代码演示并几乎证明了上述内容:

\documentclass[tikz]{standalone}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
  %\draw (0:2) foreach \a in {30,60,...,330} { -- (\a:2) } -- cycle;
  \begin{scope}
  \draw (0:2)--(30:2)--(60:2)--(90:2)--(120:2);
  \end{scope}
  %Problematic:
  \begin{scope}[shift={(3,0)}]
  \draw (0:2)--;
  \draw (30:2)--;
  \draw (60:2)--;
  \draw (90:2)--;
  \draw (120:2)--;
  \end{scope}

  \begin{scope}[shift={(3,-3)}]
  \draw  foreach \a in {0,30,...,120} {(\a:2)--};% ({\a+30}:2) };%
  \end{scope}
  %Problematic with same result:
  \begin{scope}[shift={(0,-3)}]
  \draw  foreach \a in {0,30,...,90} {(\a:2)--({\a+30}:2) };%
  \end{scope}

  %In your case:
  \begin{scope}[shift={({(3+1.5)/2},-6)}]
  \draw  foreach \a in {0,30,...,330} {(\a:2)--({\a+30}:2) };%
  \end{scope}
\end{tikzpicture}
\end{document}

结果如下:

在此处输入图片描述

如果您看到正确的图片,它们来自有问题的代码,在一种情况下,它只绘制以 结束的线条,--而在另一种情况下(仍然在左边但向下)来自以 结束其任何语句的循环--。但结果(当然在编译时出现错误)图像与以下结果相同:

 \draw (Point)--;

解决办法就是关闭每个语句的--

答案2

我读了一些内容,试图在手册中找到解释。(我指的是版本 3.0.1a。)

如果您查看第 14 章中各个操作的详细描述,您会发现语法始终要求在末尾添加一个坐标。例如,line-to 操作的语法为,并且--(coordinate or cycle)在教程部分 (2.3) 中还提到“ --[...] 后面必须跟另一个坐标”。但是,move-to 操作也是一个有效的操作,其语法为(coordinate)

在第 83 章的后面,它说:“TikZ 允许您在路径构造中使用foreach[...]。在这种情况下,命令必须是路径构造命令。”我认为这个词命令在这里有点误导,因为它在手册的其他部分有不同的含义。我猜这里的意思是花括号内的重复部分必须是“独立的”路径操作。这可以解释为什么和都可以,而-- (\x,\y)不能。(\x,\y)(\x,\y) --

无论如何,虽然 TikZ 手册的质量非常高,但我认为这一小部分可以更详细一些。另外,如果我没算错的话,foreach在超过 1,100 页的篇幅中,只有两个路径内部构造的示例。一个简单的例子,如“这个可以工作,这个不行”可能会有所帮助。

[这基本上就是@koleygr 所说的,但我想在手册中找到对这种行为的清晰解释。]

答案3

免责声明:这不是答案。事实上,我会真的对解释的答案感兴趣为什么那个会发生。

我快速浏览了 tikz.code.tex 并找到了评论

TT 的评论:我希望我修复了 \tikz \foreach 问题。新版本将采取保守的方法,并且只有当 \tikz 之后的下一个关键字是以下之一时才会执行花哨的操作:\draw、\fill、\filldraw、\graph、\matrix,

我同意这并没有告诉我们为什么第二个代码示例不起作用,但人们可能从中得到的一个信息是,foreach 棘手。我不同意的原因是koleygr 的回答,或者说我读到的,在我看来,它没有解释为什么会发生这种情况,而且在我看来更令人担忧的是,它表明您需要在 foreach 的第二个参数中有一个完整的路径。当然,由于我并不真正了解具体发生了什么,所以我很可能是错的。不过,我想展示一个简短的代码片段,它可以完成第二个不起作用的 foreach 循环中的预期工作。这是一个不太优雅但有效的 foreach 循环。

\documentclass[tikz]{standalone}
\begin{document}
\tikzset{my foreach code/.code={\xdef\Lst{}\foreach #1 }}
\begin{tikzpicture}[]
  \draw [my foreach code={\a in {0,30,...,330} {\xdef\Lst{\Lst (\a:2) -- }}}] 
  \Lst   cycle;
\end{tikzpicture}
\end{document}

在此处输入图片描述

将此与以下不起作用的示例进行比较是有益的。

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \xdef\Lst{}
  \draw foreach \a in {0,30,...,330} {\xdef\Lst{\Lst (\a:2) -- }} \Lst cycle;
\end{tikzpicture}
\end{document}

人们会期望这有效,但事实并非如此。根据我对 koleygr 的回答的理解,第一个代码也不应该有效,但它确实有效。(那些可能想反对的人\foreachforeachpgfmanual 在第 14.14 节中指出:“由于历史原因,您也可以写 \foreach 而不是 foreach。”)

底线:除了这很棘手之外,我真的没有简单的信息,而且将来可能会有一个foreach可以使用该语法的版本。

相关内容