移動・回転させる

基本図形の描き方・色の付け方は理解されたかと思います。

次に学習するのは移動と回転です。図形を描くときには座標を指定するので、図形の移動は座標を動かせばいいだけですが、たくさんの図形があると 全ての図形に移動の処理を書かなくてはいけないので大変です。ここで紹介する移動と回転は沢山の図形を一斉に動かす時などによく使います。
Processingでの移動と回転は特殊で、図形自体を移動・回転させるのではなく、図形が描かれる空間を移動させたり回転させたりします。

まずは例を見てみましょう

translate

最初は移動させるための関数であるtranslateです。

translateは移動させるx座標、y座標の値を渡します。


var w = 400;
var h = 400;
function setup() {
  createCanvas(w, h);
  background(0);
}

function draw() {
  fill(255);
  ellipse(w / 2, h / 2, 50);
  translate(100, 100);    //translate(x座標の移動値, y座標の移動値)
  fill(200);
  ellipse(w / 2, h / 2, 50);
  translate(0, -50);
  fill(100);
  ellipse(w / 2, h / 2, 50);
}   
        

するとどうでしょうか。真ん中の白円が移動前の円です。
右下に描かれている円が右へ100、下へ100移動させた円で、その上が右へ0,上へ50移動させた円です。
ellipseの中身は全て同じですが、translateによって移動させられているのが分かるかと思います。

translate(100, 100)は見ての通り右へ100, 下へ100移動させる命令ですが、translate(0, -50)での移動は 意外なことに、translate(100, 100)で移動してからさらに上方向に50移動しています。

translateは元の位置から図形を移動させる命令ではなく、以降に描く図形の位置をずらす(描画領域の空間そのものを動かす)設定関数であると言えます。
また、設定は重ね掛けされるため上のような描画になってしまうのです。

このままでも注意して使えば良いように思いますが、何度もtranslateを使うときは常に今どれくらい移動しているのか考えなくてはいけません。
そこで便利なのがpushとpopという二つの関数です。

pushとpop

pushは現在の描画空間の位置や回転、色などの設定項目を保存します。
popはpush以降の設定項目をリセットし、push時に保存しておいた設定を復元します。実際に使ってみましょう。


var w = 400;
var h = 400;
function setup() {
  createCanvas(w, h);
  background(0);//white
}

function draw() {
  fill(255);// 白
  ellipse(w / 2, h / 2, 50);
  fill(100);  // 濃い灰色
  
  push();
  translate(100, 100);
  fill(200); // 薄い灰色
  ellipse(w / 2, h / 2, 50);
  pop();

  push();
  translate(0, -50);
  //fill(100);
  ellipse(w / 2, h / 2, 50);
  pop();
}   
        

注目していただきたいのは、3番目に描画した円の位置と色です。
まず位置ですが、元の円の上に移動しました。
これは、push,popによって最初のtranslateが「隔離」されたことにより2番目のtranslateが影響を受けなくなったためです。
1つ目のpushでfill等の設定を保存し、popで設定が復元されます。この復元の際に1つめのpushからpopの間での変更はなかったことになります。
そのため、translate(0, -50)を呼んだ時点でtranslate(100, 100)の設定はなくなっているため、3番目の円は元の位置から上へ50移動しているのです。

色に関しても同じです。
1番目の円を描いた後でfill(100)を設定しています。このあとpush~popの間でfill(200)を設定していますが、popでfill(100)が復元されるので、 3番目に描く円はfill(200)の薄い灰色ではなく、fill(100)の濃い灰色で塗られるのです。
pushとpopを使った方が複雑になりにくいので、基本的にrotateやtranslateを使うときはpush,popを使うようにしましょう。

rotate

次に紹介するのは回転ですが、こちらも癖のある関数です。
まずrotateを使ってみる前に角度を表すラジアンについて少し説明します。

ラジアンとは、角度を表す単位の一つで、0から始まり2π(πは円周率。円周率の2倍なので、2πは約6.28)で0から360度を表します。 つまり、360度と2πラジアンは角度としては同じになります。
1ラジアンは360/2π ≒ 57.2958度となり、逆に1度は2π/360 ≒ 0.0174533ラジアンです。
ラジアンを使うと、30度はπ/6ラジアン、90度はπ/2ラジアン、45度はπ/4ラジアンのように表されます。

それではrotateの使い方について説明します。
rotateは引数に角度(単位はラジアン)を取り、引数の角度分原点を中心に空間を回転させます。


var w = 400;
var h = 400;
function setup() {
  createCanvas(w, h);
  background(0);
}

function draw() {
  rect(w/2,h/2,100, 100);
  push();
  rotate(PI / 6); //π/6は30°のこと
  rect(w/2,h/2,100, 100);
  pop();
}
        

原点中心の回転なので、ただrotateを使うだけだと移動してしまいます。

では、その場で回転させるにはどうすればいいでしょうか。
実は、その場回転は少しコツが必要で、まずtranslateで表示したい場所へ移動し、その上でrotateで回転させるという方法を使います。


var w = 400;
var h = 400;
function setup() {
  createCanvas(w, h);
  background(0);
}

function draw() {
  rect(100,100,100,100); //回転前の四角形
  push();
  translate(150, 150);  //表示したい場所へ移動
  rotate(PI / 6);       //原点中心の回転
  rect(-50,-50,100,100);//移動・回転させる図形。中心が原点になるように描く
  pop();
}
        

上手くその場回転できましたね。何が起きているかというと、rotateは原点中心に回転させる関数ですから、 中心が原点に描かれている四角形(rect(-50,-50,100,100))はその場で回転します。
また、translate(150, 150)は右下へ150ずつ移動させる命令です、なので、原点にあるものは (150, 150)へ移動します。
translateとrotateを組み合わせることで(150,150)が中心の四角形がその場で30°回転しているように見えるのです。

残念ながらその場回転はこんな複雑な方法しかないですが、translateとrotateの特性を理解して使えるようになりましょう。

応用例

クリックで動きが止まります。再度クリックするとまた動きます。


var w = 400;
var h = 400;
function setup() {
  createCanvas(w, h);
  background(100);
  frameRate(10);
}

function draw() {
  background(100);
  push();
  stroke(color(200, 0, 0));
  translate(200, 200);
  rotate(frameCount / 10);
  drawGear(20, 50);
  pop();

  push();
  stroke(color(0, 200, 0));
  translate(92, 200);
  rotate(-frameCount / 10 + 120);
  drawGear(20, 50);
  pop();

  push();
  stroke(color(0, 0, 200));
  translate(200, 92);
  rotate(-frameCount / 10);
  drawGear(20, 50);
  pop();

  push();
  stroke(color(0, 255, 255));
  translate(277, 277);
  rotate(-frameCount / 10 + 44);
  drawGear(20, 50);
  pop();
}

function drawGear(n, r){
  var rad = TWO_PI / n;

  for(i = 0; i < TWO_PI; i += 0.01){
    var y1 = 0;
    var y2 = 0;
    if(sin(i * n) >= 0){
      y1 = r;
    }else{
      y1 = r * 1.1;
    }
    line(y1 * cos(i), y1 * sin(i), 0, 0);
  }
  ellipse(0, 0, 10);
}
          

まとめ

  • 移動はtranslate関数を使う。translateは描画空間そのもののを動かす
  • push,popでtranslateやrotateでの変形を隔離することができる
  • rotateは回転を行う関数だが、原点中心の回転であることに注意する
Prev Next