JS奮闘記【JavaScriptとcanvasと線形変換 その2 ~任意の点を中心にした回転編~】

JS奮闘記 canvasと線形変換

こんにちは。エンジニアの辻です。
前回(JS奮闘記【JavaScriptとcanvasと線形変換 ~回転編~】)は、線形変換を使ってcanvas上のボックスを回転させてみました。
さて、ボックスを回転できるようになったのは良いのですが、回転の中心は原点のままです。
今回は回転の中心を原点ではなく、任意の点にした上でボックスを回転させてみたいと思います。

任意の点を中心として回転させる線形変換

まずはこちらをご覧ください。
この数式が任意の点を中心として回転(反時計回り)させる線形変換の計算式になります。
前回扱った式と似ていますね。

任意の点を中心として回転(反時計回り)させる線形変換

なぜこの数式で任意の点を中心とした回転が可能なのか解説していきます。
なんか難しそうですが、処理を1つずつ追っていけば大丈夫です!

まず、以下の2次元平面をご覧ください。
点Pが回転の中心点であり、座標は(a, b)とします。
点Aが回転対象の赤ボックスの中心点です。座標は(x, y)とします。

 

線形変換の説明 初期状態

 

上図の状態から点P、Aそれぞれのxを-a。yを-bします。
すると、以下の図のように点Pが原点に重なるように平行移動します。
この時の点PをP’。点AをA’としましょう。
点P’は(a – a, b – b)なので(0, 0)となり、点A’は(x – a, y – b )となります。

 

線形変換の説明 点Pを原点に移動

 

次に、点P'(原点)を中心としてθ°で回転の線形変換を行います。
すると、点A’がθ°移動した点Bが得られます。点Bは(x’, y’)とします。
2次元平面で表すと以下のようになります。

ここまでで任意の点を中心として回転させる線形変換の計算式の前半まで完了しました。

 

線形変換の説明 原点を中心点にした反時計周りの回転

 

あとはカンタンです。
点数P’、A’、Bそれぞれのxに+a、yに+bをして平行移動させます。
この平行移動によって、点P’、A’は、元の点P、Aの位置に戻ります。
点Bは点B’に移動します。この点B’が点Pを中心にしてθ°回転した時の座標(x”, y”)になるわけです。

 

線形変換の説明 回転の中心点を戻す

canvas上で回転処理を実装してみる

今回の成果物

まずは今回の成果物のスクリーンショットをどうぞ。
前半で解説した線形変換の計算式をcanvas上で実行してみた結果です。
 

任意の点を中心にした回転の線形変換の成果物

 

赤ボックスが初期配置のオブジェクトです。(200, 200)の位置に配置しました。
回転の中心点は(80, 120)の位置に配置しています。
この中心点を元に赤オブジェクトを反時計回りに回転させ、回転後の位置にボックスを描画しています。

青ボックスは中心点を元に、赤ボックスを60°回転させたボックスです。
緑ボックスは120°。黄色ボックスは180°回転させています。
図解すると以下のようになります。

 

任意の点を中心にした回転の線形変換の成果物の解説

ソースコードの解説

それでは、ソースコードの解説に入っていきます。

ソースコードの構成は前回と同様です。
index.htmlとmain.jsがあるだけのシンプルな構成です。
index.htmlは前回から変わっていません。変更したのはmain.jsのみです。

main.jsの全文は以下の通りです。

処理の流れは前回と同じで…
canvasの原点を画面中央に配置して、y軸のプラス・マイナスを反転。
そして、原点、x軸、y軸の描画を行った後、ボックスの回転処理と描画…となっています。

大きく変更になったのはlinearTransformation関数の中身です。
前回は原点を中心にした回転だけに対応していましたが、今回は任意の点を受け取り、その点を中心にした回転を行えるようになっています。

線形変換処理(linearTransformation)の解説

では、肝心のlinearTransformation関数の中身を見ていきましょう。
…と言っても難しい事は何もやっていません。
linearTransformation関数でやっている事は、本記事の前半で解説した計算式を、そっくりそのままJavaScriptに置き換えているだけです。

はじめに引数についてですが、targetが回転対象の座標。degreeは回転させる角度。basicPointが回転の中心点となっています。

basicPointには初期値として、{x: 0, y: 0}を入れています。
この初期値があることで、basicPointに何も入らなければ、回転の中心点は原点となり、basicPointに座標が入れば、その座標が回転の中心点となるわけです。

処理の初めは、引数のdegreeからラジアンを算出しています。
この処理は前回と同じですね。

次に、中心点を原点に移動させた上で線形変換の計算をしています。
計算結果はfirstTransformationに格納されます。
このfirstTransformationが、任意の点を中心として回転させる線形変換の計算式の前半に該当します。

最後にfirstTransformationのxとyに、回転の中心点basicPointのxとyをそれぞれ加算します。
この加算が、任意の点を中心として回転させる線形変換の計算式の後半に該当します。
これで任意の点であるbasicPointを中心に回転した後の(x, y)が得られます。

あとは戻り値を使って、ボックスを描画するだけですね。

まとめ

前回から引き続き、線形変換を使ってcanvas上での回転処理を実装しました。
ここまでくれば、どんな回転であっても表現できそうですね。

次回も、もうちょっとだけ線形変換をやってみたいと思います。
もうちっとだけ続くんじゃ。

次回の記事: JS奮闘記【JavaScriptとcanvasと線形変換 その3 ~様々な線形変換編~】



❏❏ TOPIC ❏❏ ------------------------------------------------------------

カスタム自由!フリーECサイトパッケージ
チャットボット導入サービス
WEBシステム開発・スマホアプリ開発はSRIAへ