我如何在 tikz 中使用类似以下内容的内容?
foreach (\x, \y, \colour) in {(0, 0, blue), (1, 1, green)} {
\node[fill=\colour] at (\x,\y) {};
}
答案1
TikZ 本身有一个非常强大的 foreach 循环:\foreach
。(→foreach;PGF 手册 (v2.10),第 2.20 节“重复的事情:For 循环”和第 56 章“重复的事情:Foreach 语句”)
它使用语法
\foreach \varA/\varB/…/\var<N>[<options>] in {val1A/val1B/…/val1<N>,
val2A/val2B/…/val2<N>,
…,
val<m>A/val<m>B/…/val<m><N>}
紧接着的是括号中的参数{ }
,它会循环,并且应该使用命令\varA
, \varB
, …, \varN
。
如果像您的示例一样,您只想循环一个 TikZ 路径,则可以省略括号:
\tikz
\foreach \x/\y/\colour in {0/0/blue, 1/1/green}
\node[fill=\colour] at (\x,\y) {};
可选的<options>
可以包含各种附加内容,例如
count=\cVar from <C>
\cVar
:引入了简单地从 到 递增的<C>
宏。<C> + <m>
该from <C>
部分是可选的,如果没有它,计数器将从 开始<C> = 1
。remember=\var as \previousVar (initially <value>)
:可用于以不同的名称记住上一次迭代的值。是(initially <value>)
可选的。evaluate
:可用于根据输入变量评估某个值。
如果您坚持不使用/
分隔符,您可以创建一个带有.code args
处理程序的 PGF 密钥,您可以在其中指定确切的输入语法,然后将其与.list
处理程序一起使用。这样,任何任意分隔符都是可能的,甚至是混合分隔符。
,
由于您在元组中使用 also作为分隔符,因此您必须{ }
再次将它们括起来。您可以通过使用 for examples;
作为内部分隔符来避免这种情况。
更改最外层分隔符需要对宏进行大量重新定义。此类 foreach 循环已存在许多其他实现和改进。
代码
\documentclass[tikz,convert=false]{standalone}
\begin{document}
\tikz
\foreach \x/\y/\colour in {0/0/blue, 1/1/green}
\node[fill=\colour] at (\x,\y) {};
\tikz[my Foreach/.code args={(#1,#2,#3)}{\node[fill=#3] at (#1,#2) {};}] {
\tikzset{my Foreach/.list={{(0, 0, blue)}, {(1, 1, green)}}}
}
\tikz[my Foreach/.code args={#1,#2,#3}{\node[fill=#3] at (#1,#2) {};}] {% same as above
% but without the parentheses
\tikzset{my Foreach/.list={{0, 0, blue}, {1, 1, green}}}
}
\tikz[my Foreach/.code args={#1;#2;#3}{\node[fill=#3] at (#1,#2) {};}] {% same as above
% but with ; instead of ,
\tikzset{my Foreach/.list={0; 0; blue, 1; 1; green}}
}
\end{document}
输出
答案2
TikZ/PGF 内核有用于此目的的宏。我建议\xforeach
用 编写一个更通用的宏expl3
;语法有点不同,但我想你可以接受它。
\documentclass{article}
\usepackage{xparse,tikz}
\ExplSyntaxOn
\NewDocumentCommand{\xforeach}{mmm}
{
\group_begin:
\unapiedra_xforeach:nnn {#1} {#2} {#3}
\group_end:
}
\cs_new_protected:Npn \unapiedra_xforeach:nnn #1 #2 #3
{
% store the variables in a sequence
\seq_set_split:Nnn \l_unapiedra_variables_seq { , } { #1 }
% store the data in a sequence
\seq_set_split:Nnn \l_unapiedra_data_seq { ; } { #2 }
% cycle through the data items
\seq_map_inline:Nn \l_unapiedra_data_seq
{
% separate the items in a sequence
\seq_set_split:Nnn \l_unapiedra_instance_seq { , } { ##1 }
% assign the value to each variable
\seq_mapthread_function:NNN
\l_unapiedra_variables_seq
\l_unapiedra_instance_seq
\unapiedra_set:Nn
% execute the code
#3
}
}
% the helper function that does the (temporary) assignments
\cs_new_protected:Npn \unapiedra_set:Nn #1 #2
{
\cs_set:Npn #1 { #2 }
}
\seq_new:N \l_unapiedra_variables_seq
\seq_new:N \l_unapiedra_data_seq
\seq_new:N \l_unapiedra_instance_seq
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\xforeach {\x, \y, \colour} { 0, 0, blue ; 1, 1, green} {
\node[fill=\colour] at (\x,\y) {};
}
\end{tikzpicture}
\end{document}