レンズの問題を中学生に聞かれたのですが、すぐに答えらませんでした。
そこでプログラムでグラフを描きながら考察したことのまとめです。
問題
物体とスクリーンの間に凸レンズを置いて、スクリーンに像を写すことを考えます。
ここで、レンズを物体側からスクリーン側に移動させていきます。このとき、像が焦点を結ぶレンズの位置は何か所あるでしょうか?
という問題です。ここでレンズの焦点距離は10cm、物体とスクリーン間の距離は60cmとします(説明しやすいように、実際の問題から少し改変しています)。
解
レンズの位置をX、焦点が合う位置をYとします。
このXとYの関係をグラフ化すると以下のようになります(レンズの公式は使わずに、直線の交わる点としてYを求めました)。
面白いことに、Xが20までは、Yは減少しますが、Xが20を超えると増加するという関係になります。
X=20というのは、レンズの焦点距離の2倍のときです。この時にスクリーンまでの距離が最小になるのです。
見方を変えて、スクリーンが60cm の位置に固定されているとすれば(オレンジの横線)、関数がオレンジの横線と交わるのが2か所なので、
この2か所で焦点が合うといえます。
プログラム
Jupyter notebook で作成しました。
まず、計算や描画に使用する関数を作ります。
def draw_line_2p(p1, p2, x_min=None, x_max=None, col='b', lw=2, isShow=True): ''' 2点 p1, p2を結ぶ直線を、x_min, x_maxの範囲で描く 傾きaと切片bを出力 isShow = True とすると描画する ''' if x_min is None: x_min = p1[0] if x_max is None: x_max = p2[0] if p1[0] == p2[0]: # 垂直の場合 plt.plot([p1[0], p1[0]], [p1[1], p2[1]], color=col, lw=lw) return None, None a = (p2[1] - p1[1]) / (p2[0] - p1[0]) b = p1[1] - a * p1[0] y0 = a * x_min + b y1 = a * x_max + b if isShow: plt.plot([x_min, x_max], [y0, y1], color=col, lw=lw) return a, b
次に二つの直線の交点を求める関数を作ります。
def intersection(p1, p2, q1, q2): ''' p1, p2 の2点を通る直線と、q1, q2 を通る直線の交点を求める ''' p_a, p_b = draw_line_2p(p1, p2, isShow=False) q_a, q_b = draw_line_2p(q1, q2, isShow=False) if p_a == q_a: return None, None x = - (p_b - q_b) / (p_a - q_a) y = p_a * x + p_b return x, y
こちらがメイン。
物体の高さ(light_H)、レンズの位置(lens_pos)、焦点距離(lens_F)を与えると、
スクリーンの位置を出力し、その時の位置関係を図示するプログラムです。
def get_screen_pos(light_H=5, lens_pos=20, lens_F=10, isShow=True): ''' 被写体位置を(0, light_H) としたとき lens_pos: レンズ位置 lens_F: レンズの焦点距離 から、 screen の位置(x, y)を出力 ''' # 物の座標 light_base = [0, 0] # 光源の根本 light_top = [0, light_H] # 光源の頭 light_top_on_lens = [lens_pos, light_H] # 光源の頭がレンズへ投射する位置 lens_low = [lens_pos, -light_H] # レンズの下側 lens_up = [lens_pos, light_H] # レンズの下側 lens_focus = [lens_pos + lens_F, 0] # レンズの焦点のある座標 lens_center = [lens_pos, 0] # レンズの位置 # 焦点位置 x, y = intersection(light_top_on_lens, lens_focus, light_top, lens_center) # 物の描画 if isShow: x_max = 100 # 描画する範囲 if x is not None: x_max = x draw_line_2p(light_base, light_top, col='r', lw=5) # 物体 draw_line_2p(lens_low, lens_up, col='b', lw=5) # レンズ plt.plot(lens_focus[0], lens_focus[1], marker='o', color='b', markersize=10) # レンズ焦点 # 焦点を通る光の経路 draw_line_2p(light_top, light_top_on_lens, col='c') draw_line_2p(light_top_on_lens, lens_focus, x_max=x_max, col='c') # レンズの中心を通る経路 draw_line_2p(light_top, lens_center, x_min=0, x_max=x_max, col='m') if x > 0: # 像 plt.plot([x, x], [0, y], lw=5, color=(1, .8, .8)) # 光源の頭が映る位置 plt.plot(x, y, marker='x', markersize=10, color='r') return x, y # test x, y = get_screen_pos(light_H=5, lens_pos=20, lens_F=10, isShow=True) print(f'焦点の合う距離:{x:.2f} cm') plt.grid() plt.show()
これを使って、XとYの関係をグラフにするのが次のコード。
xs = [] ys = [] lens_poss = np.linspace(11, 60, 100) # 焦点距離10と同じ位置10は無限になるので11から for lens_pos in lens_poss: x, y = get_screen_pos(light_H=5, lens_pos=lens_pos, lens_F=10, isShow=False) xs.append(x) ys.append(y) plt.figure(figsize=(10, 5)) plt.plot(lens_poss, xs, label='rens position') plt.plot([10, 60], [60, 60], color='orange', label='screen 60 cm') plt.xlabel('x (lens_position)') plt.ylabel('y (screen_position)') plt.xticks(range(10, 61, 5)) plt.legend() plt.grid() plt.show()
以下、レンズの位置を変えたショット。
レンズの焦点が10cm なので、レンズの位置が10cmのときは、焦点の合う距離は無限遠方。下の図は、そこからレンズの位置を右に1cm動かしたもの。
レンズを右に動かすと焦点の合うスクリーンの位置は近づいてくる。レンズを12.7cmの地点まで動かすと、スクリーンの位置はだいたい60cmとなる。このとき、像の大きさは本物よりも大きい。
レンズの位置を焦点距離の2倍の位置まで(20cm)動かしたときが、最もスクリーンの位置が近くなり40cm。像の大きさは本物の大きさと同じになる。
さらにレンズの位置を右に動かしていくと、焦点の合うスクリーンの位置は右に離れていく。
レンズの位置が47cmまで動くと、スクリーンの位置は60cmくらいとなる。この時の像は本物よりもだいぶ小さい。
つまり、問題の答えは、「2か所」ということになります。
曲線の式
YとXの関係式を求めます。
物体からレンズまでの距離をa、レンズからスクリーンまでの距離をb とすると以下の公式がなりたちます。
[math]
\frac{1}{a} + \frac{1}{b} = \frac{1}{F}
[/math]
a=X, b=Y-X として、Y=の形に整えると以下の式が得られます。
[math]
Y = \frac{-X^2}{F-X}
[/math]
ではグラフを描きましょう。
def func(x, F=10): return -x**2/(F-x) x = np.linspace(11, 60, 100) y = func(x) plt.figure(figsize=(10, 5)) plt.plot(x, y) plt.grid() plt.xlabel('x (lens_position)') plt.ylabel('y (screen_position)') plt.xticks(range(10, 61, 5)) plt.show()
先ほどと同じグラフが得られました。
コメントを残す