在 MetaPost 中,可以在绘图命令中使用循环;例如
draw for ix=1 upto 8:(ix*2, 1/(1+cosd ix)).. endfor origin;
我在 Asymptote 中没有做到同样的事情;尝试了类似
draw(for (int k=0; k<=10; ++k){(sin(k),cos(k),sin(k/10))..}cycle);
检查了一些教程,但没有找到答案。
希望这是可能的,是吗?
答案1
Asymptote 不允许以这种方式内联 for 循环。你可以使用匿名函数来模仿它们,如下所示g.kov 的回答,但它确实很笨重。
这是一个更惯用的替代方法:
triple[] points;
for (int k=0; k<=10; ++k) {
points.push((sin(k),cos(k),sin(k/10)));
}
draw(operator..(...points) .. cycle);
您在此处使用的函数称为operator..
。通常,operator..(a, b, c, d)
这是一种比较笨拙的写法a..b..c..d
;但是,如果您将其作为函数调用,则可以通过在数组前面放置三个点来扩展数组,以便
pair[] points = {a1, a2, a3, a4, a5, a6, a7, a8, a9};
guide g = operator..(...points);
相当于
guide g = a1 .. a2 .. a3 .. a4 .. a5 .. a6 .. a7 .. a8 .. a9;
如果您想使用for
循环来生成points
列表,那么这种operator..(...points)
符号就变得非常有价值。
答案2
我不认为 Asymptote 中有这样的宏构造函数(它不是一种宏语言),但我们可以做一些等效的事情,例如
import graph3;
size(9cm);
guide3 loop(int n, triple F(int,int)){
guide3 g;
for (int k=0; k<=n; ++k)g=g..F(k,n);
return g..cycle;
}
draw(
loop(
10,
new triple(int k, int n){return (sin(k),cos(k),sin(k/n));}
)
,red+0.7bp
);
loop()
此示例在命令内部的调用中使用了匿名函数draw()
,但还有更多可用选项,例如,定义要明确使用的函数,或定义特殊draw()
命令,创建一个将生成并保留所有点以及曲线和特殊绘图命令的类,等等。
编辑:
也许,最接近 MetaPost 构造的可能是一行代码
draw(operator..(...sequence(new triple(int k){return (sin(k),cos(k),sin(k/10));},10))..cycle);
它将@Charles Staats 的回答与 sequence()
命令结合在一起。