import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# 空間曲線の定義(例としてヘリカルカーブを使用)
def r(s):
x = np.cos(s)
y = np.sin(s)
z = s
return np.array([x, y, z])
# 曲線の微分(接線ベクトル、加速度ベクトルの計算)
def dr_ds(s):
x_prime = -np.sin(s)
y_prime = np.cos(s)
z_prime = 1
return np.array([x_prime, y_prime, z_prime])
def d2r_ds2(s):
x_double_prime = -np.cos(s)
y_double_prime = -np.sin(s)
z_double_prime = 0
return np.array([x_double_prime, y_double_prime, z_double_prime])
# 曲線上の点sでの接線ベクトル、主法線ベクトル、従法線ベクトルを計算
def frenet_frame(s):
e1 = dr_ds(s) / np.linalg.norm(dr_ds(s))
e1_prime = d2r_ds2(s)
kappa = np.linalg.norm(e1_prime) # 曲率
e2 = e1_prime / kappa if kappa != 0 else np.zeros_like(e1) # 主法線ベクトル
e3 = np.cross(e1, e2) # 従法線ベクトル
return e1, e2, e3, kappa
# sの範囲を設定
s_values = np.linspace(0, 4 * np.pi, 100)
# 曲線、接線ベクトル、主法線ベクトル、従法線ベクトルを計算
r_values = np.array([r(s) for s in s_values])
tangent_vectors = np.array([frenet_frame(s)[0] for s in s_values])
normal_vectors = np.array([frenet_frame(s)[1] for s in s_values])
binormal_vectors = np.array([frenet_frame(s)[2] for s in s_values])
curvature_values = np.array([frenet_frame(s)[3] for s in s_values])
# 3Dプロットの設定
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 曲線の描画
ax.plot(r_values[:, 0], r_values[:, 1], r_values[:, 2], label='Curve', color='b')
# フレネの標構の描画(間隔を置いて描画)
for i in range(0, len(s_values), 10):
ax.quiver(r_values[i, 0], r_values[i, 1], r_values[i, 2],
tangent_vectors[i, 0], tangent_vectors[i, 1], tangent_vectors[i, 2],
color='r', length=0.5, normalize=True, label='Tangent Vector (e1)' if i == 0 else "")
ax.quiver(r_values[i, 0], r_values[i, 1], r_values[i, 2],
normal_vectors[i, 0], normal_vectors[i, 1], normal_vectors[i, 2],
color='g', length=0.5, normalize=True, label='Normal Vector (e2)' if i == 0 else "")
ax.quiver(r_values[i, 0], r_values[i, 1], r_values[i, 2],
binormal_vectors[i, 0], binormal_vectors[i, 1], binormal_vectors[i, 2],
color='b', length=0.5, normalize=True, label='Binormal Vector (e3)' if i == 0 else "")
# ラベルとタイトルの設定
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_title('Frenet-Serret Frame along a Helical Curve')
ax.legend()
plt.show()
# 曲率の表示
plt.plot(s_values, curvature_values, label='Curvature (κ)')
plt.xlabel('Arc Length (s)')
plt.ylabel('Curvature (κ)')
plt.title('Curvature along the Curve')
plt.grid(True)
plt.legend()
plt.show()