Processing math: 0%

任意点周りの回転移動を2通り解説!プログラムで自動化!

この記事で解決できるお悩み

  • 回転した座標を求める方法を知りたい!
  • 座標の回転をプログラムで実装したい!

こんなお悩みを解決します。

この記事の内容

こんにちは、Youta(@youta_blog)です。

今回は「座標平面上での点の回転」「回転後の座標を出すプログラム」についてのお話です。

あなたは学生時代、以下のような問題を見たことはありますか?

xy平面上に点P(a, b)と点Q(c, d)がある。

Qを中心に、点Pを反時計回りに\theta回転させた点をP’とする。

ただし、PQ=P’Qである。

このとき、P’の座標を求めよ。

[20 慶應義塾大 薬学 7 改題]

解法を忘れてしまったり、そもそもどう解けばいいかわからない…という方が多いのではないでしょうか。

でもご安心ください!

本記事では、こうした問題に対処できる2通りのアプローチを解説します。

合わせて、コンピュータに自動で解かせるためのプログラムもご紹介します。

回転後の座標を導出する方法

まず始めに冒頭の問題の答えを示します。

答え

x座標: (a-c)\cos{\theta}-(b-d)\sin{\theta}+c

y座標: (b-d)\cos{\theta}+(a-c)\sin{\theta}+d

すずか

意味わからん。
大丈夫です。こうなる理由を以下の2通りの方法で解説しますね。

先生

三角関数を使うやり方

手順は簡単。たった3ステップです。

1ステップずつ詳しく見ていきましょう。

平行移動→Rの座標計算

まずは新しい変数を導入します。

最終的に消えてしまう変数ですので怖がらないでくださいね。

  • r: 線分PQの長さ
  • \phi: 動径ORx軸の正の向きとのなす角

線分PQを、Qが原点Oに重なるように平行移動させます。

原点が回転の中心となるようにするためです。

では、これから本題のPの移動先Rの座標を考えましょう。

そもそもQから原点Oに行くためには、Qx軸方向に-cy軸方向に-dだけ平行移動すればよいですね。

ということはPからRに行くのも同様、Px軸方向に-cy軸方向に-dだけ平行移動すればよいです。

よって、Rの座標が求まりました。

Rの座標(その1)

x座標: a-c

y座標: b-d

さらに角度\phiと動径ORに着目すると、三角関数の定義によりRの座標は別の形でも表せます。

Rの座標(その2)

x座標: a-c=r\cos{\phi}

y座標: b-d=r\sin{\phi}

加法定理→Sの座標計算

次は、Rを原点を中心に角度\thetaだけ回転させた点Sの座標を求めます。

r=PQ=RO=SOであるので、先ほどと同様に三角関数の定義によりSの座標は以下のようになります。

Sの座標

x座標: r\cos{(\phi+\theta)}

y座標: r\sin{(\phi+\theta)}

ここで三角関数の加法定理を使います。

三角関数の加法定理

\sin{(\alpha+\beta)}=\sin{\alpha}\cos{\beta}+\cos{\alpha}\sin{\beta}

\cos{(\alpha+\beta)}=\cos{\alpha}\cos{\beta}-\sin{\alpha}\sin{\beta}

上記の公式と先ほどのRの座標を考慮すると、Sの座標が以下のように計算できます。

Sの座標
x座標: \begin{align*} r\cos{(\phi+\theta)}&=r(\cos{\phi}\cos{\theta}-\sin{\phi}\sin{\theta}) \\ &=r\cos{\phi}\cos{\theta}-r\sin{\phi}\sin{\theta} \\ &=(a-c)\cos{\theta}-(b-d)\sin{\theta} \\ \end{align*}
y座標: \begin{align*} r\sin{(\phi+\theta)}&=r(\sin{\phi}\cos{\theta}+\cos{\phi}\sin{\theta}) \\ &=r\sin{\phi}\cos{\theta}+r\cos{\phi}\sin{\theta} \\ &=(b-d)\cos{\theta}+(a-c)\sin{\theta} \\ \end{align*}

すずか

r\phiが消えてスッキリした!

平行移動→P’の座標計算

最後に、Sを平行移動してP’を求めましょう。

平行移動量はSTEP1の平行移動→Rの座標計算のときと真逆です。

つまり、Sx軸方向にcy軸方向にdだけ平行移動します。

P’の座標

x座標: (a-c)\cos{\theta}-(b-d)\sin{\theta}+c

y座標: (b-d)\cos{\theta}+(a-c)\sin{\theta}+d

大変でしたね…。

以上が、三角関数を使っての導出の流れです。

先ほどの答えと一致していればOKです!

複素数平面を使うやり方

こちらも手順は3ステップからなります。

2以外は三角関数のときとほとんど変わらないのでご安心ください。

1ステップずつ詳しく見ていきます。

平行移動→Rの座標計算

線分PQを、Qが原点Oに重なるように平行移動させます。

原点が回転の中心となるようにするためです。

では、これから本題のPの移動先であるRの座標を考えましょう。

そもそもQから原点Oに行くためには、Qを実軸方向に-c、虚軸方向に-dだけ平行移動すればよいですね。

ということはPからRに行くのも同様、Pを実軸方向に-c、虚軸方向に-dだけ平行移動すればよいです。

よって、点Rが表す複素数が求まりました。

Rが表す複素数

実部: a-c

虚部: b-d

回転移動→Sの座標計算

次は、Rを原点を中心に角度\thetaだけ回転させた点Sの座標を求めます。

複素数平面に関して、以下の事実が成り立つことを利用します。

原点を中心とする回転

\alpha=\cos{\theta}+i\sin{\theta}と複素数zに対して、点\alpha zは、点zを原点を中心として\thetaだけ回転した点である。

上記の事実と先ほどのRが表す複素数を考慮すると、Sが表す複素数を以下のように計算できます。

Sが表す複素数

\alpha=\cos{\theta}+i\sin{\theta}とする。

Rが表す複素数をzとするとz=(a-c)+(b-d)i

よって、点Sが表す複素数は

\begin{align*} \alpha z&=(\cos{\theta}+i\sin{\theta})\{(a-c)+(b-d)i)\} \\ &=\cos{\theta}\{(a-c)+(b-d)i)\}+i\sin{\theta}\{(a-c)+(b-d)i)\} \\ &=(a-c)\cos{\theta}+(b-d)i\cos{\theta}+(a-c)i\sin{\theta}+(b-d)i^2\sin{\theta} \\ &=(a-c)\cos{\theta}+(b-d)i\cos{\theta}+(a-c)i\sin{\theta}-(b-d)\sin{\theta} \\ &=(a-c)\cos{\theta}-(b-d)\sin{\theta}+(b-d)i\cos{\theta}+(a-c)i\sin{\theta} \\ &=\{(a-c)\cos{\theta}-(b-d)\sin{\theta}\}+\{(b-d)\cos{\theta}+(a-c)\sin{\theta}\}i \\ \end{align*}
実部: (a-c)\cos{\theta}-(b-d)\sin{\theta}
虚部: (b-d)\cos{\theta}+(a-c)\sin{\theta}

平行移動→P’の座標計算

最後に、Sを平行移動してP’を求めましょう。

平行移動量はSTEP1の平行移動→Rの座標計算のときと真逆です。

つまり、Sを実軸方向にc、虚軸方向にdだけ平行移動します。

P’が表す複素数

実部: (a-c)\cos{\theta}-(b-d)\sin{\theta}+c

虚部: (b-d)\cos{\theta}+(a-c)\sin{\theta}+d

複素数平面上の実軸と虚軸の値は、それぞれxy平面上でのx軸・y軸の値です。

よって、これで点xy平面上でのP’の座標が求まりました。

以上が、複素数平面を使った導出の流れです。

どちらでも同じ答えが出るのが面白いですね!

