타원과 관련한 아름다운 사실이 있어서 소개를 해 볼까 합니다.
한 점에서 타원에 그은 두 접선이 수직으로 만난다면, 그 점이 이루는 자취는 뭘까?
타원의 방정식을
x2a2+y2b2=1
이라 하고 우리가 관심이 있는 점을 (X,Y)라 합시다. 이 점을 지나는 직선의 방정식을
y=m(x−X)+Y
라 쓸 수 있죠.
식(2)의 직선의 방정식이 식(1)의 타원에 접하길 기대하는 거죠. 따라서
x2a2+(m(x−X)+Y)2b2=1
이 중근 즉, 판별식이 0이어야 합니다.
식(3)을 정리하면
b2x2+a2(mx+(Y−mX))2=a2b2
이고, x에 대한 식으로 깔끔(?) 하게 정리하면
(b2+a2m2)x2+2m(Y−mX)a2x+a2(Y−mX)2−a2b2=0
입니다. 따라서
D/4=m2a4(Y−mX)2−(b2+a2m2)[a2(Y−mX)2−a2b2]=0
이고 이것을 m에 대한 식으로 정리 하면
(a2−X2)m2+2XYm+(b2−Y2)=0
이 나옵니다.
따라서, 식(4)의 m이 두 근 m1,m2를 가져야 하고 , 이 두 근의 곱 m1m2=−1이 나와야 합니다.
(4)의 판별식은
D/4=(XY)2−(a2−X2)(b2−Y2)>0이어야 하고, 이것을 정리하면
X2a2+Y2b2>1
입니다. 즉, 점 (X,Y)는 타원 바깥의 점이어야 한다는 얘기죠. 그건 자명합니다. 타원 안에서는 타원에 접선을 그릴 수 없기 때문이죠.
이제 m1m2=−1을 이용하면 근과 계수와 이 관계에 의해서
−1=m1m2=b2−Y2a2−X2
이고
X2+Y2=a2+b2
이 됩니다. 즉 중심이 타원의 중심과 같고, 반지름이 √a2+b2인 원이 되는 것입니다.
python 차트 연습도 할 겸 위의 문제를 그려 보겠습니다.
import math
import numpy as np
import matplotlib.pyplot as plt
def plot_ellipse():
a = 2
b = 1
theta = np.linspace(0, 2 * np.pi, 100)
x = a * np.cos(theta)
y = b * np.sin(theta)
plt.plot(x, y, color='gray', linestyle='-')
radius = np.sqrt(a**2+b**2)
x_line = np.linspace(-10,10,1000)
res_x =[]
res_y=[]
for t in theta:
cir_x = radius*np.cos(t)
cir_y = radius*np.sin(t)
res_x.append(cir_x)
res_y.append(cir_y)
coeff = 2*cir_x*cir_y/(a**2 - cir_x**2)
slope1= (-1*coeff + np.sqrt(coeff**2+4))/2
slope2 = (-1 * coeff - np.sqrt(coeff ** 2 + 4)) / 2
plt.xlim([-3, 3])
plt.ylim([-3, 3])
plt.plot(x, y, color='gray', linestyle='-')
plt.plot(cir_x,cir_y,'b', marker ='o')
plt.plot(res_x, res_y, 'b')
plt.plot(x_line, slope1*(x_line-cir_x)+cir_y,'r')
plt.plot(x_line, slope2 * (x_line - cir_x) + cir_y, 'r')
plt.pause(0.05)
plt.cla()
plt.show()
if __name__ == '__main__':
plot_ellipse()
code를 간단히 볼까요?
a = 2 #장축을 a
b = 1 #단축을 b
theta = np.linspace(0, 2 * np.pi, 100) #theta을 0에서 2π까지 돌리면서
x = a * np.cos(theta) #타원의 x좌표를 설정
y = b * np.sin(theta) #타원의 y좌표를 설정
plt.plot(x, y, color='gray', linestyle='-') #타원위의 점을 plotting한다.
식(1)의 타원의 방정식은
x=acosθ,y=bsinθ , 0≤θ≤2π
로 매개변수 방정식으로 쓸 수 있습니다.
radius = np.sqrt(a**2+b**2) #문제의 결과는 반지름이 sqrt(a^2+b^2)인 원이라 반지름을 설정
x_line = np.linspace(-10,10,1000) #접선을 그리기 위해 x좌표 설정
res_x =[] #문제의 결과인 원의 x좌표를 저장할 list
res_y=[] #문제의 결과인 원의 y좌표를 저장할 list
for t in theta:
cir_x = radius*np.cos(t) #원의 x좌표
cir_y = radius*np.sin(t) #원의 y좌표
res_x.append(cir_x) #원의 x좌표를 res_x에 추가
res_y.append(cir_y) #원의 y좌표를 res_y에 추가
coeff = 2*cir_x*cir_y/(a**2 - cir_x**2) #아래 설명 참조
slope1= (-1*coeff + np.sqrt(coeff**2+4))/2 #아래 설명 참조
slope2 = (-1 * coeff - np.sqrt(coeff ** 2 + 4)) / 2 #아래 설명 참조
plt.xlim([-3, 3]) #그래프의 x좌표를 -3과 3사이로 설정
plt.ylim([-3, 3]) #그래프의 y조표를 -3과 3사이로 설정
plt.plot(x, y, color='gray', linestyle='-') #타원을 그림
plt.plot(cir_x,cir_y,'b', marker ='o') #원위의 점을 o라는 marker를 사용하여 그림
plt.plot(res_x, res_y, 'b') #시간이 지나며 갱신되는 원의 자취를 그림
plt.plot(x_line, slope1*(x_line-cir_x)+cir_y,'r') #접선1을 그림
plt.plot(x_line, slope2 * (x_line - cir_x) + cir_y, 'r') #접선2를 그림
plt.pause(0.05) #0.05초만큼의 정지화면을 주어 그래프의 animation을 효과를 줌
plt.cla() #화면 지우는 함수
수식(4)를 좀 더 간략히 쓰면
m2+2XYa2−X2m−1=0
이 됩니다.
c=2XYa2−X2 라고 두면, m2+cm−1=0의 두 근은
m1,m2=−c±√c2+42
이므로 위의 code의 coeff, slope1, slope2를 설명할 수 있습니다.
결과는 아래와 같습니다. scale 때문에 원이 아닌 것 같이 보이네요.
댓글