LoginSignup
2
11

More than 5 years have passed since last update.

Pythonによる回転行列と法線ベクトルの実装

Last updated at Posted at 2017-11-07

0. Pythonによる回転行列と法線ベクトルの実装

色々と図形をぐるぐるまわしたいと思ったので実装した。
図形を回転させたら軌跡は円になるので、回転行列で計算可能なのである。

1. 回転行列

python 3.6を用いた。回転行列の数式は以下を参考にした。
http://1st.geocities.jp/shift486909/program/spin.html

2次元

{\begin{equation}
\begin{vmatrix}
X' \\
Y' \\
\end{vmatrix}
=
\begin{vmatrix}
\cos\theta &-\sin\theta \\
\sin\theta &\cos\theta \\
\end{vmatrix}
\times
\begin{vmatrix}
X \\
Y \\
\end{vmatrix}
\end{equation}
}

3次元 (Z軸周り= x -> y)

{\begin{equation}
\begin{vmatrix}
X' \\
Y' \\
Z' \\
\end{vmatrix}
=
\begin{vmatrix}
\cos\theta z &-\sin\theta z &0 \\
\sin\theta z &\cos\theta z &0 \\
0 &0 &1 \\
\end{vmatrix}
\times
\begin{vmatrix}
X \\
Y \\
Z \\
\end{vmatrix}
\end{equation}
}

今回は2次元で実装


# -*- coding: utf-8 -*-
import numpy as np


if __name__ == '__main__':

    # matrix
    a = np.matrix([2.5, 2.5]).A1
    b = np.matrix([5, 5]).A1
    print("a=" + str(a))
    print("b=" + str(b))
    # AB = AC = r
    pythagoras = b - a
    r = np.sqrt( (pythagoras[0] * pythagoras[0]) + (pythagoras[1] * pythagoras[1] ))
    print("r=" + str(r))

    # tan theta (Inclination)
    tant = (b[1] - a[1]) / (b[0] - a[0])
    # theta
    tan = np.arctan(tant)
    # AD = r*cos α
    # BD = r*sin α
    AD = r * np.cos(tan)
    BD = r * np.sin(tan)
    print("AD=" + str(AD))
    print("BD=" + str(BD))

    theta = np.deg2rad(90)

    rotateMat = np.matrix([
        [np.cos(theta), -np.sin(theta)],
        [np.sin(theta), np.cos(theta)],
    ])

    print(rotateMat)

    xy = np.matrix([[AD], [BD]])

    cxy = (rotateMat * xy)
    cxy = cxy.A1 + a
    print("cxy=" + str(cxy) )

    print("------------------")
    # cx = AD*cos θ-BD*sin θ+ax
    # cy = AD*sin θ+BD*cos θ+ay
    AD2 = b[0] - a[0]
    BD2 = b[1] - a[1]
    cx = ((AD2 * np.cos(theta)) - (BD2 * np.sin(theta))) + a[0]
    print(cx)
    cy = ((AD2 * np.sin(theta)) + (BD2 * np.cos(theta))) + a[1]
    print(cy)

1.1. 回転行列 - 関数化

関数化

def calcRot(_posxy, _orgxy, _rad):
    ADBD = _posxy - _orgxy
    ADBD = np.matrix([[ADBD[0]], [ADBD[1]]])
    rotateMat = np.matrix([
        [np.cos(_rad), -np.sin(_rad)],
        [np.sin(_rad), np.cos(_rad)],
    ])
    cxy = (rotateMat * ADBD).A1 + _orgxy

    return  cxy

こんな感じに使えばおk

 _posxy = np.matrix([_x, _y]).A1
 _orgxy = np.matrix([_x, _y]).A1
 _rad = np.deg2rad(90)

 rotatedPos = calcRot(_posxy, _orgxy, _rad)

1.2. 回転行列 - 複素数

コメントで教えて貰いましたが、回転行列は複素数でも表現できるらしい。

イメージ的にはこんな感じ。
https://atarimae.biz/wp-content/uploads/2015/05/fourway.png

確かに。

# -*- coding: utf-8 -*-
import numpy as np

if __name__ == '__main__':

    A = 2.5 + 2.5j
    B = 5.0 + 5.0j
    print('A=' + str(A))
    print('B=' + str(B))

    theta = np.deg2rad(90)
    rotate = np.cos(theta) + 1j * np.sin(theta) # = np.exp(1j * theta)

    AB = B - A
    AC = rotate * AB
    C  = AC + A
    print('C=' + str(C))

2. 法線ベクトル

法線ベクトルは対象とする直線に直交していればよいので、回転行列を用いて90度回転させるだけでよいのである。
もちろん他にもやり方は沢山ある。私は同じ関数(回転行列)を使いまわせるのでこれを使っている。

def calcNorm_vec(_posxy, _orgxy):
    ADBD = _posxy - _orgxy
    ADBD = np.matrix([[ADBD[0]], [ADBD[1]]])
    theta = np.deg2rad(90)
    rotateMat = np.matrix([
        [np.cos(theta), -np.sin(theta)],
        [np.sin(theta), np.cos(theta)],
    ])
    cxy = (rotateMat * ADBD)
    vv = cxy.A1
    nv = vv / np.linalg.norm(vv)
    return nv

以上。

2
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
11