如果我使用和搜索的术语不正确,我深表歉意。这对我来说似乎是一个显而易见的问题,所以我很惊讶我没有找到任何东西(所以我假设我遗漏了一些东西)。
在中metapost
,我可以使用以下内容来定义循环:
for i=some-value step 0.05 until some-other-value:
fill fullcircle scaled so-and-so withcolor i*white;
so-and-so := so-and-so - something;
something-else := i;
endfor;
这意味着我可以定义增量应该有多大,而不需要知道的初始值和最终值i
。
类似的事情可能发生吗tikz
?
我可以通过用第一个值加上步长值来计算循环的第二个值,以更迂回的方式实现相同的效果。但是,我想知道是否有更简单的方法。
也就是说,下面的代码可以工作:
\documentclass[border=5pt,tikz]{standalone}
\begin{document}
\tikzset{
/mytree/key1/.initial={-10},
/mytree/key2/.initial={10},
/mytree/step1/.initial={2},
}
\begin{tikzpicture}
\pgfmathsetmacro{\myfirststep}{\pgfkeysvalueof{/mytree/key1} + \pgfkeysvalueof{/mytree/step1}}%
\foreach \i in {\pgfkeysvalueof{/mytree/key1},\myfirststep,...,\pgfkeysvalueof{/mytree/key2}}
\node at (\i,0) {\i};
\end{tikzpicture}
\end{document}
但我想知道是否可以更换线路
\pgfmathsetmacro{\myfirststep}{\pgfkeysvalueof{/mytree/key1} + \pgfkeysvalueof{/mytree/step1}}%
\foreach \i in {\pgfkeysvalueof{/mytree/key1},\myfirststep,...,\pgfkeysvalueof{/mytree/key2}}
用一些更优雅的东西
\foreach \i [step=\pgfkeysvalueof{/mytree/step1}] in {\pgfkeysvalueof{/mytree/key1},...,\pgfkeysvalueof{/mytree/key2}}
step
这与in的用法类似metapost
?
答案1
带有 的实现expl3
;生成完整列表,从而减轻 PGF 自行完成工作的负担。
\documentclass{article}
\usepackage{xparse,tikz}
\ExplSyntaxOn
\NewDocumentCommand{\mpfor}{mm}
{% #1 = variable, #2 = keys
\cfr_mpfor:nn { #1 } { #2 }
}
\keys_define:nn { cfr/mpfor }
{
start .fp_set:N = \l_cfr_mpfor_start_fp,
start .value_required:,
end .fp_set:N = \l_cfr_mpfor_end_fp,
end .value_required:,
step .fp_set:N = \l_cfr_mpfor_step_fp,
}
\clist_new:N \l_cfr_mpfor_values_clist
\cs_new_protected:Npn \cfr_mpfor:nn #1 #2
{
\keys_set:nn { cfr/mpfor } { step = 1 , #2 } % default step 1
\bool_do_while:nn
{
(% if the step is positive, continue until <= holds
\fp_compare_p:n { \l_cfr_mpfor_step_fp > \c_zero_fp }
&&
\fp_compare_p:n { \l_cfr_mpfor_start_fp <= \l_cfr_mpfor_end_fp }
)
||
(% if the step is negative, continue until >= holds
\fp_compare_p:n { \l_cfr_mpfor_step_fp < \c_zero_fp }
&&
\fp_compare_p:n { \l_cfr_mpfor_start_fp >= \l_cfr_mpfor_end_fp }
)
}
{
\clist_put_right:Nx \l_cfr_mpfor_values_clist { \fp_eval:n { \l_cfr_mpfor_start_fp } }
\fp_add:Nn \l_cfr_mpfor_start_fp { \l_cfr_mpfor_step_fp }
}
\cfr_mpfor_foreach:Vn \l_cfr_mpfor_values_clist { #1 }
}
\cs_new_protected:Npn \cfr_mpfor_foreach:nn #1 #2
{
\foreach #2 in ~ { #1 }
}
\cs_generate_variant:Nn \cfr_mpfor_foreach:nn { V }
\ExplSyntaxOff
\begin{document}
\begin{tikzpicture}
\mpfor{\i}{start=-4,step=2,end=8}{\node at (\i,0) {$\i$};}
\end{tikzpicture}
\begin{tikzpicture}
\mpfor{\i}{start=8,step=-2,end=-4}{\node at (\i,0) {$\i$};}
\end{tikzpicture}
\end{document}
注意,不会检查循环是否结束(可能会添加)。如果步长为零,则仅使用起点。
可以使用任何值,只要它符合模块接受的值fp
。
答案2
这不是很简单的方法,也不是很优雅,但是...是一种可能性。这是TikZ
唯一的解决方案。它可以适应添加其他键(例如,,,,... second
)。random step
exclusive start
exclusive end
\documentclass[border=5pt,tikz]{standalone}
\pgfkeys{
/stepfor/.cd,
start/.store in={\startvalue},
step/.store in={\stepvalue},
end/.store in={\endvalue}
}
\def\for[#1]#2{
\pgfkeys{/stepfor/.cd,#1}
\pgfmathsetmacro{\secondvalue}{int(\startvalue+\stepvalue)}
\foreach \i in {\startvalue,\secondvalue,...,\endvalue}{#2}
}
\begin{document}
\begin{tikzpicture}
\for[start=-4,step=2,end=8]{\node at (\i,0) {\i};}
\end{tikzpicture}
\end{document}
笔记: 我加入int
评估\secondvalue
只是为了让输出更好;)但是为了处理实数,当然应该将其删除。
答案3
如果您接受使用 之外的库TikZ
,并且只想循环整数,则可以举例说明xinttools
。
方法 1:仅使用xint
。
\documentclass[tikz,border=5pt]{standalone}
\usepackage{xinttools}
\begin{document}
\begin{tikzpicture}
\xintFor* #1 in {\xintSeq[2]{-4}{8}} \do {
\node at (#1,0) {#1};
}
\end{tikzpicture}
\end{document}
方法 2:使用xint
和\foreach
。
\documentclass[tikz,border=5pt]{standalone}
\usepackage{xinttools}
\begin{document}
\begin{tikzpicture}
\edef\interval{\xintListWithSep{,}{\xintSeq[2]{-4}{8}}}
\foreach \i in \interval
\node at (\i,0) {\i};
\end{tikzpicture}
\end{document}
方法 2+:使用xint
和\foreach
样式。
\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usepackage{xinttools}
\tikzset{
/pgf/foreach/interval/.code args={from #1 to #2 by #3}{
\edef\interval{\xintListWithSep{,}{\xintSeq[#3]{#1}{#2}}}
}
}
\begin{document}
\begin{tikzpicture}
\foreach[interval=from -4 to 8 by 2] \i in \interval
\node at (\i,0) {\i};
\end{tikzpicture}
\end{document}