"""
概要: 立方晶系の結晶面とゾーン軸を3Dで可視化するスクリプト。
詳細説明:
このスクリプトは、matplotlibを使用して3Dプロットを作成し、指定されたミラー指数(hkl)を持つ結晶面と、
それらの法線ベクトル、および特定のゾーン軸を描画します。
主に[001]ゾーン軸に属する結晶面を表示し、結晶学における面と軸の関係を視覚的に理解するのに役立ちます。
生成されたプロットはPNG画像として保存されます。
関連リンク: :doc:`zone_axes_usage`
"""
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
alpha = 0.1
[ドキュメント]
def plot_plane(ax, h, k, l, color, alpha, label):
"""
概要: ミラー指数(hkl)で定義される結晶面を3D空間にプロットします。
詳細説明:
この関数は、立方晶系においてミラー指数(hkl)で定義される結晶面を、
平面方程式 hx + ky + lz = d (ここではd=1を仮定) に基づいて3Dプロットします。
プロット範囲はx, y, z軸それぞれ[-1.5, 1.5]に制限され、この範囲外に出る部分は表示されません。
ミラー指数に特定のゼロ値がある場合の特殊なケース(例: l=0, k=0, h=0)も処理します。
軸オブジェクトに直接描画を行い、明示的な戻り値はありません。
:param ax: matplotlibの3D軸オブジェクト。平面が描画されるAxes3Dインスタンス。
:type ax: mpl_toolkits.mplot3d.axes3d.Axes3D
:param h: 平面のミラー指数 h。
:type h: int
:param k: 平面のミラー指数 k。
:type k: int
:param l: 平面のミラー指数 l。
:type l: int
:param color: 平面の色を示す文字列。例: 'red', 'blue'。
:type color: str
:param alpha: 平面の透明度 (0.0から1.0)。
:type alpha: float
:param label: 平面を示す凡例ラベル文字列。例: r'$(110)$'。
:type label: str
:returns: None
"""
grid_range = np.linspace(-1.5, 1.5, 50)
if l != 0:
xx, yy = np.meshgrid(grid_range, grid_range)
zz = (1 - h * xx - k * yy) / l
zz[(zz < -1.5) | (zz > 1.5)] = np.nan
ax.plot_surface(xx, yy, zz, color=color, alpha=alpha)
elif k != 0 and h != 0:
xx_plane, zz_plane = np.meshgrid(grid_range, grid_range)
yy_plane = (1 - h * xx_plane) / k
yy_plane[(yy_plane < -1.5) | (yy_plane > 1.5)] = np.nan
ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
elif h != 0 and k == 0 and l == 0:
yy_plane, zz_plane = np.meshgrid(grid_range, grid_range)
xx_plane = np.zeros_like(yy_plane)
ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
elif h == 0 and k != 0 and l == 0:
xx_plane, zz_plane = np.meshgrid(grid_range, grid_range)
yy_plane = np.zeros_like(xx_plane)
ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
elif h == 0 and k == 0 and l != 0:
xx_plane, yy_plane = np.meshgrid(grid_range, grid_range)
zz_plane = np.zeros_like(xx_plane)
ax.plot_surface(xx_plane, yy_plane, zz_plane, color=color, alpha=alpha)
else:
print(f"Warning: Cannot plot plane ({h}{k}{l})")
ax.plot([], [], [], color=color, label=label, alpha=alpha)
[ドキュメント]
def main():
"""
概要: 立方晶系の結晶面と[001]ゾーン軸を3Dで可視化し、画像を保存します。
詳細説明:
matplotlibを使用して3Dプロットを設定し、以下の要素を描画します。
- 3次元の軸とプロット範囲の設定。
- [001]ゾーン軸とそれに属する複数の結晶面(例: (110), (120), (010) など)。
- 各結晶面の法線ベクトル。
- 凡例とタイトル。
最終的に生成されたプロットは 'cubic_planes_001_zone.png' というファイル名で保存され、
画面にも表示されます。
:returns: None
"""
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
plot_limit = 1.5
ax.set_xlim([-plot_limit, plot_limit])
ax.set_ylim([-plot_limit, plot_limit])
ax.set_zlim([-plot_limit, plot_limit])
ax.set_xlabel('a')
ax.set_ylabel('b')
ax.set_zlabel('c')
ax.set_title('Cubic Crystal Planes with [001] Zone Axis')
zone_axis = np.array([0, 0, 1])
ax.quiver(0, 0, 0, zone_axis[0], zone_axis[1], zone_axis[2],
color='black', length=1.2, arrow_length_ratio=0.1)
ax.text(zone_axis[0] * 1.3, zone_axis[1] * 1.3, zone_axis[2] * 1.3,
r'$[001]$ Zone Axis', color='black')
planes_data = [
{'hkl': (1, 1, 0), 'color': 'red', 'label': r'$(110)$'},
{'hkl': (1, 2, 0), 'color': 'blue', 'label': r'$(120)$'},
{'hkl': (0, 1, 0), 'color': 'green', 'label': r'$(010)$'},
{'hkl': (1, -2, 0), 'color': 'purple', 'label': r'$(1\bar{2}0)$'},
{'hkl': (1, -1, 0), 'color': 'orange', 'label': r'$(1\bar{1}0)$'}
]
for plane_info in planes_data:
h, k, l = plane_info['hkl']
color = plane_info['color']
label = plane_info['label']
plot_plane(ax, h, k, l, color, alpha=alpha, label=label)
normal_vector = np.array([h, k, l])
if np.linalg.norm(normal_vector) > 0:
normal_vector_scaled = normal_vector / np.linalg.norm(normal_vector) * 0.8
ax.quiver(0, 0, 0,
normal_vector_scaled[0],
normal_vector_scaled[1],
normal_vector_scaled[2],
color=color, linestyle='--',
length=0.8, arrow_length_ratio=0.2)
ax.text(normal_vector_scaled[0] * 1.1,
normal_vector_scaled[1] * 1.1,
normal_vector_scaled[2] * 1.1,
label + ' normal', color=color)
ax.legend()
plt.tight_layout()
plt.savefig('cubic_planes_001_zone.png')
plt.show()
if __name__ == "__main__":
main()