2

私はPostScriptにfollowiongプログラムを持っていますが、これは理解が困難です。

/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

上記のプログラムに関する私の質問は次のとおりです。

  1. ここでどういう2 copy ge { dup 0 rlineto }意味ですか?
  2. ここではどのように機能しifelse、条件は何ですか?
  3. ここで何をし3 divますか?
  4. 2 copy KochRここでステートメントは何を実行しますか?
4

3 に答える 3

1

非常に基本的な PostScript の概念と操作に問題があるようです。PostScript 言語リファレンス マニュアルのコピーはありますか?

  1. copy はオペランド スタックのエントリをコピーします。前の引数は、コピーするスタック上のオペランドの数をインタプリタに伝えます。ge は、より大きいか等しいかをテストし、その後に実行可能な配列が続きます。

  2. ifelse は期待どおりに機能します。条件が true の場合は最初の実行可能配列が実行され、それ以外の場合は 2 番目の実行可能配列が実行されます。

  3. 3 div は、スタック上のオペランドを 3 で除算し、結果をオペランド スタックに配置します。

  4. 2 copy はポイント 1 と同じことを行います。'KochR' は名前付きオブジェクトであり、この場合は実行可能な配列です。以前に定義されている必要があります。定義されていない場合、「未定義」エラーが発生します。

于 2012-09-12T07:30:42.670 に答える
1

2 copy geコピーのKochR2 つの引数 (座標ペアであると想定しています) は、そのコンポーネントを比較して、真の値を取得します。次にifelse、その真理値に基づいて{ dup 0 rlineto }、他のブロックのステートメントを実行するかどうかを決定します。 3 div座標ペアの y 値を 3 分割し、その点をその軸に沿って原点に近づけます。 2 copy KochR座標ペア (y が 3 分の 1 にカットされているか、その位置が回転されている) のコピーを作成し、それらを再帰的に使用して同じことを実行します。

関数が何をするかについての私の最良の見積もりは、現在の点から に渡された点の方向に減衰するジグザグを描きKochR、オペランド スタックに点のリストを残すことです。プログラムは、現在のパスにそのようなジグザグをいくつか追加し、それぞれが独自のサブパスになり、それらすべてをストロークして、ポイントのリスト全体をスタックに残します (問題が発生する可能性があります)。

于 2012-09-13T15:15:04.080 に答える
1
What does 2 copy ge { dup 0 rlineto } mean here?

ifor演算子の THEN 句としては、ifelse「if (stack(top-1) > stack(top)) draw_horizo​​ntal_line((current_x, current_y) -> (current_x + stack(top), current_y)」という意味です。{ dup 0 rlineto }は再帰のクロージャーです: いつ停止し、再帰の代わりに何をすべきかを決定する部分です. 相対線を描画します. currentpoint を基準にします. currentpointrlineto最後のパス構築演算子 ( , , のようなが、ない、ない)放置しました。movetolinetorotatestroke

How does ifelse work here and what is the condition?

ifelse常に同じように動作します: booleantype procedure-body procedure-body ifelse: ブール値が true の場合は最初のプロシージャ本体を実行し、そうでない場合は 2 番目を実行します。gt条件は、スタック上の 2 つの数値に適用された演算子のブール値の結果です。gtはその引数を消費するため、先頭に追加することは、これ2 copyを行うときにデータが失われないことを意味しますgt

What does 3 div do here?

2 番目の引数 (top-of-stack) は Figure の全体的なサイズを制御するため、すべての子呼び出しの結合された描画コマンドによって表される部分的な Figure の「サイズ」も制御します。3 div各再帰レベルで、Figure の「サイズ」がその親の「サイズ」よりも小さく、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?

この行は、現在の呼び出しに渡された 2 つの引数から同じしきい値と削減されたサイズを使用して、kochR プロシージャへの再帰呼び出しを実行します。Usingとは、2 つの値がさらに下2 copyに行くまでスタックに保持されることを意味します。pop pop


Adobe Image Model (Stencil-Mask、または Path-Paint モデルとも呼ばれます) を実装する利用可能なグラフィックス ライブラリを想定して、C への大まかな翻訳を次に示します。パラメータは、それぞれ線分のサイズと図の全体的なサイズのように見えます。したがって、最大再帰レベルは、式 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 が不要になることがわかるはずです。PostScript プログラミング2 copyの観点からは、これはすべて非常に基本的なことです。しかし、再帰が制限される方法は非常に洗練されています。

ところで、この種のフラクタルが好きなら (私も好きです)、http://en.wikipedia.org/wiki/L-systemを絶対に見なければなりません。すごい。

Adobe Image Model を実装する一般的な C ライブラリの 1 つにCairo Graphicsがありますが、実際に動作するプログラムを作成するタスクは、読者の演習として残しておきます。:)

于 2012-09-12T16:03:48.717 に答える