漢字プリント 数学プリント
問題文
座標平面上に3点 $\mathrm{O}(0,0),\mathrm{A}(4,2),\mathrm{B}(6,0)$ を考える。平面上の直線 $\ell$ に関して点 $\mathrm{A}$ と対称な点が線分 $\mathrm{OB}$ 上にあるとき、直線 $\ell$ をピッタリ直線と呼ぶことにする。
  1. 点 $\mathrm{P}(p,q)$ を通るピッタリ直線 $\ell$ があるとし、 $\ell$ に関して $\mathrm{A}$ と対称な点を $\mathrm{A'}(t,0)\,(0 \leqq t \leqq 6)$ とするとき、 $p,q,t$ の間に成り立つ関係式を求めよ。
  2. ピッタリ直線が2本通る点 $\mathrm{P}(p,q)$ の存在範囲を求め、それを図示せよ。図には三角形 $\mathrm{OAB}$ も書いておくこと。
  3. 点 $\mathrm{P}(p,q)$ を通る2本のピッタリ直線が直交するような点 $\mathrm{P}(p,q)$ の存在範囲を求め、それを図示せよ。
(2006 名古屋大学 理系第3問)
  1. $q=\frac{t-4}{2}\,p-\frac{t^2-20}{4}$
  2. 略(動画を参照)
  3. 略(動画を参照)
※ この答えは学校側が公表したものではありません。個人が作成した非公式の答えです。
コード
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as ani
import matplotlib.patches as patches

#紙の準備
left   = -3
right  =  9
bottom = -1
top    =  3
fig = plt.figure()
fig.subplots_adjust(left=0,right=1)
fig.suptitle("2006名古屋大数学 理系第3問",
             color="0.5",ha="right",x=0.96,y=0.96)
ax = fig.add_subplot(111)
ax.set_xlim(left,right)
ax.set_ylim(bottom,top)
ax.set_aspect("equal")
ax.axis("off")

#点とか図形とかを準備
a  = np.array([4,2])
b  = np.array([6,0])
OAB = patches.Polygon([(0,0),a,b],fill=False,ec="0.4",lw=1.5)
x  = np.linspace(0,6,61)
y1 = np.maximum(-2*x+5,x-4)
y2 = 1/4*x**2-2*x+5
area = ax.fill_between(x,y1,y2,fc="none",ec="c",lw=3,hatch="//",
                       zorder=10,clip_on=False,alpha=0.0)
x = np.array([left,right])

#注釈を準備
arrow_dict = dict(arrowstyle="-|>",color="0.3",relpos=(.0,.2))
at1 = ax.annotate("ピッタリ直線",xy=(3.5,-2),xytext =(4.5,-1.5),
                  color="0.3",annotation_clip=False,arrowprops=arrow_dict)
arrow_dict = dict(arrowstyle="-|>",color="0.3",relpos=(.0,.5),alpha=0,
                  connectionstyle="angle,angleA=0,angleB=60")
at2 = ax.annotate("ピッタリ直線が\n2回通る範囲!",xy=(2,2),xytext =(3.2,2.5),alpha=0,
                  color="0.3",annotation_clip=False,arrowprops=arrow_dict)
arrow_dict = dict(arrowstyle="-|>",color="0.3",relpos=(1,.5),alpha=0,
                  connectionstyle="angle,angleA=0,angleB=60")
at3 = ax.annotate("直交する\nピッタリ直線\nの交点の軌跡",xy=(3.2,0),xytext =(0,-1.2),alpha=0,
                  color="0.3",annotation_clip=False,arrowprops=arrow_dict)

#動かすものを準備
u1,u2   = ax.plot([],[],[],[],c="0.6",lw=1)
l1,l2   = ax.plot([],[],[],[],c="c",clip_on=False)
T1,T2,A = ax.plot([],[],[],[],4,2,c="lightslategrey",marker="o")
s = ax.plot([],[],[],[],[],[],[],[],
            [],[],[],[],[],[],[],[],c="0.6",lw=0.5)
K,= ax.plot(2.5,0,c="forestgreen",marker="o",zorder=10,visible=False)
raxy  = [a/2,(2.5,0),(4.5,1),a]
ang   = np.rad2deg(np.arctan(-2))
raang = [ang,ang+90,ang+180,ang-90]
ra = [patches.Rectangle(raxy[i],0.15,0.15,angle=raang[i],
                        fill=False,ec="0.6",visible=False)\
      for i in range(4)]
for obj in [OAB]+ra:
    ax.add_patch(obj)

#グループ分け
group1 = [T1,l1,u1]+s[:4]
group2 = [T2,l2,u2]+s[4:]

#コメントたち
phrases = []
phrases.append("""
突如
""")
phrases.append("""
名大数学に現れた
""")
phrases.append("""
“ ピッタリ直線 ”
""")
phrases.append("""
???
""")
phrases.append("""
2本の
“ ピッタリ直線 ”
が直交するのは
""")
phrases.append("""
結局
ただの「垂直二等分線」でした
""")
phrases.append("""
以上!
""")
prs = fig.text(0.5,0.5,phrases[0],c="w",ha="center",va="center",
               fontsize=20,linespacing=2.5,fontfamily="Meiryo",
               bbox=dict(color="black",pad=300))

#同じ長さを表す記号
def set_s(s,xy):
    r = 0.07
    x,y = xy
    theta = np.arctan(-(x-4)/(y-2))
    sx = [x-r*np.cos(theta),x+r*np.cos(theta)]
    sy = [y-r*np.sin(theta),y+r*np.sin(theta)]
    s.set_data(sx,sy)
 
#ピッタリ直線を動かす関数
def moving(k,group):
    t = np.array([k,0])
    group[0].set_data(k,0)
    
    m = (t+a)/2
    slope = (k-4)/2
    y = slope*(x-m[0])+m[1]
    group[1].set_data(x,y)
    group[2].set_data([k,4],[0,2])
    
    r = (np.linalg.norm(m-a)/2+0.04)/np.linalg.norm(m-a)
    set_s(group[3],r*m+(1-r)*a)
    set_s(group[4],r*a+(1-r)*m)
    set_s(group[5],r*m+(1-r)*t)
    set_s(group[6],r*t+(1-r)*m)
    
    return m,slope,y

#お気に入りのイージング関数
def easing(x):
    if x<0.0:
        return 0
    elif x<0.5:
        return 2*x**2
    elif x<1.0:
        return 1-(-2*x+2)**2/2
    else:
        return 1

#シーンその1
def part1(i):
    k = 6*i/199
    m,slope,y = moving(k,group1)
    ax.plot(x,y,c="lightgreen",alpha=0.1,clip_on=False,zorder=-10)
    
    ang = np.rad2deg(np.arctan(slope))
    ra[0].angle = ang
    ra[0].set_xy(m)
    
    atx = m[0]-3/slope
    at1.xy = (atx,-2)
    at1.xyann = (atx+1,-1.5)
    
    if i==100:
        at1.set_visible(False)
    elif i==180:
        for obj in s[:4]+ra[:1]:
            obj.set_visible(False)

#シーンその2
def part2(i):
    k = i/49
    alpha = easing(k)
    for obj in [area,at2,at2.arrow_patch]:
        obj.set_alpha(alpha)
    for obj in [A]+group1[:3]:
        obj.set_alpha(1-alpha)

#シーンその3
def part3(i):
    k  = 2.5+1.5*i/99
    K.set_data(k,0)
    ax.plot(k,0,"co")
    
    k1 = k-np.sqrt(k**2-8*k+20)
    k2 = k+np.sqrt(k**2-8*k+20)
    m1,slope,_ = moving(k1,group1)
    m2,_,_     = moving(k2,group2)
    
    ang = np.rad2deg(np.arctan(slope))
    ra[0].angle = ang
    ra[0].set_xy(m1)
    ra[1].angle = ang+90
    ra[1].set_xy((k,0))
    ra[2].angle = ang+180
    ra[2].set_xy(m2)
    ra[3].angle = ang-90
    ra[3].set_xy(a)

#シーンその4
def part4(i):
    k = i/49
    alpha = easing(k)
    for obj in [at3,at3.arrow_patch]:
        obj.set_alpha(alpha)
    for obj in [A,K]+group1+group2+ra:
        obj.set_alpha(1-alpha)

#上演
def update(i):
    if i<100:
        pass
    elif i<300:
        part1(i-100)
    elif i<400:
        part2(i-300)
    elif i<450:
        pass
    elif i<550:
        part3(i-450)
    elif i<650:
        part4(i-550)
    else:
        pass
    
    if i==10:
        prs.set_text(phrases[1])
    elif i==30:
        prs.set_text(phrases[2])
    elif i==70:
        prs.set_text(phrases[3])
    elif i==90:
        moving(0,group1)
        ra[0].set_visible(True)
        prs.set_visible(False)
    elif i==400:
        prs.set_text(phrases[4])
        prs.set_visible(True)
    elif i==440:
        moving(0,group1)
        moving(5,group2)
        ra[0].set_xy(a/2)
        ra[0].angle = ang
        for obj in [area,at2,at2.arrow_patch]:
            obj.set_visible(False)
        for obj in [A]+group1[:3]:
            obj.set_alpha(1.0)
        for obj in [K]+s[:4]+ra:
            obj.set_visible(True)
        prs.set_visible(False)
    elif i==650:
        prs.set_text(phrases[5])
        prs.set_visible(True)
    elif i==690:
        prs.set_text(phrases[6])

mov = ani.FuncAnimation(fig,update,700,interval=100)
plt.show()
解説になっているのか?甚だギモンな動画
「高校数学のエアポケット」に戻る