Turtle库绘制望远镜和显微镜成像系统原理图
(一)望远镜成像系统(两片凸透镜实现)
1.作用:利用望远镜能够看清远处的物体;
2.组成:由两组凸透镜组成。靠进物体的叫物镜,焦距较长;靠近眼睛的目镜,焦距较短,物镜的第二焦点与目镜的第一焦点重合;
3.原理:物镜的作用是使远处的物体在焦点附近成实像,目镜的作用相当于一个放大镜,用来把像放大
由于不同的透镜材质不同,折射率不同(如果要考虑这些的话,会有很多参数要设置),所以下面的透镜是随便画的,所以,下面透镜圆心角也是随便设的,合理即可。实现得效果大致如下
下面是为了方便自定义绘图,写了一些自定义函数
下面这个函数用来计算两向量之间的夹角,这个函数有两个参数,v1,v2它们是列表,分别存放在两个向量的四个坐标的位置信息位置。例如:v1=[x1,y1,x2,y2](第一个向量的两个坐标),v3=[x3,y3,x4,y4](第二个向量的两个坐标)。经函数计算后,返回的结果是两个向量的夹角。
这个函数在这个任务里的作用是,计算圆心角。
PS:这里是向量,因为向量有方向,有固定的夹角,而两条直线的夹角由两个。所以,这里是向量
def yuan_xin_jiao(v1, v2):#计算两向量夹角的函数
dx1 = v1[2] - v1[0]
dy1 = v1[3] - v1[1]
dx2 = v2[2] - v2[0]
dy2 = v2[3] - v2[1]
angle1 = math.atan2(dy1, dx1)
angle1 = int(angle1 * 180/math.pi)
angle2 = math.atan2(dy2, dx2)
angle2 = int(angle2 * 180/math.pi)
if angle1*angle2 >= 0:
included_angle = abs(angle1-angle2)
else:
included_angle = abs(angle1) + abs(angle2)
if included_angle > 180:
included_angle = 360 - included_angle
return included_angle
下面这个是,标注图像上字母的函数,a,b是坐标位置,c是要标注的内容
def words(a,b,c):#标注字母的函数
penup()
goto(a,b)
pendown()
write(c,font=('Arial',7,'normal'))
这个函数,与上面的函数没啥区别,主要是字体大小不同
def character(a,b,c):#写汉字的函数
penup()
goto(a,b)
pendown()
write(c,font=('Arial',15,'normal'))
下面这个是计算两点之间距离的函数,x1,y1,x2,y2,分别是两点的横纵坐标
def distence(x1,y1,x2,y2):#计算两点之间距离的函数
p1 = np.array([x1,y1])
p2 = np.array([x2,y2])
p3 = p2 - p1
p4 = math.hypot(p3[0], p3[1])
return p4
下面是画线前准备的函数,a,b跳转到指定位置
def draw(a,b):#画线前的准备函数
penup()
goto(a,b)
pendown()
下面这个是计算两直线之间角度的函数line1,line2也是列表,分别存放两条直线的四个坐标位置,如:line1=[x1,y1,x2,y2](格式),返回在是焦点的坐标
def point(line1, line2): # 计算直线交点函数
x1 = line1[0] # 取四点坐标
y1 = line1[1]
x2 = line1[2]
y2 = line1[3]
x3 = line2[0]
y3 = line2[1]
x4 = line2[2]
y4 = line2[3]
k1 = (y2 - y1) * 1.0 / (x2 - x1) # 计算k1,由于点均为整数,需要进行浮点数转化
b1 = y1 * 1.0 - x1 * k1 * 1.0 # 整型转浮点型是关键
if (x4 - x3) == 0: # L2直线斜率不存在操作
k2 = None
b2 = 0
else:
k2 = (y4 - y3) * 1.0 / (x4 - x3) # 斜率存在操作
b2 = y3 * 1.0 - x3 * k2 * 1.0
if k2 == None:
x = x3
else:
x = (b2 - b1) * 1.0 / (k1 - k2)
y = k1 * x * 1.0 + b1 * 1.0
return x, y
代码如下:
from turtle import *
import math
import numpy as np
def yuan_xin_jiao(v1, v2):#计算两向量夹角的函数
dx1 = v1[2] - v1[0]
dy1 = v1[3] - v1[1]
dx2 = v2[2] - v2[0]
dy2 = v2[3] - v2[1]
angle1 = math.atan2(dy1, dx1)
angle1 = int(angle1 * 180/math.pi)
angle2 = math.atan2(dy2, dx2)
angle2 = int(angle2 * 180/math.pi)
if angle1*angle2 >= 0:
included_angle = abs(angle1-angle2)
else:
included_angle = abs(angle1) + abs(angle2)
if included_angle > 180:
included_angle = 360 - included_angle
return included_angle
def words(a,b,c):#标注字母的函数
penup()
goto(a,b)
pendown()
write(c,font=('Arial',7,'normal'))
def character(a,b,c):#写汉字的函数
penup()
goto(a,b)
pendown()
write(c,font=('Arial',15,'normal'))
def distence(x1,y1,x2,y2):#计算两点之间距离的函数
p1 = np.array([x1,y1])
p2 = np.array([x2,y2])
p3 = p2 - p1
p4 = math.hypot(p3[0], p3[1])
return p4
def draw(a,b):#画线前的准备函数
penup()
goto(a,b)
pendown()
def point(line1, line2): # 计算直线交点函数
x1 = line1[0] # 取四点坐标
y1 = line1[1]
x2 = line1[2]
y2 = line1[3]
x3 = line2[0]
y3 = line2[1]
x4 = line2[2]
y4 = line2[3]
k1 = (y2 - y1) * 1.0 / (x2 - x1) # 计算k1,由于点均为整数,需要进行浮点数转化
b1 = y1 * 1.0 - x1 * k1 * 1.0 # 整型转浮点型是关键
if (x4 - x3) == 0: # L2直线斜率不存在操作
k2 = None
b2 = 0
else:
k2 = (y4 - y3) * 1.0 / (x4 - x3) # 斜率存在操作
b2 = y3 * 1.0 - x3 * k2 * 1.0
if k2 == None:
x = x3
else:
x = (b2 - b1) * 1.0 / (k1 - k2)
y = k1 * x * 1.0 + b1 * 1.0
return x, y
f1= eval(input("物镜的焦距f1:"))#这里设置为90
f2= eval(input("目镜的焦距f2:"))#这里设置为30
O1= eval(input("物镜的主点位置O1:"))#这里设置为(-80,0)
O2= eval(input("目镜的主点位置O2:"))#这里设置为(40,0)
H1= eval(input("物镜的高度H1:"))#这里设置为50
H2= eval(input("目镜的高度H2:"))#这里设置为30
Y1= eval(input("物镜的圆心位置Y1:"))#这里设置为(0,0)
Y2= eval(input("目镜的圆心位置Y2:"))#这里设置为(0,0)
Y= eval(input("平行光入射高度Y:"))#这里设置为40
X= eval(input("绘制平行光的起始位置X:"))#这里设置为-180
character(-50,251,"望远镜成像系统")
r1=distence(Y1,0,O1,H1)#物镜半径
Y1A=[Y1,0,O1,H1]#F2,A两点的横纵坐标
Y1B=[Y1,0,O1,-H1]
yuan_xin_jiao1=yuan_xin_jiao(Y1A,Y1B)#计算圆心角
r2=distence(Y2,0,O2,H2)#目镜半径
Y2C=[Y2,0,O2,H2]#Y2,C两点的横纵坐标
Y2D=[Y2,0,O2,-H2]
yuan_xin_jiao2=yuan_xin_jiao(Y2C,Y2D)#计算圆心角
draw(0,0)#画光轴,自行合理设置
fd(220)
fd(-440)
draw(O1,H1)#画物镜
seth(-90-yuan_xin_jiao1/2)
circle(r1,yuan_xin_jiao1)
seth(90-yuan_xin_jiao1/2)
circle(r1,yuan_xin_jiao1)
draw(O1,0)#画物镜的主平面
seth(-90)
fd(H1)
fd(-H1*2)
draw(O2,H2)#画目镜
seth(-90-yuan_xin_jiao2/2)
circle(r2,yuan_xin_jiao2)
seth(90-yuan_xin_jiao2/2)
circle(r2,yuan_xin_jiao2)
draw(O2,0)#画目镜的主平面
seth(-90)
fd(H2)
fd(-H2*2)
pencolor('blue')#设定光线的颜色,和字体的颜色
draw(X,Y)
seth(0)
fd(O1-X)
JF1=[O1,Y,O1+f1,0]#E,F1两点的横纵坐标
CD=[O2,H2,O2,-H2]
x1,y1=point(JF1, CD)#计算两直线的交点,Q
goto(x1,y1)
fd(100)#自行合理设置
draw(X,-Y)
fd(O1-X)
KF1=[O1,-Y,O1+f1,0]#E,F1两点的横纵坐标
CD=[O2,H2,O2,-H2]
x2,y2=point(KF1, CD)#计算两直线的交点,P
goto(x2,y2)
fd(100)#自行合理设置
words(O1,0,'O1')
words(O2,0,'O2')
words(O1,H1,'A')
words(O1,-H1-15,'B')#相对于真实的位置,这里向下偏移15个单位,主要是为了美观,下面的代码中也有类似的操作,就不一一注释了
words(O2,H2,'C')
words(O2,-H2-15,'D')
words(O1,Y-15,'J')
words(O1,-Y,'K')
words(x2,y2,'P')
words(x1,y1,'Q')
words(O1-f1,0,'-F1')
words(O1+f1,0+15,'F1')
words(O2-f2,0-15,'-F2')
words(O2+f2,0,'F2')
character(O1,H1+30,"物镜")
character(O2,H2+30,"目镜")
hideturtle()
done()
效果如下
(二)显微镜成像系统(两片凸透镜实现)
1.作用:用来观察细微物体或物体细微部。
2。原理:根据凸透镜的成像原理 ,要经过凸透镜的两次成像,先用一个接近物体的凸透镜使物体成-放大的实像,然后再用另一个接近眼睛的凸透镜把这个实像再次放大,就能看清很微小的物体。
3.组成:由一个透镜或者几个透镜的组合构成,离物体近的透镜叫物镜,其焦距较短;离眼睛近的透镜叫目镜,其焦距比物镜稍大,两镜间的距离可以调节。
实现大致效果如下:
下面这个函数是用来计算函数的倾斜角度的,用上面的计算向量夹角的函数当然也可以,但这里配合turtle.seth函数使用更方便
def angle(x1,y1,x2,y2):#计算直线的倾斜角度角度
oue_put = math.atan((y1 - y2) / (x1-x2))
oue_put = math.degrees(oue_put)
return oue_put
看看代码吧:
from turtle import *
import math
import numpy as np
def angle(x1,y1,x2,y2):#计算直线的倾斜角度角度
oue_put = math.atan((y1 - y2) / (x1-x2))
oue_put = math.degrees(oue_put)
return oue_put
def yuan_xin_jiao(v1, v2):#计算两向量夹角的函数
dx1 = v1[2] - v1[0]
dy1 = v1[3] - v1[1]
dx2 = v2[2] - v2[0]
dy2 = v2[3] - v2[1]
angle1 = math.atan2(dy1, dx1)
angle1 = int(angle1 * 180/math.pi)
angle2 = math.atan2(dy2, dx2)
angle2 = int(angle2 * 180/math.pi)
if angle1*angle2 >= 0:
included_angle = abs(angle1-angle2)
else:
included_angle = abs(angle1) + abs(angle2)
if included_angle > 180:
included_angle = 360 - included_angle
return included_angle
def words(a,b,c):#标注字母的函数
penup()
goto(a,b)
pendown()
write(c,font=('Arial',7,'normal'))
def character(a,b,c):#写汉字的函数
penup()
goto(a,b)
pendown()
write(c,font=('Arial',15,'normal'))
def distence(x1,y1,x2,y2):#计算两点之间距离的函数
p1 = np.array([x1,y1])
p2 = np.array([x2,y2])
p3 = p2 - p1
p4 = math.hypot(p3[0], p3[1])
return p4
def draw(a,b):#画线前的准备函数
penup()
goto(a,b)
pendown()
def point(line1, line2): # 计算直线交点函数
x1 = line1[0] # 取四点坐标
y1 = line1[1]
x2 = line1[2]
y2 = line1[3]
x3 = line2[0]
y3 = line2[1]
x4 = line2[2]
y4 = line2[3]
k1 = (y2 - y1) * 1.0 / (x2 - x1) # 计算k1,由于点均为整数,需要进行浮点数转化
b1 = y1 * 1.0 - x1 * k1 * 1.0 # 整型转浮点型是关键
if (x4 - x3) == 0: # L2直线斜率不存在操作
k2 = None
b2 = 0
else:
k2 = (y4 - y3) * 1.0 / (x4 - x3) # 斜率存在操作
b2 = y3 * 1.0 - x3 * k2 * 1.0
if k2 == None:
x = x3
else:
x = (b2 - b1) * 1.0 / (k1 - k2)
y = k1 * x * 1.0 + b1 * 1.0
return x, y
L= eval(input("主光轴的长度L:"))#这里设置为300
f1= eval(input("物镜的焦距f1:"))#这里设置为40
f2= eval(input("目镜的焦距f2:"))#这里设置为100
O1= eval(input("物镜的主点位置O1:"))#这里设置为(-80,0)
O2= eval(input("目镜的主点位置O2:"))#这里设置为(100,0)
H1= eval(input("物镜的高度H1:"))#这里设置为50
H2= eval(input("目镜的高距H2:"))#这里设置为100
Y1= eval(input("物镜的圆心位置Y1:"))#这里设置为(0,0)
Y2= eval(input("目镜的圆心位置Y2:"))#这里设置为(-20,0)
X= eval(input("物体的位置X:"))#这里设置为(-140,0)
Y= eval(input("物体的高度Y:"))#这里设置为40
character(-50,251,"显微镜成像系统")
r1=distence(Y1,0,O1,H1)#物镜半径
F1A=[Y1,0,O1,H1]#-F1,A两点的横纵坐标
F1B=[Y1,0,O1,-H1]#-F1,B两点的横纵坐标
yuan_xin_jiao1=yuan_xin_jiao(F1A,F1B)#计算圆心角
r2=distence(Y2,0,O2,H2)#目镜半径
F2C=[Y2,0,O2,H2]#-F2,C两点的横纵坐标
F2D=[Y2,0,O2,-H2]##-F2,D两点的横纵坐标
yuan_xin_jiao2=yuan_xin_jiao(F2C,F2D)#计算圆心角
draw(0,0)#画光轴
fd(L)
fd(-2*L)
draw(O1,H1)#画物镜
seth(-90-yuan_xin_jiao1/2)
circle(r1,yuan_xin_jiao1)
seth(90-yuan_xin_jiao1/2)
circle(r1,yuan_xin_jiao1)
draw(O1,0)#画物镜的主平面
seth(-90)
fd(H1)
fd(-H1*2)
draw(O2,H2)#画目镜
seth(-90-yuan_xin_jiao2/2)
circle(r2,yuan_xin_jiao2)
seth(90-yuan_xin_jiao2/2)
circle(r2,yuan_xin_jiao2)
draw(O2,0)#画目镜的主平面
seth(-90)
fd(H2)
fd(-H2*2)
draw(X,0)#画物的位置
seth(90)
fd(Y)
pencolor('blue')#设定光线的颜色,和字体的颜色
draw(X,Y)#跳转到Y点,画直线YA
seth(0)
fd(O1-X)
YO1=[X,Y,O1,0]#Y,O1两点的横纵坐标
EF1=[O1,Y,O1+f1,0]
x1,y1=point(YO1, EF1)#计算两直线的交点
print(x1,y1)
goto(x1,y1)#跳转到G点,画直线GJ
distence3=distence(x1,y1,O2,y1)#计算GJ的距离
fd(distence3)
draw(X,Y)#跳转到Y点,画直线YG
goto(x1,y1)
GO2=[x1,y1,O2,0]#G,O2两点的横纵坐标
JF2=[O2,y1,O2+f2,0]
x2,y2=point(GO2, JF2)#计算两直线的交点
draw(x2,y2)#跳转到P点
angle1=angle(O2,0,x1,y1)#计算O2G的倾斜角度
seth(angle1)
distence1=distence(x1,y1,x2,y2)#计算GP的距离
for i in range (10):#这里是为了画倾斜的虚线
fd(distence1/20)
penup()
fd(distence1/20)
pendown()
fd(200)#自行合理设置
draw(x2,y2)#跳转到P点
angle2=angle(O2,y1,x2,y2)##计算JP的倾斜角度
seth(angle2)
distence2=distence(O2,y1,x2,y2)#计算JP的距离
for i in range (10):#这里是为了画倾斜的虚线
fd(distence2/20)
penup()
fd(distence2/20)
pendown()
fd(300)#自行合理设置
draw(x2,y2)#跳转到P点
for i in range (10):#这里是为了P点到主光轴的的虚线
seth(-90)
fd(y2/20)
penup()
fd(y2/20)
pendown()
#下面X点,B点,D点,G点,P点,J点的坐标皆偏离主光轴-15个单位,为了美观
words(X,-15,'X')
words(X,Y,'Y')
words(O1-f1,0,'F1')#F1左焦点
words(O1,0,'O1')
words(O1+f1,0,'-F1')#F1右焦点
words(O2-f2,0,'F2')#F2左焦点
words(O2,0,'O2')
words(O2+f2,0,'-F2')#F2左焦点
words(O1,H1,'A')
words(O1,-H1-15,'B')
words(O2,H2,'C')
words(O2,-H2-15,'D')
words(O1,Y-15,"E")
words(x1,y1-15,"G")
words(x2,y2-15,"P")
words(O2,y1-15,"J")
character(x2-30,y2/2,"虚像")
character(O1,H1+30,"物镜")
character(O2,H2+30,"目镜")
hideturtle()
done()
效果如下:
数据输入示例:
主光轴的长度L:300
物镜的焦距f1:40
目镜的焦距f2:100
物镜的主点位置O1:-80
目镜的主点位置O2:100
物镜的高度H1:50
目镜的高距H2:100
物镜的圆心位置Y1:0
目镜的圆心位置Y2:-20
物体的位置X:-140
物体的高度Y:40
(三)结语
如果有什么错误的地方,还请大家批评指正,最后,希望小伙伴们都能有所收获。码字不易,喜欢的话,关注一波在走吧