5_1:移動(translate) p5.js JavaScript

座標変換は実際には、相当な数学的難問で、高校数学程度の知識(行列や三角関数など)が必要になりますが、p5.jsでは専用の関数が用意されているので、それらを適切に呼び出すだけで実現できます。とは言え、その舞台裏で行われていることを分かっておくことも重要で、本稿では、変換の中で最も単純な移動を見ていきます。

次のコードを実行すると、下図の結果が表示されます(グリッドの作成コードはのぞく)。

// 赤の矩形
fill(255, 0, 0);
rect(20, 20, 20, 40);

// 座標を右に40、下に20移す
translate(40, 20);
// 緑の矩形
fill(0, 255, 0);
rect(20, 20, 20, 40);

赤の矩形も緑も矩形も、同じ(20,20)を左上隅とする幅20、高さ40の矩形なのですが、translate(40, 20)によって、座標が右に40、下に20ずれたことで、緑の矩形は赤の矩形の右下に描画されます。これが移動の座標変換です。

座標変換は行列同士の掛け算で表されます。2行2列同士の行列の掛け算は次の要領で計算します。

行列の積の計算方法と例題

点(x, y)を、X軸方向にTx、Y軸方向にTyだけ移動する計算は次の行列の掛け算で行います。

行列の扱いが得意なTensorFlow.jsという機械学習用のライブラリを使って、計算してみます。

// 平行移動行列(translate)
const Tx = 40;
const Ty = 20;

// 平行移動の変換行列
const TM = tf.tensor2d(
    [1, 0, Tx,
        0, 1, Ty,
        0, 0, 1
    ], [3, 3]);
TM.print();

const x = 20;
const y = 20;
const m = tf.tensor2d([x, y, 1], [3, 1]);
m.print();

TM.matMul(m).print();

コンソールには次の結果が出力されます。

上から1つめは、平行移動の変換を行いたいときに、掛け算の左に置く行列です。変数Txに40、Tyに20が代入されているので、(40, 20)だけ座標が平行移動することになります。2つめの出力は、変換される対象の行列で、(20,20)です。赤と緑の矩形の左上隅となる座標です。そして3つめが変換後の行列です。(60,40)という結果は、緑の矩形が実際に描かれた左上隅の座標と一致します。

なぜ行列を使うのか?

行列なんて忘れてしまった、という方は、p5.jsを使う限り、行列の計算で、何と何を掛けて足すのかを覚える必要はありません。行列は単に、変換の複雑な計算を簡単に見せるために使われているだけです。

位置の移動

現在のマウスカーソルの位置に矩形を描画するサンプルです。

function setup() {
    createCanvas(120, 120);
    background(204);
    strokeWeight(2);
    fill(255, 0, 0)
}

function draw() {
    // 現在のカーソル位置にキャンバスの原点(0,0)を移動する
    translate(mouseX, mouseY);
    // 現在のキャンバスの原点を左上隅とする矩形を描く
    rect(0, 0, 30, 30)
}

translate()関数は、キャンバスの座標(0,0)を、(mouseX, mouseY)に設定します。draw()関数は繰り返し呼び出され、そのたびにrect()関数は新しい原点(0, 0)に矩形を描画します。

translate()

説明

表示ウィンドウ内でオブジェクトを移動させる量を指定する。xパラメータは左右方向の移動量を、yパラメータは上下方向の移動量を指定する。

変換は累積的に作用する。その後に発生するすべてのものに適用され、関数への以降の呼び出しによって効果が蓄積される。たとえばtranslate(50, 0)を呼び出した後、translate(20, 0)を呼び出すことは、translate(70, 0)と同じ。draw()内でtranslate()を呼び出すと、変換は、次のループが始まるときにリセットされる。この関数は、push()pop()関数の使用によってさらに制御することができる。

シンタックス

translate(x, y, [z])
translate(vector)

複数のtranslate()

作成された変換は、以降のすべての描画関数に適用されます。1つめの矩形はマウスカーソルで制御し、2つめの矩形は(35,10)だけ移動させようと考えると、次のようなコードが書けそうです。

function draw() {
    translate(mouseX, mouseY);
    rect(0, 0, 30, 30);
    translate(35, 10);
    rect(0, 0, 15, 15)
}

しかし、複数のtranslate()関数からの複数の値はいっしょに追加されます。2つめの小さい矩形はじっととしていず、マウスの動きに合わせて、mouseX + 35とmouseY + 10だけ移動します。そして変換は、次のdraw()関数が始まるときに、リセットされます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA