この記事で解決できるお悩み
- 回転した座標を求める方法を知りたい!
- 座標の回転をプログラムで実装したい!
こんなお悩みを解決します。
この記事の内容
こんにちは、Youta(@youta_blog)です。
今回は「座標平面上での点の回転」「回転後の座標を出すプログラム」についてのお話です。
あなたは学生時代、以下のような問題を見たことはありますか?
xy平面上に点P(a, b)と点Q(c, d)がある。
点Qを中心に、点Pを反時計回りに\theta回転させた点をP’とする。
ただし、PQ=P’Qである。
このとき、点P’の座標を求めよ。
[20 慶應義塾大 薬学 7 改題]
解法を忘れてしまったり、そもそもどう解けばいいかわからない…という方が多いのではないでしょうか。
でもご安心ください!
本記事では、こうした問題に対処できる2通りのアプローチを解説します。
合わせて、コンピュータに自動で解かせるためのプログラムもご紹介します。
Contents [hide]
回転後の座標を導出する方法
まず始めに冒頭の問題の答えを示します。
答え
x座標: (a-c)\cos{\theta}-(b-d)\sin{\theta}+c
y座標: (b-d)\cos{\theta}+(a-c)\sin{\theta}+d
すずか
先生
三角関数を使うやり方
手順は簡単。たった3ステップです。
1ステップずつ詳しく見ていきましょう。
平行移動→Rの座標計算
まずは新しい変数を導入します。
最終的に消えてしまう変数ですので怖がらないでくださいね。
- r: 線分PQの長さ
- \phi: 動径ORとx軸の正の向きとのなす角
線分PQを、Qが原点Oに重なるように平行移動させます。
原点が回転の中心となるようにするためです。
では、これから本題のPの移動先Rの座標を考えましょう。
そもそもQから原点Oに行くためには、Qをx軸方向に-c、y軸方向に-dだけ平行移動すればよいですね。
ということはPからRに行くのも同様、Pをx軸方向に-c、y軸方向に-dだけ平行移動すればよいです。
よって、Rの座標が求まりました。
x座標: a-c
y座標: b-d
さらに角度\phiと動径ORに着目すると、三角関数の定義によりRの座標は別の形でも表せます。
x座標: a-c=r\cos{\phi}
y座標: b-d=r\sin{\phi}
加法定理→Sの座標計算
次は、Rを原点を中心に角度\thetaだけ回転させた点Sの座標を求めます。
r=PQ=RO=SOであるので、先ほどと同様に三角関数の定義により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の座標が以下のように計算できます。
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*}
すずか
平行移動→P’の座標計算
最後に、Sを平行移動してP’を求めましょう。
平行移動量はSTEP1の平行移動→Rの座標計算のときと真逆です。
つまり、Sをx軸方向にc、y軸方向にdだけ平行移動します。
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が表す複素数が求まりました。
実部: a-c
虚部: b-d
回転移動→Sの座標計算
次は、Rを原点を中心に角度\thetaだけ回転させた点Sの座標を求めます。
複素数平面に関して、以下の事実が成り立つことを利用します。
\alpha=\cos{\theta}+i\sin{\theta}と複素数zに対して、点\alpha zは、点zを原点を中心として\thetaだけ回転した点である。
上記の事実と先ほどのRが表す複素数を考慮すると、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だけ平行移動します。
実部: (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]
すずか
先生
【x座標】
- 問題の答え: 1+\frac{\sqrt{2}}{2}
- 電卓の結果: 1.707106781186548
- プログラム: 1.7071067811865475
【y座標】
- 問題の答え: 1+\frac{\sqrt{2}}{2}
- 電卓の結果: 1.707106781186548
- プログラム: 1.7071067811865475
【x座標】
- 問題の答え: 1+\frac{\sqrt{2}}{2}
- 電卓の結果: 1.707106781186548
- プログラム: 1.7071067811865475
【y座標】
- 問題の答え: 1-\frac{\sqrt{2}}{2}
- 電卓の結果: 0.292893218813452
- プログラム: 0.2928932188134524
【x座標】
- 問題の答え: 1-\sqrt{2}
- 電卓の結果: -0.414213562373095
- プログラム: -0.4142135623730949
【y座標】
- 問題の答え: 1
- 電卓の結果: 1
- プログラム: 1.0
すずか
任意の点周りで座標を回転させるプログラムの活用例
最後に、この点の回転が活躍する例をご紹介します。
アート制作
これはお花を描くプログラムです。
一見複雑そうですが、楕円を回転させて位置をずらしながら配置しているだけです。
このような幾何学的な模様も、点の回転によって簡単に描けてしまいます。
お花模様を描くプログラムに関する記事は、近日中にアップするのでお楽しみに!
図形の回転
動画プレーヤー
お次は図形をマウスドラッグにより回転させるプログラムです。
ExcelやWord等でこの光景を目にしたことがあるかも知れませんね。
現在Tkinter搭載の関数では、図形を回転させることはできません。
しかし、今回ご紹介した点を回転させるプログラムを上手く使うと、このようにクルクル回すことが出来るのです。
下記記事にて、Tkinterで図形を回転させる方法を紹介しています。
>> 【Tkinter】図形を回転させる!自動で回転・ドラッグで回転
まとめ
この記事では、xy座標平面上の点を回転させるプログラムをご紹介しました。
三角関数と複素数平面での解説を載せましたが、回転行列によっても回転が可能です。
現状の関数単体ではあまり有用性を感じられませんが、図形を回転する際には真価を発揮しそうです。
最後までお付き合いいただきありがとうございました。
この記事に関するお悩みや疑問・質問などは、ご自由にコメント欄に投稿してください(コメント欄はこの記事の最下部です)。