【raytracing】光線が集まる位置(結像位置)を取得し、図に表示する方法[Python]

  • URLをコピーしました!

raytracing

前回、raytracingライブラリを使ってABCD行列のそれぞれの値と焦点位置を取得し、図に追加する方法を紹介しました。

今回は光線が集まる位置(結像位置)を取得し、図に表示する方法を紹介します。

まず前回までのプログラムのおさらいですが、焦点位置を表示するところまでできており、こんな感じです。

from raytracing import *
import matplotlib.pyplot as plt

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

#----------位置、角度情報取得ここから----------
y_list = []; z_list = []; theta_list = []
for angle in angle_list:
    ray = Ray(y=0, theta=np.radians(angle))
    trace = path.trace(ray)

    y_optics = []; z_optics = []; theta_optics = []
    for data in trace:
        y_optics.append(data.y)
        z_optics.append(data.z)
        theta_optics.append(data.theta)
    y_list.append(y_optics)
    z_list.append(z_optics)
    theta_list.append(theta_optics)
#----------位置、角度情報取得ここまで----------

#----------光線プロットここから----------
fig = plt.figure()
plt.clf()

for y_optics, z_optics in zip(y_list, z_list):
    plt.plot(z_optics, y_optics, color="red", lw=0.5)

#----------焦点距離取得&プロットここから----------
position = 0
for optics in path:
    optics_position = optics.B
    position = position+optics_position
    ffl = optics.frontFocalLength()
    bfl = optics.backFocalLength()
    if ffl != None and bfl != None:
        plt.scatter(position+ffl, 0, color="black", s=5)
        plt.scatter(position-bfl, 0, color="black", s=5)
#----------焦点距離取得&プロットここまで----------

plt.xlabel("Distance")
plt.ylabel("Height")
plt.show()
#----------光線プロットここまで----------

実行結果

光線が集まる位置の取得方法

光線が集まる位置を取得するには前に紹介した「光線の高さや位置、角度を取得する方法」が重要になります。

上のプログラムでもありますが、この部分です。

y_list = []; z_list = []; theta_list = []
for angle in angle_list:
    ray = Ray(y=0, theta=np.radians(angle))
    trace = path.trace(ray)

    y_optics = []; z_optics = []; theta_optics = []
    for data in trace:
        y_optics.append(data.y)
        z_optics.append(data.z)
        theta_optics.append(data.theta)
    y_list.append(y_optics)
    z_list.append(z_optics)
    theta_list.append(theta_optics)

この部分では全部の位置(z)、高さ(y)、角度(theta)を取得していますが、光線が集まる位置を取得するにはレンズを通った後の位置と高さ、その後の空間を通った後の位置と高さが必要になります。

今回は「最後に」光線が集まる位置を取得することとして、位置を集めたリスト(z_list)、高さを集めたリスト(y_list)からそれぞれの光線のデータを取り出し、さらにその光線のデータの最後から2番目(レンズを通った後)と一番最後(空間を通った後)の位置と高さのデータと取得します。

for y_ray, z_ray in zip(y_list, z_list):
    z1 = z_ray[-2]; z2 = z_ray[-1]
    y1 = y_ray[-2]; y2 = y_ray[-1]

そしてこの部分は直背であるため、1次関数で表すことができます。

\( y = ax + b\)

今回、レンズ後の点(z1, y1)から空間後の点(z2, y2)の直線であり、光線が集まる場所としては高さ0のところになるため、式としてはこんな感じになります。

\( 0 = \frac{(y2-y1)}{(z2-z1)}x -y1\)

これをxについて解くとこんな感じです。

\(x = -y1 \frac{(z2-z1)}{(y2-y1)}\)

そして得られた値は光線が集まる場所の位置、つまりzの値になりますが、レンズまでの位置の距離は考慮されていないため、最後にレンズまでの位置を足すと光学系の中で光線が集まる位置となります。

from raytracing import *

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

y_list = []; z_list = []; theta_list = []
for angle in angle_list:
    ray = Ray(y=0, theta=np.radians(angle))
    trace = path.trace(ray)

    y_optics = []; z_optics = []; theta_optics = []
    for data in trace:
        y_optics.append(data.y)
        z_optics.append(data.z)
        theta_optics.append(data.theta)
    y_list.append(y_optics)
    z_list.append(z_optics)
    theta_list.append(theta_optics)

cross_list = []
for y_ray, z_ray in zip(y_list, z_list):
    z1 = z_ray[-2]; z2 = z_ray[-1]
    y1 = y_ray[-2]; y2 = y_ray[-1]
    cross = -y1*(z2-z1)/(y2-y1)
    cross_point = cross + z1
    cross_list.append(cross_point)

print(cross_list)

実行結果
[np.float64(62.5), np.float64(62.5), np.float64(62.5), 
np.float64(nan), np.float64(62.5), np.float64(62.5), np.float64(62.5)]

光線の集まる位置を図に追加

次に光線の集まる位置を図に追加しますが、今回は矢印を追加できる「annotate」を使ってみます。

from raytracing import *
import matplotlib.pyplot as plt

path = ImagingPath()
path.append(Space(d=50))
path.append(Lens(f=10))
path.append(Space(d=50))

angle_list = np.linspace(-10, 10, 7)

#----------位置、角度情報取得ここから----------
y_list = []; z_list = []; theta_list = []
for angle in angle_list:
    ray = Ray(y=0, theta=np.radians(angle))
    trace = path.trace(ray)

    y_optics = []; z_optics = []; theta_optics = []
    for data in trace:
        y_optics.append(data.y)
        z_optics.append(data.z)
        theta_optics.append(data.theta)
    y_list.append(y_optics)
    z_list.append(z_optics)
    theta_list.append(theta_optics)
#----------位置、角度情報取得ここまで----------

#----------結像位置取得ここから----------
cross_list = []
for y_ray, z_ray in zip(y_list, z_list):
    z1 = z_ray[-2]; z2 = z_ray[-1]
    y1 = y_ray[-2]; y2 = y_ray[-1]
    cross = -y1*(z2-z1)/(y2-y1)
    cross_point = cross + z1
    cross_list.append(cross_point)
#----------結像位置取得ここまで----------

#----------光線プロットここから----------
fig = plt.figure()
plt.clf()

for y_optics, z_optics in zip(y_list, z_list):
    plt.plot(z_optics, y_optics, color="red", lw=0.5)

#----------結像位置プロットここから----------
for point in cross_list:
    plt.annotate("", xy=[point, 2], xytext=[point, 7], arrowprops=dict())
#----------結像位置プロットここまで----------

#----------焦点距離取得&プロットここから----------
position = 0
for optics in path:
    optics_position = optics.B
    position = position+optics_position
    ffl = optics.frontFocalLength()
    bfl = optics.backFocalLength()
    if ffl != None and bfl != None:
        plt.scatter(position+ffl, 0, color="black", s=5)
        plt.scatter(position-bfl, 0, color="black", s=5)
#----------焦点距離取得&プロットここまで----------

plt.xlabel("Distance")
plt.ylabel("Height")
plt.show()
#----------光線プロットここまで----------

実行結果

次回はraytracingライブラリで焦点距離を変化させ、特定の高さ(サイズ)の光線を得る方法を紹介します。

ではでは今回はこんな感じで。

よかったらシェアしてね!
  • URLをコピーしました!

コメント

コメントする