2

Processing に取り掛かるための小さな宿題として、次のコードを取得するためのコードを作成する必要がありました。 仕事

使用する

public void setup() {
   size(300,200);
   noFill();
   rect(100, 20, 40, 80);
   ellipseMode(CENTER);
   fill(#000000);
   ellipse(width/2, height/2, 5,5);
   
   noFill();
   translate(width/2, height/2);
   rotate(radians(65));
   rect(-20, -40, 40, 80);
}
public void draw() {
}

これまでのところ、これは非常にうまく機能しました。rectしかし、回転を正しくするために、下の命令内の座標を変更しなければならなかったのは好きではありません。回転すると、単一の要素ではなく、実際には座標系全体が回転することを知っています。私が知らないのはtranslate、コマンド内で同じ座標を使用しながら、出力を上の図のようにするために命令にどの値を入力するかrectです。

タスクは、使用したコードで既に完了していますが、あまり好きではありません。だから、これは私の宿題を他の誰かに頼むだけではなく、純粋な興味です。

編集:質問のより一般化された試み:回転する前にどの値を変換して必要な結果を取得するかをどのように知ることができますか? それらを計算する方法はありますか?もちろん、ただ試しているだけではありませんよね?

4

3 に答える 3

6

処理で混乱するのは座標系です。Processing では、原点 (0,0) は画面の左上にあり、正の座標のみが画面に表示されます。これに対する非常に一般的な回避策は、次を呼び出すことです。

translate(width/2, height/2);

メソッドの最初にvoid draw()。こうすることで、0,0 がスケッチの中心になり、その後呼び出されるメソッドrotate(radians(65))はスケッチの中心からアクションを実行します。

P3DまたはOPENGLレンダラーを使用するスケッチは多くの場合、変換を呼び出して座標系を使いやすいものに変更するため、これも良いことです。たとえば、0,0 または 0,0,0 にあるオブジェクトは中心にあり、オブジェクトの周りをカメラで周回したり、オブジェクトをその中心を中心に回転させたりすることが容易になります。

オブジェクトを描画する別の一般的な方法は、各オブジェクトの座標を指定する代わりに、上記のように原点を設定することです。つまり、rect(-100, -50, 50, 50)以下に示すように、0,0 で各オブジェクトを描画する前に、変換の前に popMatrix() と pushMatrix を使用します。

translate(width/2, height/2);
pushMatrix();
  translate(-100, -50);
  rect(0,0,50,50);
popMatrix();

最終的に 3D レンダラーに移行する可能性がある場合、これは 2D レンダラーで使用するのに適した方法です。これは、原点が 0,0 であると仮定してジオメトリを描画する独自のメソッドまたはオブジェクトを簡単に置き換えたり、作成rect()したりできるためです。box()sphere()

x 座標と y 座標を変数に置き換えるか、for ループで配列を反復処理すると、最小限の労力と最小限のコードの書き換えで、2 次元または 3 次元で数百または数千の形状を非常に簡単に描画できます。


更新:コメントに従って、元のポスターの説明を追加しました。


これにどのようにアプローチするかを示すために、問題を少し変更しました。プッシュ マトリックスとポップ マトリックスを使用して、上で説明した移動/回転の方法を示しています。私は値を推測しているだけですが、ピクセル精度が必要な場合は、フォトショップやプレビューなどの画像編集プログラムで測定できます.

rect1

translate(180, 150);
rect(0, 0, 180, 80);

rect2

translate(185, 170);
rotate(radians(65));
rect(0, 0, 180, 80);

楕円

translate(180, 250);
ellipse(0, 0, 8, 8);

pushMatrix()とですべてをまとめpopMatrix()ます。

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

void draw(){
  // rect1
  noFill();
  pushMatrix();
    translate(180, 150);
    rect(0, 0, 180, 80);
  popMatrix();
  // rect2
  pushMatrix();
    translate(185, 170);
    rotate(radians(65));
    rect(0, 0, 180, 80);
  popMatrix();
  // ellipse
  fill(0);
  pushMatrix();
    translate(180, 250);
    ellipse(0, 0, 8, 8);
  popMatrix();
}
于 2012-11-20T03:28:34.447 に答える
3

回転は原点 (0,0) に適用されるため、原点で回転する軸を描画する必要があります。または、座標系の原点を軸に移動します。それは確かに紛らわしいです。変換を使用するときは、常に原点に描画する傾向があります。これを試して、物事がより明確になるかどうかを確認してください...または以下:) また、変換の範囲を制御するための push/popMatrix() があります...

public void setup() {
  size(300, 380);
  smooth();
}
public void draw() {
  background(0);
  stroke(255);
  //use push/pop Matrix to control scope of translate and rotate
  pushMatrix();
  //move coordinates system origin to center of screen
  translate(width/2, height/2);
  // rotate with origin as axis
  rotate(radians(mouseY));
  //draw at origin (now temp moved to center of screen)
  // white line 
  line(0, 0, 150, 0);
  // here all coordinate system is back to normal
  popMatrix();

  //draw with normal system red line at origin
  stroke(255, 0, 0);
  line(0, 0, 150, 0);

    //draw with normal system blue line at centre
  stroke(0, 0, 255);
  line(width/2, height/2, width/2 + 150, height/2);
}
于 2012-11-20T02:41:35.253 に答える
3

私の特定の例では、長方形の座標を変更せずに画像の結果を取得するために移動および回転する方法を知っていますか?

さて、回転を適切に使用するには原点で描画する必要があるため、四角形の原点を扱っているだけです...コードにあるように、デフォルトでは、原点は左上隅であるため、オフを作成しました((0,0)から)座標(0,0)でコーナーではなく中心を描画するように設定し、中央で回転させます。素晴らしい。あなたが見つけた値が四角形の幅の半分(-20)と四角形の高さの半分(-40)を引いたものであることは偶然ではありません。rectMode(CENTER) に変更すると、(0,0) に描画できます。同じことが移動にも当てはまります。楕円がある画面の中心である目的のポイントに移動するだけです。半幅と半高を使用して行われることは...

見る:

public void setup() {
  size(300, 200);
  smooth();
  ellipseMode(CENTER);
  rectMode(CENTER);
  noFill();
  // here converting the coordinates to work with CENTER mode
  //could have changed the rect mode just after this
  // but i kept as an illustration
  int rwidth = 40;
  int rheight = 80;
  int xpos = 100 + rwidth/2;
  int ypos = height/2 - rheight/2 ;

  rect(xpos, ypos, rwidth, rheight);

  fill(#000000);
  ellipse(width/2, height/2, 5, 5);

  noFill();
  pushMatrix();

  translate(width/2, height/2);

  //draw at origin gray
  stroke(150);
  rect(0, 0, 40, 80);
  // then rotate
  rotate(radians(65));
  // draw again black
  stroke(0);
  rect(0, 0, 40, 80);

  popMatrix();


  // here using the cordinates calculated before as a translate value 
  // we draw at origin, but it appears at same place
  stroke(230,230,100);
  // a bit to the left...
  translate(xpos-2, ypos-2);

  rect(0, 0, 40, 80);

}

于 2012-11-22T13:27:31.703 に答える