我在PostScript中有跟随程序,我在理解方面有困难。
/kochR
{
2 copy ge {dup 0 rlineto}
{
3 div
2 copy kochR
60 rotate
2 copy kochR
-120 rotate
2 copy kochR
60 rotate
2 copy kochR
} ifelse
pop pop
} def
0 0 moveto
27 81 kochR
0 27 moveto
9 81 kochR
0 54 moveto
3 81 kochR
0 81 moveto
1 81 kochR
stroke
我对上述计划的疑问是:
2 copy ge { dup 0 rlineto }
在这里意味着什么?ifelse
如何在这里工作?条件是什么?3 div
在这做什么?2 copy KochR
声明在此处执行了什么?答案 0 :(得分:1)
您似乎在使用非常基本的PostScript概念和操作时遇到了一些问题,您是否有PostScript语言参考手册的副本?
copy复制操作数堆栈上的一个条目,前面的参数告诉解释器要复制的堆栈上有多少个操作数。 ge测试大于或等于,然后是可执行数组。
ifelse以您期望的方式工作,如果条件为真,则执行第一个可执行数组,否则执行第二个可执行数组。
3 div将堆栈上的操作数除以3并将结果放在操作数堆栈上。
2副本与第1点相同,'KochR'是一个命名对象,在这种情况下它是一个可执行数组。它必须先前已定义,否则将出现“未定义”错误。
答案 1 :(得分:1)
What does 2 copy ge { dup 0 rlineto } mean here?
作为if
或ifelse
运算符的THEN子句,它表示“if(stack(top-1)> stack(top))draw_horizontal_line((current_x,current_y) - > (current_x + stack(top),current_y)。procedure-body { dup 0 rlineto }
是递归的闭包:决定何时停止以及做什么而不是递归的部分。{ {1}}绘制相对行。相对于当前点,即。当前点是最后一个路径构造运算符(如rlineto
,{ {1}},但不是moveto
,而不是lineto
)离开了它。
rotate
stroke
总是以相同的方式工作:booleantype procedure-body procedure-body ifelse:如果boolean为true,则执行第一个过程体,否则执行第二个过程体。条件是应用于堆栈上2个数字的How does ifelse work here and what is the condition?
运算符的布尔值结果。由于ifelse
会使用其参数,因此预先gt
表示gt
执行此操作时数据不会丢失。
2 copy
由于第二个参数(堆栈顶部)控制图形的整体大小,它还控制由所有子调用的组合绘图命令表示的局部图形的“大小”。 gt
表示在每个递归级别,图的“大小”小于其父级的“大小”,小1/3。在叶子调用中,在条件a>> = b的情况下,b被用作组成图像的各个线段的长度。这意味着a不是行长本身,而是阈值。 b,在下降到b / 3,b / 9,b / 27,b / 81时,遇到或超过阈值a,然后是时候关闭克隆机并让每个人拿起他们的铅笔。
What does 3 div do here?
该行执行对kochR过程的递归调用,使用相同的阈值和从传递给当前调用的两个参数减小的大小。使用3 div
表示这两个值在堆栈中保持不变,直到What does the 2 copy KochR statement perform here?
进一步向下。
这是对C的粗略转换,假设有一个可用的图形库来实现Adobe Image Model(也称为Stencil-Mask或Path-Paint模型)。参数看起来分别是线段的大小和图的整体大小。因此,最大递归水平由等式a> = b *(1/3)^ R间接控制。
2 copy
所以你应该能够从中看到所有pop pop
东西都是后记必须“保持活跃”2个未命名变量的手段。每行对应一个过程调用,它从堆栈中消耗2个变量。如果您还省略了上一次“过程调用”中的最终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
是不必要的。从 postscript编程的角度来看,这都是非常基本的东西。但递归受限的方式非常复杂。
顺便说一下,如果你喜欢这些分形(我这样做),你绝对必须看到http://en.wikipedia.org/wiki/L-system。太棒了。
实现Adobe Image Model的一个流行的C库是Cairo Graphics,但我将创建一个工作程序作为读者的练习。 :)
答案 2 :(得分:1)
2 copy ge
副本KochR
的2个参数(我假设它是一个坐标对)并比较其组件,获得真值。然后ifelse
根据该真值确定是{ dup 0 rlineto }
还是其他块中的语句。 3 div
将coord对的y值除以三,使得该点更接近沿该轴的原点。 2 copy KochR
创建一个坐标对的副本(其中y可以在三分之一处切割,或者其位置旋转),然后递归使用它们对它们执行相同的操作。
我对该函数的最佳估计是它从传递给KochR
的点的方向上的当前点绘制了一个减弱的曲折,留下了操作数堆栈中的点列表。该程序将几个这样的zig-zags附加到当前路径,每个zig-zags都是自己的子路径,然后将它们全部划分,将整个点列表留在堆栈上(可能存在问题)。