3

処理と再帰を使用して、これに似た形を描画しようとしています。 http://i.imgur.com/OPf5D.png

でも、形を描くためのあらゆる方法を試していると、頭がおかしくなったような気がします。これは私が得た最も近いものです:http://i.imgur.com/vCHJG.png

加えて、私のコード、どんな助けもいただければ幸いです。ありがとう:

void setup(){
  size(600,600);
}

void draw(){
  background(255);
  draws(300, 300, 50, 5);
}

void draws(int x, int y, int x2, int num){
  stroke(0);
  strokeWeight(2);
  line (x, y, (x+x2), y); //right
  line(x, y, x, y-50); //right up
  line (x-x2, y, x-(x2*2), y); // left 
  line(x-x2, y, x-x2, y-50); //left up 
  line (x, y-50, x-x2, y-50); //top 

  if(num>0){
    draws(x-x2, y-x2, x2/2, num-1);
  }
}
4

3 に答える 3

0

ロジックは、コッホフラクタルの生成に似ています。これは次のようになります。

  1. 直線の水平線を引きます。
  2. 線を3つのセグメントに分割します。
  3. 中央のセグメントを1つのセグメントのサイズと同じ量だけ上に移動します。
  4. セグメントごとに繰り返します。

したがって、関数は基本的にこの線を描画しようとする必要があります。

           _________
          |         |
          |         |
          |         |
 _________|         |_________

このプロセスは、水平線ごとに順番に繰り返されます。

これを行うために私が考えることができる1つの簡単な方法は、単純に直線から始めることです。次に、各反復で線の中央を消去し、アップシフトを実行します(黒い線の上に白い線を描くことができます)。

したがって、擬似コードは次のようになります。

// Pseudocode:

fractal (x_start,x_end, y) {
    // first simply draw a straight line:
    line(x_start,y,x_end,y);

    // divide the line into 3 and push the middle up
    length = x_end-x_start;
    segment_length = length/3;
    x2 = x_start+segment_length;
    x3 = x_start+segment_length*2;
    y2 = y-segment_length;
    erase_line(x2,y,x3,y);
    line(x2,y,x2,y2);  // up
    line(x2,y2,x3,y2); // accross
    line(x3,y2,x3,y);  // down

    // now repeat for each segment
    fractal(x_start,y,x2,y);
    fractal(x2,y2,x3,y2);
    fractal(x3,y,x_end,y);
}

これが基本的な動作機能です。繰り返しが停止しないため、上記の関数は無限に(またはメモリが不足するまで)続行されることに注意してください。したがって、最初に行うことは、再帰制限を追加することです。

// Pseudocode:

fractal (x_start,x_end, y, limit) {
    //
    // same content as above except the last 3 lines
    //

    limit --;
    if (limit) {
        fractal(x_start,y,x2,y,limit);
        fractal(x2,y2,x3,y2,limit);
        fractal(x3,y,x_end,y,limit);
    }
}

それは良い出発点になるはずです。

あなたが行うことができる他の最適化があります。たとえば、各反復は基本的に直線を再度描画するため、最初に直線を描画する必要はありません。再帰の限界で水平線を引くだけで済みます。つまり、描画しなかった線を消去する必要はありません。ただし、その実装は読者の演習として残しておきます。

于 2012-11-26T04:26:26.690 に答える
0

(多分これはコメントであるはずです-それは完全な答えではないので-しかし私はそれを作ることができないようです)

そうは言っても……

  • 各ステップで3ではなく2で割っています。
  • 毎回3秒の階層を描く必要があります
  • ここに「y」座標がありますが、x座標が間違っています。推測では....階層は次のようになります....

`

if(num>0){

    draws(x, y-x2, x2/3, num-1); // Central one    
    draws(x-x2, y, x2/3, num-1); // Left One   
    draws(x, y, x2/3/2,  num-1); // right one
}

`

少し難しいのは、座標が右の線の左側から開始することです。おそらく、左端または右端から開始する方が簡単です。

于 2012-11-26T04:22:02.743 に答える
0

わかった!助けてくれてありがとう。

これがその肉です、他のすべては大丈夫でした:

line(x、y、x、y-x2); //右

line(x-x2、y、x-x2、y-x2); //左

if(num> 0){

draws(x-(x2/3), y-x2, x2/3, num-1); // Central one  

draws(x+(x2/1.5), y, x2/3, num-1); // right one  

draws(x-(x2*1.33), y, x2/3, num-1); // left one

}

if(num == 0){//インスタンスがこれ以上ない場合は、水平線を描画します

line (x, y, (x+x2), y); //right

line (x-x2, y, x-(x2*2), y); // left 

line (x, y-x2, x-x2, y-x2); //top 

}

于 2012-11-27T00:29:15.783 に答える