梅威瑟:
\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 的回答的理解,第一个代码也不应该有效,但它确实有效。(那些可能想反对的人\foreach
:foreach
pgfmanual 在第 14.14 节中指出:“由于历史原因,您也可以写 \foreach 而不是 foreach。”)
底线:除了这很棘手之外,我真的没有简单的信息,而且将来可能会有一个foreach
可以使用该语法的版本。