What does 2 copy ge { dup 0 rlineto } mean here?
作为if
orifelse
运算符的 THEN 子句,它表示“if (stack(top-1) > stack(top)) draw_horizontal_line((current_x, current_y) -> (current_x + stack(top), current_y)。{ dup 0 rlineto }
是递归的闭包:决定何时停止以及做什么而不是递归的部分。rlineto
绘制一条相对线。相对于 currentpoint,也就是说。currentpoint 是最后一个路径构造运算符(如moveto
, lineto
, 但是not rotate
, and not stroke
) 离开了它。
How does ifelse work here and what is the condition?
ifelse
总是以相同的方式工作: booleantype procedure-body procedure-body ifelse:如果布尔值为真,则执行第一个过程主体,否则执行第二个。gt
条件是应用于堆栈上 2 个数字的运算符的布尔值结果。由于gt
消耗了它的参数,前置2 copy
意味着数据不会丢失gt
。
What does 3 div do here?
由于第二个参数(堆栈顶部)控制图形的整体大小,因此它还控制由所有子调用的组合绘图命令表示的部分图形的“大小”。3 div
意味着在每个递归级别,图形的“大小”小于其父级的“大小”,小 1/3。在叶子调用中,条件 a >= b 成立,b 用作组成图像的各个线段的长度。这意味着 a 本身不是行长,而是一个阈值。一旦 b 在下降到 b/3、b/9、b/27、b/81 的过程中遇到或超过阈值 a,那么就该关闭克隆机并让每个人拿起铅笔。
What does the 2 copy KochR statement perform here?
此行执行对 kochR 过程的递归调用,使用相同的阈值和从传递给当前调用的两个参数中减小的大小。使用2 copy
意味着这两个值在堆栈上持续存在,直到pop pop
进一步下降。
这是对 C 的粗略翻译,假设有一个可用的图形库实现了 Adobe 图像模型(也称为 Stencil-Mask 或 Path-Paint 模型)。参数似乎分别是线段的大小和图形的整体大小。因此,最大递归级别由等式 a >= b * (1/3)^R 间接控制。
void kochR(double a, double b) {
if (a >= b) {
// line from currentpoint to currentpoint+(b,0)
// ie. line of length b along current x-axis
rlineto(b, 0);
} else {
b /= 3;
kochR(a, b); // recurse with reduced length
rotate(60); // rotate x-axis CCW by 60 degrees
kochR(a, b);
rotate(-120); // rotate x-axis CW by 120 degrees
kochR(a, b);
rotate(60);
kochR(a, b);
}
}
int main(void) {
moveto(0,0);
kochR(27, 81);
moveto(0, 27);
kochR(9, 81);
moveto(0, 54);
kochR(3, 81);
moveto(0, 81);
kochR(1, 81);
stroke();
}
所以你应该能够从中看出,所有的2 copy
东西都是后记必须“保持活力”2个未命名变量的一种手段。每行对应一个过程调用,该调用消耗堆栈中的 2 个变量。如果您在最后一个“程序调用”中pop pop
也省略了 final ,您应该能够看到 final是不必要的。2 copy
从postscript 编程的角度来看,这都是非常基本的东西。但是递归有界的方式非常复杂。
顺便说一句,如果你喜欢这些分形(我喜欢),你绝对必须看看http://en.wikipedia.org/wiki/L-system。太奇妙了。
Cairo Graphics是一个流行的实现 Adobe 图像模型的 C 库,但我将把创建工作程序的任务留给读者作为练习。:)