すずか

当分はもう計算したくないよ…。
お疲れ様でした。

では、コンピューターにこの計算をお願いしましょうか。

先生

任意の点周りで座標を回転させるプログラムの実装

先ほどの理論を踏まえた上で、実際にプログラムを書いてみましょう。

以下に、指定した点を中心に座標を回転させる関数の実装例を示します。

実装例


import math


def rotate_point(point, center, angle, is_radian=False):
    # 点を中心周りに指定された角度分回転させる関数
    # point: 回転させる点の座標。一つ以上の座標を格納したタプル(リスト)。 (x, y) or (x1, y1, x2, y2, ...xn, yn)
    # center: 回転中心の座標 (x, y)
    # angle: 回転角度。デフォルトでは度数法。
    # is_radian: Trueの場合はangleを弧度法、Falseの場合は度数法で指定する。
    # 戻り値: 回転後の座標 (x, y) or (x1, y1, x2, y2, ...xn, yn)

    # 角度が度数法の場合は弧度法に変更
    if not is_radian:
        angle = math.radians(angle)

    sin_angle = math.sin(angle)
    cos_angle = math.cos(angle)

    # 回転した座標を格納するリスト
    rotated_points = []

    for i in range(0, len(point), 2):
        x, y = point[i] - center[0], point[i + 1] - center[1]

        # 回転後の座標を計算
        rotated_x = x * cos_angle - y * sin_angle + center[0]
        rotated_y = y * cos_angle + x * sin_angle + center[1]

        rotated_points.extend((rotated_x, rotated_y))

    return rotated_points
   

上記のコードでは、ある座標を中心周りに指定角度分回転させた座標を返す関数rotate_pointを定義しています。

引数
  • point: 回転させる座標。1つ以上の座標を格納したタプル(リスト)。
  • center: 回転中心の座標。
  • angle: 角度。デフォルトは度数法。
  • is_radian: Trueの場合はangleを弧度法、Falseの場合は度数法で指定。
戻り値
  • rotated_points: 回転後の座標を含む一次元リスト。

テスト

単一座標の回転

手始めに、慶應義塾大学の入試問題でも解かせましょう。

xy平面上に点P(9, 3)と点Q(3, 1)がある。

Qを中心に、点Pを反時計回りに15°回転させた点をP’とする。

ただし、PQ=P’Qである。

このとき、点P’の座標を求めると、x座標は□である。

[20 慶應義塾大 薬学 7]

答え

x座標: \sqrt{6}+2\sqrt{2}+3

(y座標: 2\sqrt{6}-\sqrt{2}+1)

ちなみに冒頭の問題の元ですよ。

先生

先ほどのコードの下に、以下のテストを書いて実行します。

p = (9, 3)  # 回転させたい座標
q = (3, 1)  # 中心の座標
theta = 15  # 回転角度(度数法)

answer = rotate_point(p, q, theta)

print(answer)  # 結果出力
-->[8.277916867529369, 4.484765923193261]

すずか

何この数?合ってんの?
結果の正誤について、以下にまとめたので興味のある方はどうぞ!

先生

座標

x座標】

  • 問題の答え: \sqrt{6}+2\sqrt{2}+3
  • 電卓の結果: 8.277916867529368
  • プログラム: 8.277916867529369

y座標】

  • 問題の答え: 2\sqrt{6}-\sqrt{2}+1
  • 電卓の結果: 4.484765923193261
  • プログラム: 4.484765923193261

複数座標の回転

実は先ほどのプログラムは、複数の座標を一気に回転させることができます。

ということで、次は図形の回転問題です。

複素数平面上の3点A,\ B,\ Cを表す複素数をそれぞれ

\begin{gather} z_1=2+i,\ z_2=1,\ z_3=2i \\ \end{gather}

とするとき、以下の問に答えなさい。

(1) \triangle{ABC}の重心Gを表す複素数gを求めなさい。

