当前位置: 首页 > news >正文

光的折射控制器

import math import tkinter as tk from tkinter import ttk, colorchooser class RefractionVisualizer(tk.Tk): def __init__(self): super().__init__() self.title("光的折射控制器 | 斯涅尔定律可视化") self.geometry("800x600") # 初始化参数 self.incident_angle = 30 # 入射角(度) self.n1 = 1.0 # 介质1折射率 self.n2 = 1.33 # 介质2折射率 self.light_color = "#ff0000" # 光线颜色 self.has_total_reflection = False self.refract_angle = 0 self.init_ui() self.calculate_refraction() self.draw_refraction() def init_ui(self): # 标题区域 title_frame = ttk.Frame(self) title_frame.pack(pady=10) ttk.Label(title_frame, text="光的折射控制器", font=("微软雅黑", 20, "bold")).pack() ttk.Label(title_frame, text="斯涅尔定律:n₁·sinθ₁ = n₂·sinθ₂", font=("微软雅黑", 16)).pack() # 画布区域 self.canvas = tk.Canvas(self, width=780, height=400, bg="#fafbfc", bd=1, relief="solid") self.canvas.pack(pady=10) # 控制区域 control_frame = ttk.Frame(self) control_frame.pack(pady=10, fill="x", padx=20) # 左侧控制(入射角、介质1折射率) left_frame = ttk.Frame(control_frame) left_frame.pack(side="left", fill="x", expand=True, padx=10) # 入射角 ttk.Label(left_frame, text=f"入射角 θ₁:{self.incident_angle}°", font=("微软雅黑", 12)).pack(anchor="w") self.angle_slider = ttk.Scale(left_frame, from_=0, to=89, orient="horizontal", command=self.update_angle) self.angle_slider.set(self.incident_angle) self.angle_slider.pack(fill="x", pady=5) # 介质1折射率 ttk.Label(left_frame, text=f"介质1 折射率 n₁:{self.n1:.2f}", font=("微软雅黑", 12)).pack(anchor="w") self.n1_slider = ttk.Scale(left_frame, from_=1.0, to=2.0, orient="horizontal", command=self.update_n1) self.n1_slider.set(self.n1) self.n1_slider.pack(fill="x", pady=5) # 右侧控制(介质2折射率、颜色选择) right_frame = ttk.Frame(control_frame) right_frame.pack(side="right", fill="x", expand=True, padx=10) # 介质2折射率 ttk.Label(right_frame, text=f"介质2 折射率 n₂:{self.n2:.2f}", font=("微软雅黑", 12)).pack(anchor="w") self.n2_slider = ttk.Scale(right_frame, from_=1.0, to=2.0, orient="horizontal", command=self.update_n2) self.n2_slider.set(self.n2) self.n2_slider.pack(fill="x", pady=5) # 颜色选择 self.color_label = ttk.Label(right_frame, text=f"当前颜色:{self.light_color}", font=("微软雅黑", 12)) self.color_label.pack(anchor="w") self.color_btn = ttk.Button(right_frame, text="选择光线颜色", command=self.choose_color) self.color_btn.pack(fill="x", pady=5) def update_angle(self, value): self.incident_angle = int(float(value)) self.angle_slider.master.winfo_children()[0].config(text=f"入射角 θ₁:{self.incident_angle}°") self.calculate_refraction() self.draw_refraction() def update_n1(self, value): self.n1 = round(float(value), 2) self.n1_slider.master.winfo_children()[2].config(text=f"介质1 折射率 n₁:{self.n1:.2f}") self.calculate_refraction() self.draw_refraction() def update_n2(self, value): self.n2 = round(float(value), 2) self.n2_slider.master.winfo_children()[0].config(text=f"介质2 折射率 n₂:{self.n2:.2f}") self.calculate_refraction() self.draw_refraction() def choose_color(self): color = colorchooser.askcolor(initialcolor=self.light_color)[1] if color: self.light_color = color self.color_label.config(text=f"当前颜色:{self.light_color}") self.draw_refraction() def calculate_refraction(self): theta1_rad = math.radians(self.incident_angle) sin_theta2 = (self.n1 * math.sin(theta1_rad)) / self.n2 if abs(sin_theta2) > 1: self.has_total_reflection = True self.refract_angle = self.incident_angle else: self.has_total_reflection = False theta2_rad = math.asin(sin_theta2) self.refract_angle = round(math.degrees(theta2_rad), 1) def draw_arrow(self, start_x, start_y, end_x, end_y): # 绘制光线 self.canvas.create_line(start_x, start_y, end_x, end_y, fill=self.light_color, width=2) # 计算箭头 dx = end_x - start_x dy = end_y - start_y angle = math.atan2(dy, dx) arrow_len = 10 arrow_angle = math.pi / 6 # 箭头两点 p1_x = end_x - arrow_len * math.cos(angle - arrow_angle) p1_y = end_y - arrow_len * math.sin(angle - arrow_angle) p2_x = end_x - arrow_len * math.cos(angle + arrow_angle) p2_y = end_y - arrow_len * math.sin(angle + arrow_angle) self.canvas.create_polygon(end_x, end_y, p1_x, p1_y, p2_x, p2_y, fill=self.light_color) def draw_angle_arc(self, center_x, center_y, radius, start_angle, end_angle, label): # 绘制圆弧 start_x = center_x + radius * math.cos(start_angle) start_y = center_y + radius * math.sin(start_angle) end_x = center_x + radius * math.cos(end_angle) end_y = center_y + radius * math.sin(end_angle) self.canvas.create_arc( center_x - radius, center_y - radius, center_x + radius, center_y + radius, start=math.degrees(start_angle), extent=math.degrees(end_angle - start_angle), outline="#2c3e50", width=1, style="arc" ) # 标注文字 mid_angle = (start_angle + end_angle) / 2 label_x = center_x + (radius + 15) * math.cos(mid_angle) label_y = center_y + (radius + 15) * math.sin(mid_angle) self.canvas.create_text(label_x, label_y, text=label, fill="#2c3e50", font=("微软雅黑", 10)) def draw_refraction(self): # 清空画布 self.canvas.delete("all") w = 780 h = 400 center_x = w / 2 interface_y = h / 2 ray_length = 180 # 1. 绘制介质分界面 self.canvas.create_line(0, interface_y, w, interface_y, fill="#2c3e50", width=2) # 标注介质 self.canvas.create_text(20, interface_y - 20, text=f"介质1 (n₁ = {self.n1:.2f})", fill="#2c3e50", font=("微软雅黑", 12)) self.canvas.create_text(20, interface_y + 40, text=f"介质2 (n₂ = {self.n2:.2f})", fill="#2c3e50", font=("微软雅黑", 12)) # 2. 绘制法线(虚线) self.canvas.create_line(center_x, 0, center_x, h, fill="#7f8c8d", width=1, dash=(5, 5)) # 3. 计算光线坐标 theta1_rad = math.radians(self.incident_angle) theta2_rad = math.radians(self.refract_angle) # 入射光线 incident_start_x = center_x - ray_length * math.sin(theta1_rad) incident_start_y = interface_y - ray_length * math.cos(theta1_rad) self.draw_arrow(incident_start_x, incident_start_y, center_x, interface_y) # 4. 折射/反射光线 if self.has_total_reflection: # 全反射 reflect_end_x = center_x + ray_length * math.sin(theta2_rad) reflect_end_y = interface_y - ray_length * math.cos(theta2_rad) self.draw_arrow(center_x, interface_y, reflect_end_x, reflect_end_y) self.canvas.create_text(center_x + 50, interface_y - 80, text="全反射", fill="#e74c3c", font=("微软雅黑", 12)) else: # 折射 refract_end_x = center_x + ray_length * math.sin(theta2_rad) refract_end_y = interface_y + ray_length * math.cos(theta2_rad) self.draw_arrow(center_x, interface_y, refract_end_x, refract_end_y) # 5. 标注角度 self.draw_angle_arc(center_x, interface_y, 30, -math.pi/2, -math.pi/2 + theta1_rad, f"θ₁ = {self.incident_angle}°") self.draw_angle_arc(center_x, interface_y, 50, math.pi/2 - theta2_rad, math.pi/2, f"θ₂ = {self.refract_angle:.1f}°") if __name__ == "__main__": app = RefractionVisualizer() app.mainloop()
http://www.cnnetsun.cn/news/186115.html

