E. 实验5_11_设计函数isPerfect与printPerfect

本文介绍了一段C语言代码,该代码用于查找并打印指定范围内的所有完美数。完美数是指那些其所有真因子(不包括自身)之和等于自身的正整数。代码通过定义函数isPerfect检查一个数是否为完美数,并使用函数printPerfect打印完美数及其因子分解。
#include<stdio.h>
int isPerfect(int n);
void printPerfect(int n);
int main()
{
	int t,a,b,n,count=0;
	scanf("%d%d",&a,&b);
	for(n=a;n<=b;n++)
	{
		t=isPerfect(n);
		if(t==1)
		{
		  printPerfect(n);
		  count++;
        }
	}
	printf("The total number is %d.\n",count);
	return 0;
    
} 
int isPerfect(int n)
{
	int i,sum=0;
	if(n==1)
	  return 0;
	for(i=1;i<n;i++)
	{
		if(n%i==0)
		  sum+=i;
	}
	if(sum==n)
	  return 1;
	else
	  return 0;
}
void printPerfect(int n)
{
	int i,j=0;
	for(i=1;i<n;i++)
	{
		if(n%i==0)
		{
		  if(j==0)
		  {
		  printf("%d=%d",n,i);
		  j++;
	      }
	      else if(j!=0)
	      printf("+%d",i);
		}
	}
	printf("\n");
}

 

