0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Pythonを用いた回転行列(1)

Posted at

3D空間における座標変換例

(1,1,1)の点をX軸まわりに30度回転するPythonプログラム

工学分野において,回転行列はよく用いられる.
Pythonパッケージ NumPy の配列 Arrayモジュールの使い方の例として,
サンプルプログラムを示す.

座標変換が分かりやすいように,元の位置と移動後の位置をアニメーションとして可視化するとともに,
gifファイルとして出力するようにした.

3d_rotation_animation.gif

rot_matrix.py
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import imageio

def rotate_x(point, angle_deg):
    """
    指定された点をx軸周りに回転させる変換行列を適用する関数

    Args:
        point (np.array): 回転させる点の座標 (x, y, z)
        angle_deg (float): 回転角度(度数法)

    Returns:
        np.array: 回転後の点の座標
    """
    angle_rad = np.radians(angle_deg)
    
    # x軸周りの回転行列
    # R_x = [[1, 0, 0],
    #        [0, cos(theta), -sin(theta)],
    #        [0, sin(theta), cos(theta)]]
    rotation_matrix = np.array([
        [1, 0, 0],
        [0, np.cos(angle_rad), -np.sin(angle_rad)],
        [0, np.sin(angle_rad), np.cos(angle_rad)]
    ])
    
    # 点に変換行列を適用
    rotated_point = np.dot(rotation_matrix, point)
    return rotated_point

# 元の点
original_point = np.array([1, 1, 1])

# 回転角度
rotation_angle_deg = 30

# 回転後の点
rotated_point = rotate_x(original_point, rotation_angle_deg)

print(f"元の点: {original_point}")
print(f"X軸周りに{rotation_angle_deg}度回転後の点: {rotated_point}")

## GIFアニメーションの生成

fig = plt.figure(figsize=(8, 8))
ax = fig.add_subplot(111, projection='3d')

# 軸ラベルの設定
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

# 軸の範囲を設定 (点の移動範囲を考慮して少し広めに)
ax.set_xlim([-1.5, 1.5])
ax.set_ylim([-1.5, 1.5])
ax.set_zlim([-1.5, 1.5])

# プロットの初期化
# 元の点と回転後の点を表示
# ここで凡例に回転後の座標値を含める
ax.plot([original_point[0]], [original_point[1]], [original_point[2]], 'ro', markersize=8, label='Original Point (1,1,1)')
ax.plot(
    [rotated_point[0]], [rotated_point[1]], [rotated_point[2]], 
    'bo', markersize=8, label=f'Rotated Point ({rotation_angle_deg} deg): ({rotated_point[0]:.2f}, {rotated_point[1]:.2f}, {rotated_point[2]:.2f})'
)

# 現在の点をプロットするハンドラ
point_handler, = ax.plot([], [], [], 'go', markersize=10, label='Moving Point')

# 凡例の表示
ax.legend()

# アニメーションのフレーム数 (1秒間で移動、例えば50フレーム)
num_frames = 50
interval_ms = 1000 / num_frames # 1秒 / フレーム数

def update(frame):
    """
    アニメーションの各フレームを更新する関数
    """
    # 線形補間により、元の点から回転後の点へ移動
    # tは0から1まで変化
    t = frame / (num_frames - 1)
    
    current_point = original_point * (1 - t) + rotated_point * t
    
    point_handler.set_data([current_point[0]], [current_point[1]])
    point_handler.set_3d_properties([current_point[2]])
    
    return point_handler,

# アニメーションの作成
ani = FuncAnimation(fig, update, frames=num_frames, blit=True, interval=interval_ms)

# GIFとして保存
gif_filename = "3d_rotation_animation.gif"
ani.save(gif_filename, writer='imageio', fps=num_frames / 1) # fpsは1秒あたりのフレーム数

print(f"アニメーションGIF '{gif_filename}' が生成されました。")

plt.show()
0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?