(2) 点A,\ B,\ Cをそれぞれ点Gを中心に\frac{\pi}{4}だけ回転した点を表す複素数w_1,\ w_2,\ w_3を求めなさい。

 [22 福岡女子大 環境科学 2]

答え

(1) g=1+i

(2) w_1=(1+\frac{\sqrt{2}}{2})+(1+\frac{\sqrt{2}}{2})i

\ \ \ \ \ w_2=(1+\frac{\sqrt{2}}{2})+(1-\frac{\sqrt{2}}{2})i

\ \ \ \ \ w_3=(1-\sqrt{2})+i

複素数が出てきますので、xy平面上の点に置換してテストをします。

先ほどのコードの下に、以下のテストを書いて実行します。

coords = (2, 1, 1, 0, 0, 2)  # 順にA, B, Cの座標 (A_x, A_y, B_x, B_y, C_x, C_y)
g = (1, 1)  # 三角形の重心
theta = math.pi / 4  # 回転角度(ラジアン)

answer = rotate_point(coords, g, theta, True)  # 角度がラジアンなので最後にTrueを入れる。

print(answer)  # 結果出力
-->[1.7071067811865475, 1.7071067811865475, 1.7071067811865475, 0.2928932188134524, -0.4142135623730949, 1.0]

すずか

なんかいっぱい出てきたんだけど!
順に回転後のAx,\ y座標、Bx,\ y座標、Cx,\ y座標です。

先生

Aの座標

x座標】

  • 問題の答え: 1+\frac{\sqrt{2}}{2}
  • 電卓の結果: 1.707106781186548
  • プログラム: 1.7071067811865475

y座標】

  • 問題の答え: 1+\frac{\sqrt{2}}{2}
  • 電卓の結果: 1.707106781186548
  • プログラム: 1.7071067811865475
Bの座標

x座標】

  • 問題の答え: 1+\frac{\sqrt{2}}{2}
  • 電卓の結果: 1.707106781186548
  • プログラム: 1.7071067811865475

y座標】

  • 問題の答え: 1-\frac{\sqrt{2}}{2}
  • 電卓の結果: 0.292893218813452
  • プログラム: 0.2928932188134524
Cの座標

x座標】

  • 問題の答え: 1-\sqrt{2}
  • 電卓の結果: -0.414213562373095
  • プログラム: -0.4142135623730949

y座標】

  • 問題の答え: 1
  • 電卓の結果: 1
  • プログラム: 1.0

すずか

正確すぎて怖いんだけど…。

任意の点周りで座標を回転させるプログラムの活用例

最後に、この点の回転が活躍する例をご紹介します。

アート制作

これはお花を描くプログラムです。

一見複雑そうですが、楕円を回転させて位置をずらしながら配置しているだけです。

このような幾何学的な模様も、点の回転によって簡単に描けてしまいます。

お花模様を描くプログラムに関する記事は、近日中にアップするのでお楽しみに!

図形の回転

お次は図形をマウスドラッグにより回転させるプログラムです。

ExcelやWord等でこの光景を目にしたことがあるかも知れませんね。

現在Tkinter搭載の関数では、図形を回転させることはできません。

しかし、今回ご紹介した点を回転させるプログラムを上手く使うと、このようにクルクル回すことが出来るのです。

下記記事にて、Tkinterで図形を回転させる方法を紹介しています。

>> 【Tkinter】図形を回転させる!自動で回転・ドラッグで回転

まとめ

この記事では、xy座標平面上の点を回転させるプログラムをご紹介しました。

三角関数と複素数平面での解説を載せましたが、回転行列によっても回転が可能です。

現状の関数単体ではあまり有用性を感じられませんが、図形を回転する際には真価を発揮しそうです。

最後までお付き合いいただきありがとうございました。

この記事に関するお悩みや疑問・質問などは、ご自由にコメント欄に投稿してください(コメント欄はこの記事の最下部です)。

※頂いたコメントは全て拝見し、真剣に回答させていただきます!

コメントを残す

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

CAPTCHA