import numpy as np class Surface: ''' Surface结构体 - 表示光学表面 参数: radius: 曲率半径 thickness: 厚度 nd1, nF1, nC1: 像方折射率 (d光, F光, C光) semi_dia: 半通光孔径 ''' def __init__(self, radius, thickness, nd1, nF1, nC1, semi_dia): self.radius = radius self.thickness = thickness self.nd1 = nd1 self.nF1 = nF1 self.nC1 = nC1 self.semi_dia = semi_dia # 物方折射率初始化为0,将在后续计算中设置 self.nd0 = 0 self.nF0 = 0 self.nC0 = 0 class Calculate: """ 光学计算核心类,封装所有光学计算功能 参数: object_surface: 物面信息 (Surface对象) lens_surfaces: 镜面列表 (Surface对象列表) entrance_pupil: 入瞳信息 (Surface对象) image_surface: 像面信息 (Surface对象) """ EPS = 1e-5 # PA校验精度 def __init__(self, object_surface, lens_surfaces, entrance_pupil, image_surface): self.object = object_surface self.lens = lens_surfaces self.pupil = entrance_pupil self.image = image_surface # 设置物方折射率 self._set_refractive_indices() def _set_refractive_indices(self): """设置每个镜面的物方折射率""" # 第一面的物方折射率等于物面的像方折射率 if len(self.lens) > 0: self.lens[0].nd0 = self.object.nd1 self.lens[0].nF0 = self.object.nF1 self.lens[0].nC0 = self.object.nC1 # 后续面的物方折射率等于前一面的像方折射率 for i in range(1, len(self.lens)): self.lens[i].nd0 = self.lens[i-1].nd1 self.lens[i].nF0 = self.lens[i-1].nF1 self.lens[i].nC0 = self.lens[i-1].nC1 def calc(self, K_eta, K_W, raytype, isParallel=False): """ 计算指定孔径和视场的光线在光学系统中的路径 参数: K_eta: 孔径取点系数 (0~1) K_W: 视场取点系数 (0~1) raytype: 光线类型 ('d', 'F', 'C') isParallel: 是否平行于光轴 (默认为False) 返回: L0, L1, U, I0, I1, PA: 各面的光线参数 """ # 初始化结果列表 L0, L1, U, I0, I1, PA = [], [], [], [], [], [] # 获取入瞳半径 A = self.pupil.semi_dia eta = K_eta * A # 像高 # 处理不同物距情况 if self.object.thickness is None and K_W == 0 and isParallel: # 物在无穷远且光线平行于光轴 h0 = K_eta * self.pupil.semi_dia L0, L1, U, I0, I1, PA = self._lens_recursion(0, 0, h0, raytype, True) else: # 其他情况 if self.object.thickness is None and K_W != 0: # 物在无穷远但非轴上点 U_val = -K_W * self.object.semi_dia * np.pi/180 L_val = self.pupil.thickness + eta / np.tan(U_val) elif self.object.semi_dia == 0: # 轴上点在有限远处 L_val = -self.object.thickness Lp = self.pupil.thickness U_val = np.arcsin(K_eta * A / np.sqrt(A**2 + Lp**2)) else: # 有限物距 Lp = self.pupil.thickness y = K_W * self.object.semi_dia U_val = np.arctan((y - eta) / (Lp + self.object.thickness)) L_val = Lp + eta / ((y - eta) / (Lp + self.object.thickness)) L0, L1, U, I0, I1, PA = self._lens_recursion(L_val, U_val, 0, raytype, False) return L0, L1, U, I0, I1, PA def _lens_recursion(self, L, U, H, raytype, isParallel): """ 光线追迹递归计算 (内部方法) """ L_data = [L] L1_data = [] U_data = [U] I_data = [] I1_data = [] PA_data = [] for i, surface in enumerate(self.lens): # 计算入射角 if i == 0 and isParallel: sinI = H / surface.radius else: sinI = (L - surface.radius) / surface.radius * np.sin(U) # 根据光线类型选择折射率 if raytype == 'd': n0, n1 = surface.nd0, surface.nd1 elif raytype == 'F': n0, n1 = surface.nF0, surface.nF1 else: # 'C' n0, n1 = surface.nC0, surface.nC1 # 计算折射角 sinII = n0 / n1 * sinI # 处理可能的数值误差 if abs(sinI) < 1 and abs(sinII) < 1: I_val = np.arcsin(sinI) II_val = np.arcsin(sinII) I_data.append(I_val) I1_data.append(II_val) else: I_val = None II_val = None # 计算折射后的角度 U_new = U + I_val - II_val if I_val is not None and II_val is not None else U L_new = surface.radius + surface.radius * sinII / np.sin(U_new) if II_val is not None else surface.radius L1_data.append(L_new) U_data.append(U_new) # PA校对法验证 if I_val is not None and II_val is not None and not isParallel: PA1 = L * np.sin(U) / np.cos((I_val - U)/2) PA2 = L_new * np.sin(U_new) / np.cos((II_val - U_new)/2) if abs(PA1 - PA2) > self.EPS: print(f"PA校验不通过: PA1={PA1:.6f}, PA2={PA2:.6f}") # 过渡到下一面 U = U_new L = L_new - surface.thickness # 记录物方截距 if i < len(self.lens) - 1: L_data.append(L) return L_data, L1_data, U_data, I_data, I1_data, PA_data def _astigmatism_recursion(self, L_data, L1_data, U_data, I_data, I1_data, PA_data, raytype, isParallel): """ 计算像散和场曲 (内部方法) """ lensnumber = len(self.lens) xt, xs, delta_x = 0, 0, 0 for i, surface in enumerate(self.lens): # 根据光线类型选择折射率 if raytype == 'd': n0, n1 = surface.nd0, surface.nd1 elif raytype == 'F': n0, n1 = surface.nF0, surface.nF1 else: # 'C' n0, n1 = surface.nC0, surface.nC1 # 计算表面弯曲 x = PA_data[i]**2 / (2 * surface.radius) if i < len(PA_data) else 0 # 初始化t和s值 if i == 0 and not isParallel: t = s = (L_data[0] - x) / np.cos(U_data[0]) elif i == 0 and isParallel: t = s = (L_data[1] - x) / np.cos(U_data[1]) # 计算子午和弧矢场曲 cosI = np.cos(I_data[i]) if i < len(I_data) else 1 cosII = np.cos(I1_data[i]) if i < len(I1_data) else 1 temp_tt = (n1 * cosII - n0 * cosI) / surface.radius + n0 * cosI**2 / t tt = (n1 * cosII**2) / temp_tt # t' temp_ss = (n1 * cosII - n0 * cosI) / surface.radius + n0 / s ss = n1 / temp_ss # s' # 过渡到下一面 if i < lensnumber - 1: next_x = PA_data[i+1]**2 / (2 * self.lens[i+1].radius) if i+1 < len(PA_data) else 0 D = (surface.thickness - x + next_x) / np.cos(U_data[i+1]) t = tt - D s = ss - D else: # 最后一面 lt = tt * np.cos(U_data[i+1]) + x ls = ss * np.cos(U_data[i+1]) + x xt = lt - L1_data[i] xs = ls - L1_data[i] delta_x = xt - xs return xt, xs, delta_x def process(self): """ 主计算函数,返回所有光学计算结果 返回: data1, data2, data3, data4, data5, data6: 六组计算结果 """ oo = 1e-20 # 近轴小量 # 计算焦距和主点位置 ff, l_H = self._calc_ff(oo) # 计算像距、像高、像散和场曲 ll, ll_F, ll_C, y0, y0_707, xt, xs, delta_x = self._calc_ll(oo, l_H, ff) # 计算出瞳距 l_p = self._calc_lp(oo) # 计算球差和位置色差 data2, data3, data4 = self._calc_sp(oo, ll) # 计算彗差、畸变和倍率色差 data5, data6 = self._calc_coma(oo, y0, y0_707) # 组装第一组数据 data1 = [ ff, ll, l_H, l_p, y0, y0_707, xt, xs, delta_x, ll_F, ll_C ] return data1, data2, data3, data4, data5, data6 def _calc_ff(self, oo): """计算像方焦距和主点位置""" # 创建一个近轴无穷远物面 object_ = Surface( self.object.radius, None, self.object.nd1, self.object.nF1, self.object.nC1, self.object.semi_dia ) # 计算平行入射的近轴光线 _, L1, _, _, _, _ = self.calc(oo, 0, 'd', True) # 计算焦距 ff = L1[-1] if L1 else 0 # 计算像方焦点和主点位置 l_F = L1[-1] if L1 else 0 l_H = ff - l_F return ff, l_H def _calc_ll(self, oo, l_H, ff): """计算像距、像高、像散和场曲""" # 计算物面入射的近轴光线 L0, L1, _, _, _, _ = self.calc(oo, 0, 'd') # 计算像距 if self.object.thickness is None: ll = ff - l_H else: ll = L1[-1] if L1 else 0 # 计算像高 if self.object.thickness is None: y0 = ff * np.tan(self.object.semi_dia * np.pi / 180) y0_707 = ff * np.tan(0.707 * self.object.semi_dia * np.pi / 180) else: y0 = self.object.semi_dia for i, surface in enumerate(self.lens): n0 = surface.nd0 n1 = surface.nd1 l0 = L0[i] if i < len(L0) else 0 l1 = L1[i] if i < len(L1) else 0 beta = (n0 * l1) / (n1 * l0) # 横向放大倍率 y0 *= beta y0_707 = 0.707 * y0 # 计算C光和F光的近轴像距 _, L1F, _, _, _, _ = self.calc(oo, 0, 'F') ll_F = L1F[-1] if L1F else 0 _, L1C, _, _, _, _ = self.calc(oo, 0, 'C') ll_C = L1C[-1] if L1C else 0 # 计算场曲及像散 L0_full, L1_full, U_full, I0_full, I1_full, PA_full = self.calc(0, 1, 'd') if self.object.thickness is None: L0_full[0] = 1e15 # 模拟无穷远 else: L0_full[0] = -self.object.thickness isParallel = self.object.thickness is None and self.object.semi_dia is None xt, xs, delta_x = self._astigmatism_recursion( L0_full, L1_full, U_full, I0_full, I1_full, PA_full, 'd', isParallel ) return ll, ll_F, ll_C, y0, y0_707, xt, xs, delta_x def _calc_lp(self, oo): """计算出瞳距""" # 定义入瞳面 object_ = Surface( self.pupil.radius, self.pupil.thickness, self.pupil.nd1, self.pupil.nC1, self.pupil.nF1, self.pupil.semi_dia ) _, L1, _, _, _, _ = self.calc(oo, 0, 'd') l_p = L1[-1] if L1 else 0 return l_p def _calc_sp(self, oo, ll): """计算球差和位置色差""" # 全孔径计算 _, L1d1, _, _, _, _ = self.calc(1, 0, 'd') ll_d1 = L1d1[-1] if L1d1 else 0 SPAB1 = ll_d1 - ll _, L1F1, _, _, _, _ = self.calc(1, 0, 'F') ll_F1 = L1F1[-1] if L1F1 else 0 _, L1C1, _, _, _, _ = self.calc(1, 0, 'C') ll_C1 = L1C1[-1] if L1C1 else 0 PCA1 = ll_F1 - ll_C1 # 0.707孔径计算 _, L1d707, _, _, _, _ = self.calc(0.707, 0, 'd') ll_d707 = L1d707[-1] if L1d707 else 0 SPAB707 = ll_d707 - ll _, L1F707, _, _, _, _ = self.calc(0.707, 0, 'F') ll_F707 = L1F707[-1] if L1F707 else 0 _, L1C707, _, _, _, _ = self.calc(0.707, 0, 'C') ll_C707 = L1C707[-1] if L1C707 else 0 PCA707 = ll_F707 - ll_C707 # 0孔径位置色差 _, L1F0, _, _, _, _ = self.calc(oo, 0, 'F') ll_F0 = L1F0[-1] if L1F0 else 0 _, L1C0, _, _, _, _ = self.calc(oo, 0, 'C') ll_C0 = L1C0[-1] if L1C0 else 0 PCA0 = ll_F0 - ll_C0 # 组装数据 data2 = [ll_d1, ll_F1, ll_C1, SPAB1, PCA1] data3 = [ll_d707, ll_F707, ll_C707, SPAB707, PCA707] data4 = [PCA0] return data2, data3, data4 def _calc_coma(self, oo, y0, y0_707): """计算彗差、畸变和倍率色差""" # 获取理想像面位置 _, L_perfect_d, _, _, _, _ = self.calc(oo, 0, 'd') ll_perfect = L_perfect_d[-1] if L_perfect_d else 0 # 计算彗差 coma_results = {} for field in [-1, -0.707]: for aperture in [1, 0.707, -1, -0.707]: key = f"{abs(field)}_{abs(aperture)}" _, L1, U, _, _, _ = self.calc(aperture, field, 'd') y = (ll_perfect - L1[-1]) * np.tan(U[-1]) if L1 and U else 0 coma_results[key] = y # 全视场彗差 COMA1 = (coma_results['1_1'] + coma_results['1_1']) / 2 - coma_results['1_0'] COMA2 = (coma_results['1_0.707'] + coma_results['1_0.707']) / 2 - coma_results['1_0'] # 0.707视场彗差 COMA3 = (coma_results['0.707_1'] + coma_results['0.707_1']) / 2 - coma_results['0.707_0'] COMA4 = (coma_results['0.707_0.707'] + coma_results['0.707_0.707']) / 2 - coma_results['0.707_0'] # 计算实际像高 _, L1_central_d, U_central_d, _, _, _ = self.calc(0, -1, 'd') y_d_1 = (ll_perfect - L1_central_d[-1]) * np.tan(U_central_d[-1]) if L1_central_d and U_central_d else 0 _, L1_central_F, U_central_F, _, _, _ = self.calc(0, -1, 'F') y_F_1 = (ll_perfect - L1_central_F[-1]) * np.tan(U_central_F[-1]) if L1_central_F and U_central_F else 0 _, L1_central_C, U_central_C, _, _, _ = self.calc(0, -1, 'C') y_C_1 = (ll_perfect - L1_central_C[-1]) * np.tan(U_central_C[-1]) if L1_central_C and U_central_C else 0 # 0.707视场实际像高 _, L1_central_d_07, U_central_d_07, _, _, _ = self.calc(0, -0.707, 'd') y_d_07 = (ll_perfect - L1_central_d_07[-1]) * np.tan(U_central_d_07[-1]) if L1_central_d_07 and U_central_d_07 else 0 _, L1_central_F_07, U_central_F_07, _, _, _ = self.calc(0, -0.707, 'F') y_F_07 = (ll_perfect - L1_central_F_07[-1]) * np.tan(U_central_F_07[-1]) if L1_central_F_07 and U_central_F_07 else 0 _, L1_central_C_07, U_central_C_07, _, _, _ = self.calc(0, -0.707, 'C') y_C_07 = (ll_perfect - L1_central_C_07[-1]) * np.tan(U_central_C_07[-1]) if L1_central_C_07 and U_central_C_07 else 0 # 倍率色差 MCA1 = y_F_1 - y_C_1 MCA07 = y_F_07 - y_C_07 # 畸变计算 DIS1 = y_d_1 - y0 rel_DIS1 = DIS1 / y0 if y0 != 0 else 0 DIS07 = y_d_07 - y0_707 rel_DIS07 = DIS07 / y0_707 if y0_707 != 0 else 0 # 组装数据 data5 = [ COMA1, COMA2, y_d_1, y_F_1, y_C_1, DIS1, rel_DIS1, MCA1 ] data6 = [ COMA3, COMA4, y_d_07, y_F_07, y_C_07, DIS07, rel_DIS07, MCA07 ] return data5, data6 ###上方为计算相关 ###下方为GUI相关 class MainApplication: def __init__(self, root): self.root = root self.root.title("光学系统计算程序") self.root.geometry("1000x850") # 创建光学系统对象 self.system = OpticalSystem() # 创建GUI组件 self.create_widgets() # 加载默认设置(如果有) self.load_default_settings() def create_widgets(self): # 主框架 main_frame = ttk.Frame(self.root) main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10) # 文件操作框架 file_frame = ttk.LabelFrame(main_frame, text="文件操作") file_frame.pack(fill=tk.X, padx=5, pady=5) # 文件路径输入 ttk.Label(file_frame, text="文件路径:").grid(row=0, column=0, padx=5, pady=5) self.file_path_entry = ttk.Entry(file_frame, width=50) self.file_path_entry.grid(row=0, column=1, padx=5, pady=5) # 文件操作按钮 browse_btn = ttk.Button(file_frame, text="浏览...", command=self.browse_file) browse_btn.grid(row=0, column=2, padx=5, pady=5) load_btn = ttk.Button(file_frame, text="加载系统参数", command=self.load_system) load_btn.grid(row=0, column=3, padx=5, pady=5) save_btn = ttk.Button(file_frame, text="保存系统参数", command=self.save_system) save_btn.grid(row=0, column=4, padx=5, pady=5) # 左侧面板 - 输入参数 left_frame = ttk.LabelFrame(main_frame, text="系统参数输入") left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5) # 右侧面板 - 结果展示 right_frame = ttk.LabelFrame(main_frame, text="计算结果") right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5) # 创建左侧面板的子组件 self.create_input_panel(left_frame) # 创建右侧面板的子组件 self.create_result_panel(right_frame) # 计算按钮 calc_frame = ttk.Frame(main_frame) calc_frame.pack(fill=tk.X, padx=5, pady=10) calc_btn = ttk.Button(calc_frame, text="开始计算", command=self.calculate, width=15) calc_btn.pack(side=tk.LEFT, padx=10) save_result_btn = ttk.Button(calc_frame, text="保存计算结果", command=self.save_results, width=15) save_result_btn.pack(side=tk.LEFT, padx=10) clear_btn = ttk.Button(calc_frame, text="清除所有", command=self.clear_all, width=15) clear_btn.pack(side=tk.LEFT, padx=10) def browse_file(self): """浏览文件按钮处理函数""" file_path = filedialog.askopenfilename( title="选择文件", filetypes=[("JSON文件", "*.json"), ("所有文件", "*.*")] ) if file_path: self.file_path_entry.delete(0, tk.END) self.file_path_entry.insert(0, file_path) def create_input_panel(self, parent): # 入瞳参数 pupil_frame = ttk.LabelFrame(parent, text="入瞳参数") pupil_frame.pack(fill=tk.X, padx=5, pady=5) ttk.Label(pupil_frame, text="入瞳直径 (mm):").grid(row=0, column=0, padx=5, pady=5, sticky="w") self.entrance_diameter_entry = ttk.Entry(pupil_frame, width=15) self.entrance_diameter_entry.grid(row=0, column=1, padx=5, pady=5) ttk.Label(pupil_frame, text="入瞳位置 (mm):").grid(row=0, column=2, padx=5, pady=5, sticky="w") self.entrance_position_entry = ttk.Entry(pupil_frame, width=15) self.entrance_position_entry.grid(row=0, column=3, padx=5, pady=5) # 色光类型选择 ttk.Label(pupil_frame, text="色光类型:").grid(row=1, column=0, padx=5, pady=5, sticky="w") self.light_type_var = tk.StringVar(value="d") self.light_type_combo = ttk.Combobox(pupil_frame, textvariable=self.light_type_var, width=12, state="readonly") self.light_type_combo["values"] = ("d", "f", "c") self.light_type_combo.grid(row=1, column=1, padx=5, pady=5, sticky="w") # 物方参数 object_frame = ttk.LabelFrame(parent, text="物方参数") object_frame.pack(fill=tk.X, padx=5, pady=5) # 物距选择 self.object_var = tk.BooleanVar(value=True) # True: 无穷远, False: 有限远 ttk.Radiobutton(object_frame, text="物在无穷远", variable=self.object_var, value=True, command=self.toggle_object_input).grid(row=0, column=0, padx=5, pady=5) ttk.Radiobutton(object_frame, text="物在有限远", variable=self.object_var, value=False, command=self.toggle_object_input).grid(row=0, column=1, padx=5, pady=5) # 无穷远参数 self.infinite_frame = ttk.Frame(object_frame) self.infinite_frame.grid(row=1, column=0, columnspan=2, sticky="w", padx=5, pady=5) ttk.Label(self.infinite_frame, text="半视场角 (度):").grid(row=0, column=0, padx=5, pady=5, sticky="w") self.field_angle_entry = ttk.Entry(self.infinite_frame, width=15) self.field_angle_entry.grid(row=0, column=1, padx=5, pady=5) # 有限远参数 (初始隐藏) self.finite_frame = ttk.Frame(object_frame) self.finite_frame.grid(row=1, column=0, columnspan=2, sticky="w", padx=5, pady=5) self.finite_frame.grid_remove() # 初始隐藏 ttk.Label(self.finite_frame, text="物距 (mm):").grid(row=0, column=0, padx=5, pady=5, sticky="w") self.object_distance_entry = ttk.Entry(self.finite_frame, width=15) self.object_distance_entry.grid(row=0, column=1, padx=5, pady=5) ttk.Label(self.finite_frame, text="物高 (mm):").grid(row=0, column=2, padx=5, pady=5, sticky="w") self.object_height_entry = ttk.Entry(self.finite_frame, width=15) self.object_height_entry.grid(row=0, column=3, padx=5, pady=5) ttk.Label(self.finite_frame, text="孔径角 (度):").grid(row=0, column=4, padx=5, pady=5, sticky="w") self.aperture_angle_entry = ttk.Entry(self.finite_frame, width=15) self.aperture_angle_entry.grid(row=0, column=5, padx=5, pady=5) # 光学表面输入 surface_frame = ttk.LabelFrame(parent, text="光学表面参数") surface_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) # 表面输入控件 input_frame = ttk.Frame(surface_frame) input_frame.pack(fill=tk.X, padx=5, pady=5) ttk.Label(input_frame, text="曲率半径 (mm):").grid(row=0, column=0, padx=5, pady=5) self.radius_entry = ttk.Entry(input_frame, width=10) self.radius_entry.grid(row=0, column=1, padx=5, pady=5) self.radius_entry.insert(0, "50") ttk.Label(input_frame, text="厚度 (mm):").grid(row=0, column=2, padx=5, pady=5) self.thickness_entry = ttk.Entry(input_frame, width=10) self.thickness_entry.grid(row=0, column=3, padx=5, pady=5) self.thickness_entry.insert(0, "5") ttk.Label(input_frame, text="折射率 (nd):").grid(row=0, column=4, padx=5, pady=5) self.nd_entry = ttk.Entry(input_frame, width=10) self.nd_entry.grid(row=0, column=5, padx=5, pady=5) self.nd_entry.insert(0, "1.5") ttk.Label(input_frame, text="阿贝数 (vd):").grid(row=0, column=6, padx=5, pady=5) self.vd_entry = ttk.Entry(input_frame, width=10) self.vd_entry.grid(row=0, column=7, padx=5, pady=5) self.vd_entry.insert(0, "60") button_frame = ttk.Frame(input_frame) button_frame.grid(row=0, column=8, padx=10) add_btn = ttk.Button(button_frame, text="添加表面", command=self.add_surface) add_btn.pack(side=tk.LEFT, padx=5) remove_btn = ttk.Button(button_frame, text="删除表面", command=self.remove_surface) remove_btn.pack(side=tk.LEFT, padx=5) # 表面列表 list_frame = ttk.Frame(surface_frame) list_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) columns = ("#", "曲率半径 (mm)", "厚度 (mm)", "折射率 (nd)", "阿贝数 (vd)") self.surface_tree = ttk.Treeview(list_frame, columns=columns, show="headings", height=8) for col in columns: self.surface_tree.heading(col, text=col) self.surface_tree.column(col, width=100, anchor=tk.CENTER) vsb = ttk.Scrollbar(list_frame, orient="vertical", command=self.surface_tree.yview) self.surface_tree.configure(yscrollcommand=vsb.set) self.surface_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) vsb.pack(side=tk.RIGHT, fill=tk.Y) def create_result_panel(self, parent): # 结果文本框 self.result_text = tk.Text(parent, wrap=tk.WORD) result_scroll_y = ttk.Scrollbar(parent, orient="vertical", command=self.result_text.yview) result_scroll_x = ttk.Scrollbar(parent, orient="horizontal", command=self.result_text.xview) self.result_text.configure(yscrollcommand=result_scroll_y.set, xscrollcommand=result_scroll_x.set) result_scroll_y.pack(side=tk.RIGHT, fill=tk.Y) result_scroll_x.pack(side=tk.BOTTOM, fill=tk.X) self.result_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True) # 设置初始文本 self.result_text.insert(tk.END, "计算结果将显示在此处...\n\n") self.result_text.configure(state=tk.DISABLED) def toggle_object_input(self): """切换物方参数输入界面""" if self.object_var.get(): # 无穷远 self.infinite_frame.grid() self.finite_frame.grid_remove() else: # 有限远 self.infinite_frame.grid_remove() self.finite_frame.grid() def add_surface(self): """添加光学表面""" try: # 获取输入值 r = self.radius_entry.get().strip() d = self.thickness_entry.get().strip() nd = self.nd_entry.get().strip() vd = self.vd_entry.get().strip() # 处理输入值 r = float(r) if r and r.lower() != "inf" else float('inf') d = float(d) if d else 0.0 nd = float(nd) if nd else 1.0 vd = float(vd) if vd else 0.0 # 添加到系统 surface = Surface(r, d, nd, vd) self.system.surfaces.append(surface) # 添加到树形视图 r_str = "平面" if r == float('inf') else f"{r:.2f}" self.surface_tree.insert("", "end", values=( len(self.system.surfaces), r_str, f"{d:.2f}", f"{nd:.4f}", f"{vd:.1f}" )) # 清空输入框 self.radius_entry.delete(0, tk.END) self.thickness_entry.delete(0, tk.END) self.nd_entry.delete(0, tk.END) self.vd_entry.delete(0, tk.END) self.radius_entry.focus_set() except ValueError: messagebox.showerror("输入错误", "请输入有效的数字") def remove_surface(self): """删除选中的光学表面""" selected = self.surface_tree.selection() if selected: # 从树形视图中删除 for item in selected: index = int(self.surface_tree.item(item, "values")[0]) - 1 self.surface_tree.delete(item) # 从系统中删除 if 0 <= index < len(self.system.surfaces): self.system.surfaces.pop(index) # 更新剩余表面的序号 for i, item in enumerate(self.surface_tree.get_children()): values = list(self.surface_tree.item(item, "values")) values[0] = i + 1 self.surface_tree.item(item, values=values) def load_system(self): """加载系统参数文件""" file_path = self.file_path_entry.get().strip() if not file_path: messagebox.showwarning("警告", "请输入文件路径") return try: with open(file_path, 'r') as f: data = json.load(f) # 加载系统参数 self.system.entrance_pupil_diameter = data.get("entrance_pupil_diameter") self.system.entrance_pupil_position = data.get("entrance_pupil_position") self.system.object_infinite = data.get("object_infinite", True) self.system.field_angle = data.get("field_angle") self.system.object_distance = data.get("object_distance") self.system.object_height = data.get("object_height") self.system.aperture_angle = data.get("aperture_angle") # 更新UI中的参数值 if self.system.entrance_pupil_diameter is not None: self.entrance_diameter_entry.delete(0, tk.END) self.entrance_diameter_entry.insert(0, str(self.system.entrance_pupil_diameter)) if self.system.entrance_pupil_position is not None: self.entrance_position_entry.delete(0, tk.END) self.entrance_position_entry.insert(0, str(self.system.entrance_pupil_position)) self.object_var.set(self.system.object_infinite) self.toggle_object_input() if self.system.field_angle is not None: self.field_angle_entry.delete(0, tk.END) self.field_angle_entry.insert(0, str(self.system.field_angle)) if self.system.object_distance is not None: self.object_distance_entry.delete(0, tk.END) self.object_distance_entry.insert(0, str(self.system.object_distance)) if self.system.object_height is not None: self.object_height_entry.delete(0, tk.END) self.object_height_entry.insert(0, str(self.system.object_height)) if self.system.aperture_angle is not None: self.aperture_angle_entry.delete(0, tk.END) self.aperture_angle_entry.insert(0, str(self.system.aperture_angle)) # 加载表面数据 self.system.surfaces = [] self.surface_tree.delete(*self.surface_tree.get_children()) surfaces_data = data.get("surfaces", []) for surf_data in surfaces_data: surface = Surface.from_dict(surf_data) self.system.surfaces.append(surface) r_str = "平面" if surface.r == float('inf') else f"{surface.r:.2f}" self.surface_tree.insert("", "end", values=( len(self.system.surfaces), r_str, f"{surface.d:.2f}", f"{surface.nd:.4f}", f"{surface.vd:.1f}" )) messagebox.showinfo("成功", f"系统参数已从 {os.path.basename(file_path)} 加载") # 显示加载的系统信息 self.result_text.configure(state=tk.NORMAL) self.result_text.delete(1.0, tk.END) self.result_text.insert(tk.END, f"已加载系统参数文件: {file_path}\n") self.result_text.insert(tk.END, f"包含 {len(self.system.surfaces)} 个光学表面\n") self.result_text.configure(state=tk.DISABLED) except FileNotFoundError: messagebox.showerror("错误", f"文件不存在: {file_path}") except Exception as e: messagebox.showerror("加载错误", f"加载文件失败: {str(e)}") def save_system(self): """保存系统参数文件""" # 更新系统参数 if not self.update_system_from_ui(): return # 如果没有表面数据,提示用户 if not self.system.surfaces: messagebox.showwarning("警告", "没有光学表面数据,无法保存") return file_path = self.file_path_entry.get().strip() if not file_path: messagebox.showwarning("警告", "请输入保存路径") return try: # 准备保存数据 data = { "entrance_pupil_diameter": self.system.entrance_pupil_diameter, "entrance_pupil_position": self.system.entrance_pupil_position, "object_infinite": self.system.object_infinite, "field_angle": self.system.field_angle, "object_distance": self.system.object_distance, "object_height": self.system.object_height, "aperture_angle": self.system.aperture_angle, "surfaces": [surf.to_dict() for surf in self.system.surfaces] } with open(file_path, 'w') as f: json.dump(data, f, indent=4) messagebox.showinfo("成功", f"系统参数已保存到 {os.path.basename(file_path)}") # 显示保存信息 self.result_text.configure(state=tk.NORMAL) self.result_text.insert(tk.END, f"系统参数已保存到: {file_path}\n") self.result_text.configure(state=tk.DISABLED) except Exception as e: messagebox.showerror("保存错误", f"保存文件失败: {str(e)}") def save_results(self): """保存计算结果到文件""" if not self.system.results or all(v is None for v in self.system.results.values()): messagebox.showwarning("警告", "没有计算结果可保存") return file_path = filedialog.asksaveasfilename( title="保存计算结果", defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")] ) if not file_path: return try: with open(file_path, 'w') as f: # 写入系统参数摘要 f.write("===== 光学系统参数 =====\n") f.write(f"入瞳直径: {self.system.entrance_pupil_diameter} mm\n") f.write(f"入瞳位置: {self.system.entrance_pupil_position} mm\n") f.write(f"色光类型: {self.system.light_type}\n") f.write("物距类型: " + ("无穷远" if self.system.object_infinite else "有限远") + "\n") if self.system.object_infinite: f.write(f"半视场角: {self.system.field_angle} 度\n") else: f.write(f"物距: {self.system.object_distance} mm\n") f.write(f"物高: {self.system.object_height} mm\n") f.write(f"孔径角: {self.system.aperture_angle} 度\n") f.write("\n光学表面参数:\n") for i, surf in enumerate(self.system.surfaces): r_str = "平面" if surf.r == float('inf') else f"{surf.r:.2f} mm" f.write(f"表面 {i+1}: r={r_str}, d={surf.d:.2f} mm, nd={surf.nd:.4f}, vd={surf.vd:.1f}\n") # 写入计算结果 f.write("\n\n===== 计算结果 =====\n") for key, value in self.system.results.items(): if value is not None: # 格式化键名 label = self.format_result_label(key) f.write(f"{label}: {value}\n") messagebox.showinfo("成功", f"计算结果已保存到 {os.path.basename(file_path)}") # 显示保存信息 self.result_text.configure(state=tk.NORMAL) self.result_text.insert(tk.END, f"计算结果已保存到: {file_path}\n") self.result_text.configure(state=tk.DISABLED) except Exception as e: messagebox.showerror("保存错误", f"保存计算结果失败: {str(e)}") def format_result_label(self, key): """格式化结果标签为中文描述""" labels = { "focal_length": "焦距 f' (mm)", "ideal_image_distance": "理想像距 l' (mm)", "actual_image_position": "实际像位置 (mm)", "image_principal_plane": "像方主面位置 lH' (mm)", "exit_pupil_distance": "出瞳距 lp' (mm)", "ideal_image_height": "理想像高 y0' (mm)", "spherical_aberration": "球差 (mm)", "longitudinal_chromatic": "位置色差 (mm)", "tangential_field_curvature": "子午场曲 xt' (mm)", "sagittal_field_curvature": "弧矢场曲 xs' (mm)", "astigmatism": "像散 Δxts' (mm)", "actual_image_height": "实际像高 (mm)", "relative_distortion": "相对畸变 (%)", "absolute_distortion": "绝对畸变 (mm)", "lateral_chromatic": "倍率色差 (mm)", "tangential_coma": "子午慧差 (mm)" } return labels.get(key, key) def update_system_from_ui(self): """从UI更新系统参数""" try: # 入瞳参数 if self.entrance_diameter_entry.get(): self.system.entrance_pupil_diameter = float(self.entrance_diameter_entry.get()) if self.entrance_position_entry.get(): self.system.entrance_pupil_position = float(self.entrance_position_entry.get()) # 色光类型 self.system.light_type = self.light_type_var.get() # 物方参数 self.system.object_infinite = self.object_var.get() if self.system.object_infinite: if self.field_angle_entry.get(): self.system.field_angle = float(self.field_angle_entry.get()) else: if self.object_distance_entry.get(): self.system.object_distance = float(self.object_distance_entry.get()) if self.object_height_entry.get(): self.system.object_height = float(self.object_height_entry.get()) if self.aperture_angle_entry.get(): self.system.aperture_angle = float(self.aperture_angle_entry.get()) except ValueError: messagebox.showerror("输入错误", "请输入有效的数字") return False return True def calculate(self): """执行光学计算""" # 更新系统参数 if not self.update_system_from_ui(): return # 检查必要参数 if not self.system.surfaces: messagebox.showwarning("警告", "请至少添加一个光学表面") return if self.system.entrance_pupil_diameter is None: messagebox.showwarning("警告", "请输入入瞳直径") return if self.system.object_infinite and self.system.field_angle is None: messagebox.showwarning("警告", "请输入半视场角") return if not self.system.object_infinite and ( self.system.object_distance is None or self.system.object_height is None or self.system.aperture_angle is None ): messagebox.showwarning("警告", "请输入完整的有限远参数") return # 执行计算 - 这里调用您的计算函数 self.perform_calculations() # 显示结果 self.display_results() # 显示计算完成消息 messagebox.showinfo("计算完成", "光学计算已完成,结果已显示在结果区域") def perform_calculations(self): """执行光学计算 - 这里调用您的实际计算函数""" # 重置结果 for key in self.system.results: self.system.results[key] = None # 示例:设置一些假结果用于演示 # 实际应用中,您需要调用您自己的计算函数 self.system.results["focal_length"] = Calculate.calculate_focal_length(self.system)[0] self.system.results["ideal_image_distance"] = 0#Calculate.calculate_ideal_image_distance(self.system) self.system.results["actual_image_position"] =0# Calculate.calculate_actual_image_position(self.system) self.system.results["image_principal_plane"] = Calculate.calculate_focal_length(self.system)[1] self.system.results["exit_pupil_distance"] = 0#Calculate.calculate_exit_pupil_distance(self.system) self.system.results["ideal_image_height"] =0# Calculate.calculate_ideal_image_height(self.system) self.system.results["spherical_aberration"] = 0#Calculate.calculate_spherical_aberration(self.system) self.system.results["longitudinal_chromatic"] = 0#Calculate.calculate_longitudinal_chromatic(self.system) self.system.results["tangential_field_curvature"] = 0.15 self.system.results["sagittal_field_curvature"] = 0.12 self.system.results["astigmatism"] = 0#Calculate.calculate_astigmatism(self.system) self.system.results["actual_image_height"] =0#Calculate.calculate_actual_image_height(self.system) self.system.results["relative_distortion"] = -0.5 self.system.results["absolute_distortion"] =0# Calculate.calculate_distortion(self.system) self.system.results["lateral_chromatic"] =0# Calculate.calculate_lateral_chromatic(self.system) self.system.results["tangential_coma"] =0# Calculate.calculate_tangential_coma(self.system) def display_results(self): """在结果文本框中显示计算结果""" self.result_text.configure(state=tk.NORMAL) self.result_text.delete(1.0, tk.END) # 添加系统参数摘要 self.result_text.insert(tk.END, "===== 光学系统参数 =====\n", "title") self.result_text.insert(tk.END, f"入瞳直径: {self.system.entrance_pupil_diameter} mm\n") self.result_text.insert(tk.END, f"入瞳位置: {self.system.entrance_pupil_position} mm\n") self.result_text.insert(tk.END, "物距类型: " + ("无穷远" if self.system.object_infinite else "有限远") + "\n") self.result_text.insert(tk.END, f"色光类型: {self.system.light_type}\n") if self.system.object_infinite: self.result_text.insert(tk.END, f"半视场角: {self.system.field_angle} 度\n") else: self.result_text.insert(tk.END, f"物距: {self.system.object_distance} mm\n") self.result_text.insert(tk.END, f"物高: {self.system.object_height} mm\n") self.result_text.insert(tk.END, f"孔径角: {self.system.aperture_angle} 度\n") self.result_text.insert(tk.END, "\n光学表面参数:\n") for i, surf in enumerate(self.system.surfaces): r_str = "平面" if surf.r == float('inf') else f"{surf.r:.2f} mm" self.result_text.insert(tk.END, f"表面 {i+1}: r={r_str}, d={surf.d:.2f} mm, nd={surf.nd:.4f}, vd={surf.vd:.1f}\n") # 添加计算结果 self.result_text.insert(tk.END, "\n\n===== 计算结果 =====\n", "title") # 计算关键结果 key_results = [ "focal_length", "ideal_image_distance", "actual_image_position", "image_principal_plane", "exit_pupil_distance", "ideal_image_height" ] for key in key_results: if self.system.results[key] is not None: label = self.format_result_label(key) self.result_text.insert(tk.END, f"{label}: {self.system.results[key]}\n") # 添加像差结果 self.result_text.insert(tk.END, "\n像差分析:\n", "subtitle") aberrations = [ "spherical_aberration", "longitudinal_chromatic", "tangential_field_curvature", "sagittal_field_curvature", "astigmatism", "actual_image_height", "relative_distortion", "absolute_distortion", "lateral_chromatic", "tangential_coma" ] for key in aberrations: if self.system.results[key] is not None: label = self.format_result_label(key) self.result_text.insert(tk.END, f"{label}: {self.system.results[key]}\n") self.result_text.configure(state=tk.DISABLED) def clear_all(self): """清除所有输入和结果""" # 清除系统参数 self.system = OpticalSystem() # 清除UI输入 self.file_path_entry.delete(0, tk.END) self.entrance_diameter_entry.delete(0, tk.END) self.entrance_position_entry.delete(0, tk.END) self.field_angle_entry.delete(0, tk.END) self.object_distance_entry.delete(0, tk.END) self.object_height_entry.delete(0, tk.END) self.aperture_angle_entry.delete(0, tk.END) self.radius_entry.delete(0, tk.END) self.radius_entry.insert(0, "50") self.thickness_entry.delete(0, tk.END) self.thickness_entry.insert(0, "5") self.nd_entry.delete(0, tk.END) self.nd_entry.insert(0, "1.5") self.vd_entry.delete(0, tk.END) self.vd_entry.insert(0, "60") # 清除表面列表 self.surface_tree.delete(*self.surface_tree.get_children()) self.system.surfaces = [] # 清除结果 self.result_text.configure(state=tk.NORMAL) self.result_text.delete(1.0, tk.END) self.result_text.insert(tk.END, "计算结果将显示在此处...\n\n") self.result_text.configure(state=tk.DISABLED) # 重置物距类型 self.object_var.set(True) self.toggle_object_input() messagebox.showinfo("清除完成", "所有输入和结果已清除") def load_default_settings(self): """加载默认设置(可选)""" # 这里可以添加加载默认设置的逻辑 pass if __name__ == "__main__": root = tk.Tk() app = MainApplication(root) # 设置文本样式 app.result_text.tag_config("title", font=("Arial", 10, "bold")) app.result_text.tag_config("subtitle", font=("Arial", 9, "bold")) root.mainloop() 整理成一个光学计算程序,因为这是两个人写的代码,所以都可以重编,但要保证能够顺利计算并显示结果,参数输入等都可以添加或删除
06-27
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值