相关文章:

  • Joy-Con Toolkit终极指南:全方位手柄定制与性能优化方案
  • Joy-Con Toolkit专业级手柄控制:深度解析与实战应用
  • CowabungaLite终极指南:免费解锁iOS 15+设备完整自定义功能
  • 精通iOS自定义:完全掌控你的个性化设备体验
  • NBTExplorer:3个简单步骤掌握我的世界数据编辑终极工具
  • 微信数据解密终极指南:WechatDecrypt工具5步轻松上手
  • RimWorld模组管理终极指南:RimSort完整安装使用教程
  • GetQzonehistory终极指南:一键完整备份QQ空间所有历史记录
  • CowabungaLite终极指南:解锁iOS 15+设备自定义核心功能
  • XXMI启动器:多游戏模型导入器管理工具完整指南
  • GetQzonehistory:一键导出QQ空间完整历史记录,永久保存青春回忆
  • iOS个性化定制工具箱:Cowabunga Lite深度使用指南
  • Jasminum插件:3步搞定知网文献元数据抓取的完整指南
  • 树莓派pico超详细版入门:连接电脑与文件传输
  • 组合逻辑电路设计超详细版:三态门与总线接口电路的工作机制
  • pico之版权验证不通过
  • 视频PPT提取终极指南:3分钟实现自动化课件整理
  • 解锁BAAI bge-large-zh-v1.5:中文语义检索新体验
  • 淘宝开放API批量上架商品操作指南(2025年最新版)
  • XHS-Downloader小红书数据采集终极指南:5分钟快速上手教程
  • Vue3-Element-Admin终极解决方案:企业级后台管理系统的完整框架
  • 罗技鼠标宏完整配置教程:快速掌握绝地求生压枪技巧
  • Zotero-SciPDF终极指南:一键获取学术文献PDF的完美解决方案
  • Zotero-SciPDF终极指南:一键获取学术文献PDF的完整解决方案
  • VMware macOS解锁工具终极指南:轻松打造跨平台开发环境
  • 基于Vivado2025的Verilog综合行为全面讲解
  • Hitboxer SOCD清理器:终极游戏按键冲突解决方案
  • 视频PPT智能提取:零基础快速上手完整教程
  • 图解说明常见工控设备USB串口驱动安装流程
  • VMware Unlocker工具使用指南:在Windows和Linux系统上运行macOS虚拟机