之前习惯在科创上发布(可以看https://www.kechuang.org/t/91613),现在也为CSDN贡献一下

当然也在GitHub上开源https://github.com/HSHSpaceX/Rocket-tail-fin-stability-calculator

现在阐述一下该软件的主要功能:帮助计算火箭尾翼稳定性并模拟水火箭飞行高度并可以导出可3D打印或建模的DXF格式,未来我想开发一种标签页模式。

目前软件已有V1.0和V1.1版本,软件只有64位的,这个年代应该没人用32位

写到这,还是要吐槽下CSDN,为什么文章不让放文件,所以大家如果想下可以去上面给出的科创链接,不需要注册,直接下载。这里只有原码了

V1.0源码

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
import dxfwrite
from dxfwrite import DXFEngine as dxf

# 设置中文显示
matplotlib.rcParams['font.sans-serif'] = ['SimHei']  # 用来正常显示中文标签
matplotlib.rcParams['axes.unicode_minus'] = False    # 用来正常显示负号

class RocketStabilityCalculator:
    def __init__(self, root):
        self.root = root
        self.root.title("火箭尾翼稳定性计算器HSH编写")
        self.root.geometry("1200x800")
        
        # 输入变量
        self.length_var = tk.DoubleVar(value=500.0)  # 厘米
        self.front_weight_var = tk.DoubleVar(value=10000.0)  # 克
        self.mid_weight_var = tk.DoubleVar(value=20000.0)    # 克
        self.rear_weight_var = tk.DoubleVar(value=15000.0)   # 克
        self.wind_speed_var = tk.DoubleVar(value=5.0)
        self.launch_angle_var = tk.DoubleVar(value=45.0)
        self.target_altitude_var = tk.DoubleVar(value=1000.0)
        self.wing_shape_var = tk.StringVar(value="梯形")
        self.wing_count_var = tk.IntVar(value=4)
        self.root_chord_var = tk.DoubleVar(value=30.0)  # 厘米
        self.tip_chord_var = tk.DoubleVar(value=15.0)   # 厘米
        self.wing_span_var = tk.DoubleVar(value=40.0)   # 厘米
        self.wing_position_var = tk.DoubleVar(value=0.8)
        
        # 创建主框架
        self.main_frame = ttk.Frame(root)
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 输入区域
        self.create_input_section()
        
        # 结果区域
        self.create_output_section()
        
        # 绘图区域
        self.create_plot_section()
        
        # 底部按钮
        self.create_button_section()
    
    def create_input_section(self):
        input_frame = ttk.LabelFrame(self.main_frame, text="火箭参数")
        input_frame.grid(row=0, column=0, padx=10, pady=10, sticky="nsew")
        
        # 火箭基本参数
        ttk.Label(input_frame, text="火箭总长 (cm):").grid(row=0, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.length_var).grid(row=0, column=1)
        
        ttk.Label(input_frame, text="前段重量 (g):").grid(row=1, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.front_weight_var).grid(row=1, column=1)
        
        ttk.Label(input_frame, text="中段重量 (g):").grid(row=2, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.mid_weight_var).grid(row=2, column=1)
        
        ttk.Label(input_frame, text="后段重量 (g):").grid(row=3, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.rear_weight_var).grid(row=3, column=1)
        
        # 环境参数
        ttk.Label(input_frame, text="风速 (m/s):").grid(row=4, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.wind_speed_var).grid(row=4, column=1)
        
        ttk.Label(input_frame, text="发射角度 (度):").grid(row=5, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.launch_angle_var).grid(row=5, column=1)
        
        ttk.Label(input_frame, text="目标高度 (m):").grid(row=6, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.target_altitude_var).grid(row=6, column=1)
        
        # 尾翼参数
        ttk.Label(input_frame, text="尾翼形状:").grid(row=7, column=0, sticky="w")
        shape_combobox = ttk.Combobox(input_frame, textvariable=self.wing_shape_var, 
                                    values=["矩形", "梯形", "三角形", "椭圆", "后掠"])
        shape_combobox.grid(row=7, column=1)
        
        ttk.Label(input_frame, text="尾翼数量:").grid(row=8, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.wing_count_var).grid(row=8, column=1)
        
        ttk.Label(input_frame, text="根部弦长 (cm):").grid(row=9, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.root_chord_var).grid(row=9, column=1)
        
        ttk.Label(input_frame, text="尖部弦长 (cm):").grid(row=10, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.tip_chord_var).grid(row=10, column=1)
        
        ttk.Label(input_frame, text="翼展 (cm):").grid(row=11, column=0, sticky="w")
        ttk.Entry(input_frame, textvariable=self.wing_span_var).grid(row=11, column=1)
        
        ttk.Label(input_frame, text="安装位置 (%):").grid(row=12, column=0, sticky="w")
        ttk.Scale(input_frame, from_=0, to=100, variable=self.wing_position_var, 
                 orient=tk.HORIZONTAL, length=150).grid(row=12, column=1)
        
        # 计算按钮
        ttk.Button(input_frame, text="计算稳定性", command=self.calculate_stability).grid(row=13, column=0, columnspan=2, pady=10)
    
    def create_output_section(self):
        output_frame = ttk.LabelFrame(self.main_frame, text="计算结果")
        output_frame.grid(row=0, column=1, padx=10, pady=10, sticky="nsew")
        
        # 结果文本区域
        self.result_text = tk.Text(output_frame, height=15, width=50)
        self.result_text.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        self.result_text.insert(tk.END, "计算结果将显示在这里...")
        
        # 尾翼示意图
        self.wing_canvas = tk.Canvas(output_frame, width=200, height=150, bg="white")
        self.wing_canvas.pack(pady=10)
    
    def create_plot_section(self):
        plot_frame = ttk.LabelFrame(self.main_frame, text="飞行偏离角度")
        plot_frame.grid(row=1, column=0, columnspan=2, padx=10, pady=10, sticky="nsew")
        
        # 创建绘图区域
        self.fig, self.ax = plt.subplots(figsize=(8, 4))
        self.canvas = FigureCanvasTkAgg(self.fig, master=plot_frame)
        self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
        
        # 初始绘图
        self.update_plot()
    
    def create_button_section(self):
        button_frame = ttk.Frame(self.main_frame)
        button_frame.grid(row=2, column=0, columnspan=2, pady=10)
        
        ttk.Button(button_frame, text="导出尾翼DXF", command=self.export_dxf).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="保存偏离图", command=self.save_plot).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="重置参数", command=self.reset_parameters).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="退出", command=self.root.quit).pack(side=tk.RIGHT, padx=5)
    
    def calculate_stability(self):
        try:
            # 获取输入值(转换为米)
            L = self.length_var.get() / 100  # 厘米转米
            w_front = self.front_weight_var.get() / 1000  # 克转千克
            w_mid = self.mid_weight_var.get() / 1000      # 克转千克
            w_rear = self.rear_weight_var.get() / 1000    # 克转千克
            wind_speed = self.wind_speed_var.get()
            launch_angle = self.launch_angle_var.get()
            
            # 计算重心位置
            total_weight = w_front + w_mid + w_rear
            cg = (w_front * 0.2 * L + w_mid * 0.5 * L + w_rear * 0.8 * L) / total_weight
            
            # 计算压力中心 (简化模型)
            cp = L * 0.65  # 简化计算
            
            # 计算稳定性裕度
            stability_margin = (cp - cg) / L * 100  # 百分比
            
            # 计算风偏角
            wind_angle = np.arctan(wind_speed / 10) * 180 / np.pi  # 简化模型
            
            # 计算尾翼参数
            wing_position = L * (self.wing_position_var.get() / 100)
            
            # 获取尾翼尺寸(厘米)
            root_chord_cm = self.root_chord_var.get()
            tip_chord_cm = self.tip_chord_var.get()
            wing_span_cm = self.wing_span_var.get()
            
            # 显示结果(使用厘米单位)
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(tk.END, f"=== 火箭稳定性报告 ===\n\n")
            self.result_text.insert(tk.END, f"重心位置: {cg*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"压力中心: {cp*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"稳定性裕度: {stability_margin:.1f}%\n")
            
            # 稳定性评估
            if stability_margin < 5:
                self.result_text.insert(tk.END, " 警告: 稳定性不足! 火箭可能失控\n")
            elif stability_margin < 10:
                self.result_text.insert(tk.END, " 注意: 稳定性较低\n")
            else:
                self.result_text.insert(tk.END, " 稳定性良好\n")
                
            self.result_text.insert(tk.END, f"推荐尾翼位置: {L*0.7*100:.1f} - {L*0.9*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"风偏角: {wind_angle:.1f} 度\n")
            self.result_text.insert(tk.END, f"尾翼安装位置: {wing_position*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"尾翼尺寸: 根弦 {root_chord_cm:.1f} cm, ")
            self.result_text.insert(tk.END, f"尖弦 {tip_chord_cm:.1f} cm, ")
            self.result_text.insert(tk.END, f"翼展 {wing_span_cm:.1f} cm\n")
            
            # 更新尾翼示意图
            self.draw_wing()
            
            # 更新偏离图
            self.update_plot(stability_margin)
            
        except Exception as e:
            messagebox.showerror("计算错误", f"发生错误: {str(e)}")
    
    def draw_wing(self):
        # 清除画布
        self.wing_canvas.delete("all")
        
        # 获取尾翼参数(厘米)
        root_chord = self.root_chord_var.get() * 1.5  # 缩放以便显示
        tip_chord = self.tip_chord_var.get() * 1.5
        wing_span = self.wing_span_var.get() * 1.0
        shape = self.wing_shape_var.get()
        
        # 中心位置
        center_x, center_y = 100, 75
        
        # 根据形状绘制
        if shape == "矩形":
            points = [
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y + wing_span/2,
                center_x - root_chord/2, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightblue", outline="black")
        
        elif shape == "梯形":
            points = [
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y - wing_span/2,
                center_x + tip_chord/2, center_y + wing_span/2,
                center_x - tip_chord/2, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightgreen", outline="black")
        
        elif shape == "三角形":
            points = [
                center_x, center_y - wing_span/2,
                center_x + root_chord/2, center_y + wing_span/2,
                center_x - root_chord/2, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightyellow", outline="black")
        
        elif shape == "椭圆":
            self.wing_canvas.create_oval(
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y + wing_span/2,
                fill="lightpink", outline="black"
            )
        
        elif shape == "后掠":
            points = [
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/3, center_y - wing_span/2,
                center_x + tip_chord/2, center_y + wing_span/2,
                center_x - tip_chord/1.5, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightcyan", outline="black")
        
        # 添加标签
        self.wing_canvas.create_text(center_x, center_y - wing_span/2 - 15, 
                                   text=f"{self.wing_count_var.get()}片 {shape}尾翼")
    
    def update_plot(self, stability_margin=10.0):
        # 清除之前的绘图
        self.ax.clear()
        
        # 模拟轨迹数据
        launch_angle = np.radians(self.launch_angle_var.get())
        wind_speed = self.wind_speed_var.get()
        target_alt = self.target_altitude_var.get()
        
        # 简化的轨迹计算
        t = np.linspace(0, 100, 500)
        v0 = 150  # 初始速度 m/s
        g = 9.81  # 重力加速度
        
        # 考虑风偏的轨迹
        x = v0 * np.cos(launch_angle) * t + wind_speed * t**0.5
        y = v0 * np.sin(launch_angle) * t - 0.5 * g * t**2
        
        # 计算偏离角度(相对于垂直中心轴)
        # 避免除以零错误
        with np.errstate(divide='ignore', invalid='ignore'):
            deviation_angle = np.degrees(np.arctan(x / y))
        
        # 处理无效值(当y=0时)
        deviation_angle = np.nan_to_num(deviation_angle, nan=0.0, posinf=90.0, neginf=-90.0)
        
        # 找到最大高度点
        max_alt_idx = np.argmax(y)
        max_alt = y[max_alt_idx]
        max_dev_angle = deviation_angle[max_alt_idx]
        
        # 找到火箭落地时间点(高度<0)
        ground_idx = np.argmax(y < 0)
        if ground_idx == 0:  # 如果没有找到落地点
            ground_idx = len(y) - 1
        
        # 截取到落地前的数据
        t = t[:ground_idx]
        y = y[:ground_idx]
        deviation_angle = deviation_angle[:ground_idx]
        
        # 添加不稳定性影响
        stability_factor = max(0.1, min(1.0, stability_margin / 15.0))
        instability_factor = 1.0 / stability_factor
        
        # 当尾翼安装位置不当导致不稳定时,偏离角度会急剧增加
        deviation_angle = deviation_angle * instability_factor
        
        # 绘制偏离角度随高度的变化
        self.ax.plot(deviation_angle, y, 'b-', linewidth=2, label='飞行偏离角度')
        
        # 标记最大高度点
        if max_alt_idx < ground_idx:
            self.ax.plot(deviation_angle[max_alt_idx], max_alt, 'ro', 
                        label=f'最大高度: {max_alt:.0f}m\n偏离角度: {deviation_angle[max_alt_idx]:.1f}°')
        
        # 绘制目标高度线
        if max_alt > target_alt:
            self.ax.axhline(y=target_alt, color='g', linestyle='--', 
                           label=f'目标高度: {target_alt:.0f}m')
        else:
            self.ax.axhline(y=target_alt, color='r', linestyle='--', 
                           label=f'未达目标: {target_alt:.0f}m')
        
        # 绘制零米高度线
        self.ax.axhline(y=0, color='k', linestyle='-', linewidth=1, label='地面')
        
        # 添加不稳定警告
        if stability_margin < 5:
            self.ax.text(0.5, 0.5, "警告: 尾翼安装不当!\n火箭可能失控", 
                        transform=self.ax.transAxes, fontsize=14,
                        color='red', ha='center', va='center',
                        bbox=dict(facecolor='yellow', alpha=0.5))
        
        # 设置图形属性
        self.ax.set_title("火箭飞行偏离角度")
        self.ax.set_xlabel("偏离垂直中心轴角度 (°)")
        self.ax.set_ylabel("高度 (m)")
        self.ax.grid(True, linestyle='--', alpha=0.7)
        self.ax.legend()
        self.ax.set_ylim(0, max(1500, max_alt * 1.2))
        
        # 重绘画布
        self.canvas.draw()
    
    def export_dxf(self):
        file_path = filedialog.asksaveasfilename(
            defaultextension=".dxf",
            filetypes=[("DXF 文件", "*.dxf"), ("所有文件", "*.*")]
        )
        
        if not file_path:
            return
        
        try:
            # 创建DXF文件
            dwg = dxf.drawing(file_path)
            
            # 获取尾翼参数(厘米)
            shape = self.wing_shape_var.get()
            count = self.wing_count_var.get()
            root_chord = self.root_chord_var.get()
            tip_chord = self.tip_chord_var.get()
            wing_span = self.wing_span_var.get()
            
            # 添加尾翼形状(使用厘米单位)
            if shape == "矩形":
                points = [
                    (0, 0),
                    (root_chord, 0),
                    (root_chord, wing_span),
                    (0, wing_span),
                    (0, 0)
                ]
                dwg.add(dxf.polyline(points, layer='WING'))
            
            elif shape == "梯形":
                points = [
                    (0, 0),
                    (root_chord, 0),
                    (root_chord - (root_chord - tip_chord)/2, wing_span),
                    ((root_chord - tip_chord)/2, wing_span),
                    (0, 0)
                ]
                dwg.add(dxf.polyline(points, layer='WING'))
            
            elif shape == "三角形":
                points = [
                    (root_chord/2, 0),
                    (root_chord, wing_span),
                    (0, wing_span),
                    (root_chord/2, 0)
                ]
                dwg.add(dxf.polyline(points, layer='WING'))
            
            # 保存文件
            dwg.save()
            messagebox.showinfo("导出成功", f"尾翼设计已保存为 DXF 文件:\n{file_path}")
            
        except Exception as e:
            messagebox.showerror("导出错误", f"无法保存 DXF 文件: {str(e)}")
    
    def save_plot(self):
        file_path = filedialog.asksaveasfilename(
            defaultextension=".png",
            filetypes=[("PNG 图像", "*.png"), ("JPEG 图像", "*.jpg"), ("所有文件", "*.*")]
        )
        
        if not file_path:
            return
        
        try:
            self.fig.savefig(file_path, dpi=300)
            messagebox.showinfo("保存成功", f"偏离角度图已保存为:\n{file_path}")
        except Exception as e:
            messagebox.showerror("保存错误", f"无法保存图像: {str(e)}")
    
    def reset_parameters(self):
        # 重置所有输入变量
        self.length_var.set(500.0)  # 厘米
        self.front_weight_var.set(10000.0)  # 克
        self.mid_weight_var.set(20000.0)    # 克
        self.rear_weight_var.set(15000.0)   # 克
        self.wind_speed_var.set(5.0)
        self.launch_angle_var.set(45.0)
        self.target_altitude_var.set(1000.0)
        self.wing_shape_var.set("梯形")
        self.wing_count_var.set(4)
        self.root_chord_var.set(30.0)  # 厘米
        self.tip_chord_var.set(15.0)   # 厘米
        self.wing_span_var.set(40.0)   # 厘米
        self.wing_position_var.set(80.0)
        
        # 清除结果
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(tk.END, "参数已重置,请重新计算...")
        
        # 重绘图
        self.draw_wing()
        self.update_plot()

# 主程序
if __name__ == "__main__":
    root = tk.Tk()
    app = RocketStabilityCalculator(root)
    root.mainloop()

界面设计(很差)

V1.1

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import numpy as np
import dxfwrite
from dxfwrite import DXFEngine as dxf

class RocketStabilityCalculator:
    def __init__(self, root):
        self.root = root
        self.root.title("火箭尾翼稳定性计算器HSH编写")
        self.root.geometry("1400x800")  # 调整窗口尺寸
        
        # 输入变量
        self.length_var = tk.DoubleVar(value=500.0)  # 厘米
        self.front_weight_var = tk.DoubleVar(value=10000.0)  # 克
        self.mid_weight_var = tk.DoubleVar(value=20000.0)    # 克
        self.rear_weight_var = tk.DoubleVar(value=15000.0)   # 克
        self.wind_speed_var = tk.DoubleVar(value=5.0)
        self.launch_angle_var = tk.DoubleVar(value=45.0)
        self.target_altitude_var = tk.DoubleVar(value=1000.0)
        self.wing_shape_var = tk.StringVar(value="梯形")
        self.wing_count_var = tk.IntVar(value=4)
        self.root_chord_var = tk.DoubleVar(value=30.0)  # 厘米
        self.tip_chord_var = tk.DoubleVar(value=15.0)   # 厘米
        self.wing_span_var = tk.DoubleVar(value=40.0)   # 厘米
        self.wing_position_var = tk.DoubleVar(value=0.8)
        
        # 新增:最大高度估算参数
        self.water_velocity_var = tk.DoubleVar(value=30.0)  # 喷射水速度 v_e (m/s)
        self.drag_coeff_var = tk.DoubleVar(value=0.75)      # 阻力系数 C_d
        self.air_density_var = tk.DoubleVar(value=1.225)    # 空气密度 ρ (kg/m³)
        self.cross_area_var = tk.DoubleVar(value=0.0314)    # 火箭截面积 A (m²) - 直径20cm的圆
        self.initial_mass_var = tk.DoubleVar(value=45.0)    # 初始质量 m0 (kg)
        self.final_mass_var = tk.DoubleVar(value=25.0)      # 最终质量 m1 (kg)
        self.gravity_var = tk.DoubleVar(value=9.81)         # 重力加速度 g (m/s²)
        
        # 新增:火箭稳定性相关参数
        self.diameter_var = tk.DoubleVar(value=20.0)  # 火箭直径 (cm)
        self.nose_length_var = tk.DoubleVar(value=80.0)  # 鼻锥长度 (cm)
        self.nose_shape_var = tk.StringVar(value="锥形")  # 鼻锥形状
        
        # 创建主框架
        self.main_frame = ttk.Frame(root)
        self.main_frame.pack(fill=tk.BOTH, expand=True)
        
        # 配置网格权重
        self.main_frame.columnconfigure(0, weight=1)
        self.main_frame.columnconfigure(1, weight=1)
        self.main_frame.rowconfigure(0, weight=1)
        self.main_frame.rowconfigure(1, weight=0)
        self.main_frame.rowconfigure(2, weight=0)
        
        # 输入区域
        self.create_input_section()
        
        # 结果区域
        self.create_output_section()
        
        # 新增:最大高度计算区域(T区域)
        self.create_max_height_section()
        
        # 底部按钮
        self.create_button_section()
    
    def create_input_section(self):
        input_frame = ttk.LabelFrame(self.main_frame, text="火箭参数")
        input_frame.grid(row=0, column=0, padx=15, pady=15, sticky="nsew")
        
        # 调整输入框大小
        entry_width = 15
        
        # 火箭基本参数
        ttk.Label(input_frame, text="火箭总长 (cm):").grid(row=0, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.length_var, width=entry_width).grid(row=0, column=1, pady=3)
        
        ttk.Label(input_frame, text="火箭直径 (cm):").grid(row=1, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.diameter_var, width=entry_width).grid(row=1, column=1, pady=3)
        
        ttk.Label(input_frame, text="鼻锥长度 (cm):").grid(row=2, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.nose_length_var, width=entry_width).grid(row=2, column=1, pady=3)
        
        ttk.Label(input_frame, text="鼻锥形状:").grid(row=3, column=0, sticky="w", pady=3)
        nose_shape_combobox = ttk.Combobox(input_frame, textvariable=self.nose_shape_var, 
                                          values=["锥形", "抛物线形", "半球形", "尖锥形", "椭圆形"],
                                          width=entry_width-2)
        nose_shape_combobox.grid(row=3, column=1, pady=3)
        
        ttk.Label(input_frame, text="前段重量 (g):").grid(row=4, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.front_weight_var, width=entry_width).grid(row=4, column=1, pady=3)
        
        ttk.Label(input_frame, text="中段重量 (g):").grid(row=5, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.mid_weight_var, width=entry_width).grid(row=5, column=1, pady=3)
        
        ttk.Label(input_frame, text="后段重量 (g):").grid(row=6, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.rear_weight_var, width=entry_width).grid(row=6, column=1, pady=3)
        
        # 环境参数
        ttk.Label(input_frame, text="风速 (m/s):").grid(row=7, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.wind_speed_var, width=entry_width).grid(row=7, column=1, pady=3)
        
        ttk.Label(input_frame, text="发射角度 (度):").grid(row=8, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.launch_angle_var, width=entry_width).grid(row=8, column=1, pady=3)
        
        ttk.Label(input_frame, text="目标高度 (m):").grid(row=9, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.target_altitude_var, width=entry_width).grid(row=9, column=1, pady=3)
        
        # 尾翼参数
        ttk.Label(input_frame, text="尾翼形状:").grid(row=10, column=0, sticky="w", pady=3)
        shape_combobox = ttk.Combobox(input_frame, textvariable=self.wing_shape_var, 
                                    values=["矩形", "梯形", "三角形", "椭圆", "后掠"],
                                    width=entry_width-2)
        shape_combobox.grid(row=10, column=1, pady=3)
        
        ttk.Label(input_frame, text="尾翼数量:").grid(row=11, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.wing_count_var, width=entry_width).grid(row=11, column=1, pady=3)
        
        ttk.Label(input_frame, text="根部弦长 (cm):").grid(row=12, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.root_chord_var, width=entry_width).grid(row=12, column=1, pady=3)
        
        ttk.Label(input_frame, text="尖部弦长 (cm):").grid(row=13, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.tip_chord_var, width=entry_width).grid(row=13, column=1, pady=3)
        
        ttk.Label(input_frame, text="翼展 (cm):").grid(row=14, column=0, sticky="w", pady=3)
        ttk.Entry(input_frame, textvariable=self.wing_span_var, width=entry_width).grid(row=14, column=1, pady=3)
        
        ttk.Label(input_frame, text="安装位置 (%):").grid(row=15, column=0, sticky="w", pady=3)
        ttk.Scale(input_frame, from_=0, to=100, variable=self.wing_position_var, 
                 orient=tk.HORIZONTAL, length=180).grid(row=15, column=1, pady=3)
        
        # 计算按钮
        ttk.Button(input_frame, text="计算稳定性", command=self.calculate_stability, 
                  width=20).grid(row=16, column=0, columnspan=2, pady=15)
    
    def create_output_section(self):
        output_frame = ttk.LabelFrame(self.main_frame, text="计算结果")
        output_frame.grid(row=0, column=1, padx=15, pady=15, sticky="nsew")
        
        # 结果文本区域 - 增大尺寸
        self.result_text = tk.Text(output_frame, height=28, width=60, font=("宋体", 10))
        scrollbar = ttk.Scrollbar(output_frame, command=self.result_text.yview)
        self.result_text.config(yscrollcommand=scrollbar.set)
        
        self.result_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=5)
        
        self.result_text.insert(tk.END, "计算结果将显示在这里...")
        
        # 尾翼示意图框架
        wing_frame = ttk.LabelFrame(output_frame, text="尾翼示意图")
        wing_frame.pack(fill=tk.BOTH, expand=True, padx=5, pady=5)
        
        # 尾翼示意图
        self.wing_canvas = tk.Canvas(wing_frame, width=300, height=200, bg="white", highlightthickness=1, highlightbackground="gray")
        self.wing_canvas.pack(pady=10)
    
    def create_max_height_section(self):
        """创建最大高度计算区域(T区域)"""
        height_frame = ttk.LabelFrame(self.main_frame, text="最大高度估算(含阻力)")
        height_frame.grid(row=1, column=0, columnspan=2, padx=15, pady=10, sticky="ew")
        
        # 调整输入框大小
        entry_width = 12
        
        # 使用网格布局
        row = 0
        
        # 第一行
        ttk.Label(height_frame, text="喷射水速度 v_e (m/s):").grid(row=row, column=0, sticky="w", padx=8, pady=4)
        ttk.Entry(height_frame, textvariable=self.water_velocity_var, width=entry_width).grid(row=row, column=1, padx=8, pady=4)
        
        ttk.Label(height_frame, text="阻力系数 C_d:").grid(row=row, column=2, sticky="w", padx=8, pady=4)
        ttk.Entry(height_frame, textvariable=self.drag_coeff_var, width=entry_width).grid(row=row, column=3, padx=8, pady=4)
        
        ttk.Label(height_frame, text="空气密度 ρ (kg/m³):").grid(row=row, column=4, sticky="w", padx=8, pady=4)
        ttk.Entry(height_frame, textvariable=self.air_density_var, width=entry_width).grid(row=row, column=5, padx=8, pady=4)
        
        row += 1
        
        # 第二行
        ttk.Label(height_frame, text="火箭截面积 A (m²):").grid(row=row, column=0, sticky="w", padx=8, pady=4)
        ttk.Entry(height_frame, textvariable=self.cross_area_var, width=entry_width).grid(row=row, column=1, padx=8, pady=4)
        
        ttk.Label(height_frame, text="初始质量 m0 (kg):").grid(row=row, column=2, sticky="w", padx=8, pady=4)
        ttk.Entry(height_frame, textvariable=self.initial_mass_var, width=entry_width).grid(row=row, column=3, padx=8, pady=4)
        
        ttk.Label(height_frame, text="最终质量 m1 (kg):").grid(row=row, column=4, sticky="w", padx=8, pady=4)
        ttk.Entry(height_frame, textvariable=self.final_mass_var, width=entry_width).grid(row=row, column=5, padx=8, pady=4)
        
        row += 1
        
        # 第三行
        ttk.Label(height_frame, text="重力加速度 g (m/s²):").grid(row=row, column=0, sticky="w", padx=8, pady=4)
        ttk.Entry(height_frame, textvariable=self.gravity_var, width=entry_width).grid(row=row, column=1, padx=8, pady=4)
        
        # 计算按钮
        ttk.Button(height_frame, text="计算最大高度", command=self.calculate_max_height, 
                  width=15).grid(row=row, column=2, padx=30, pady=4)
        
        # 结果显示
        self.height_result_label = ttk.Label(height_frame, text="最大高度: 未计算", 
                                            font=("", 11, "bold"), foreground="blue")
        self.height_result_label.grid(row=row, column=3, columnspan=3, padx=8, pady=4, sticky="w")
        
        # 添加公式说明
        formula_label = ttk.Label(height_frame, 
                                 text="使用公式: h_max ≈ (v_e²/(2g)) * (1/(1+(C_d*ρ*A)/(2mg))) * ln(m0/m1)", 
                                 font=("", 9), foreground="darkgreen")
        formula_label.grid(row=row+1, column=0, columnspan=6, pady=8, sticky="w")
    
    def create_button_section(self):
        button_frame = ttk.Frame(self.main_frame)
        button_frame.grid(row=2, column=0, columnspan=2, pady=15)
        
        ttk.Button(button_frame, text="导出尾翼DXF", command=self.export_dxf, 
                  width=15).pack(side=tk.LEFT, padx=10)
        ttk.Button(button_frame, text="重置参数", command=self.reset_parameters, 
                  width=15).pack(side=tk.LEFT, padx=10)
        ttk.Button(button_frame, text="关于", command=self.show_about, 
                  width=15).pack(side=tk.RIGHT, padx=10)
    
    def show_about(self):
        """显示关于信息弹窗"""
        about_text = """
火箭尾翼稳定性计算器

版本: V1.1
作者: HSH

注意事项:
1. 计算结果仅供参考,实际设计需进行实物测试
2. 建议在安全环境下进行火箭发射实验
3. 遵守当地法律法规和安全规定

联系方式: 如有问题或建议,请联系开发者
HSH0730@126.com

GitHub项目链接:
https://github.com/HSHSpaceX/Rocket-tail-fin-stability-calculator
欢迎各位一同开发

更新日志:
v1.1: 优化稳定性计算,增加鼻锥参数,水火箭发射高度
v1.0: 基础计算
    """    
        # 创建自定义弹窗
        about_window = tk.Toplevel(self.root)
        about_window.title("关于 ")
        about_window.geometry("500x600")
        about_window.resizable(False, False)
        
        # 设置弹窗图标和位置
        about_window.transient(self.root)
        about_window.grab_set()
        
        # 中心显示
        window_width = 500
        window_height = 600
        screen_width = about_window.winfo_screenwidth()
        screen_height = about_window.winfo_screenheight()
        x = (screen_width - window_width) // 2
        y = (screen_height - window_height) // 2
        about_window.geometry(f"{window_width}x{window_height}+{x}+{y}")
        
        # 创建标题标签
        title_label = tk.Label(about_window, text="火箭尾翼稳定性计算器", 
                              font=("微软雅黑", 16, "bold"))
        title_label.pack(pady=15)
        
        # 创建副标题
        subtitle_label = tk.Label(about_window, text="版本V1.1", 
                                 font=("微软雅黑", 12))
        subtitle_label.pack(pady=5)
        
        # 创建分隔线
        separator = ttk.Separator(about_window, orient='horizontal')
        separator.pack(fill='x', padx=20, pady=10)
        
        # 创建文本框架
        text_frame = tk.Frame(about_window)
        text_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
        
        # 创建文本区域
        about_text_widget = tk.Text(text_frame, wrap=tk.WORD, font=("微软雅黑", 10))
        about_text_widget.insert(tk.END, about_text)
        about_text_widget.config(state=tk.DISABLED)  # 设置为只读
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(text_frame, command=about_text_widget.yview)
        about_text_widget.config(yscrollcommand=scrollbar.set)
        
        about_text_widget.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 创建关闭按钮
        close_button = ttk.Button(about_window, text="关闭", 
                                 command=about_window.destroy, width=20)
        close_button.pack(pady=20)
        
        # 绑定ESC键关闭窗口
        about_window.bind('<Escape>', lambda e: about_window.destroy())
    
    def calculate_max_height(self):
        """计算含阻力的最大高度"""
        try:
            # 获取输入值
            v_e = self.water_velocity_var.get()
            C_d = self.drag_coeff_var.get()
            rho = self.air_density_var.get()
            A = self.cross_area_var.get()
            m0 = self.initial_mass_var.get()
            m1 = self.final_mass_var.get()
            g = self.gravity_var.get()
            
            # 计算质量比
            mass_ratio = m0 / m1
            if mass_ratio <= 1:
                raise ValueError("初始质量必须大于最终质量")
            
            # 计算阻力系数
            resistance_factor = 1 + (C_d * rho * A) / (2 * m0 * g)
            
            # 计算最大高度(使用公式)
            h_max = (v_e**2 / (2 * g)) * (1 / resistance_factor) * np.log(mass_ratio)
            
            # 更新结果标签
            self.height_result_label.config(text=f"最大高度: {h_max:.2f} m")
            
            # 在结果文本框中显示
            self.result_text.insert(tk.END, f"\n\n=== 最大高度估算 ===\n")
            self.result_text.insert(tk.END, f"计算最大高度: {h_max:.2f} m\n")
            self.result_text.insert(tk.END, f"喷射水速度: {v_e:.1f} m/s\n")
            self.result_text.insert(tk.END, f"阻力系数: {C_d:.3f}\n")
            self.result_text.insert(tk.END, f"空气密度: {rho:.3f} kg/m³\n")
            self.result_text.insert(tk.END, f"火箭截面积: {A:.4f} m²\n")
            self.result_text.insert(tk.END, f"初始质量: {m0:.1f} kg\n")
            self.result_text.insert(tk.END, f"最终质量: {m1:.1f} kg\n")
            self.result_text.insert(tk.END, f"重力加速度: {g:.2f} m/s²\n")
            self.result_text.insert(tk.END, f"质量比: {mass_ratio:.3f}\n")
            self.result_text.insert(tk.END, f"阻力因子: {resistance_factor:.3f}\n")
            self.result_text.see(tk.END)  # 滚动到最新内容
            
            return h_max
            
        except ValueError as ve:
            messagebox.showerror("输入错误", f"参数错误: {str(ve)}")
        except Exception as e:
            messagebox.showerror("计算错误", f"计算最大高度时发生错误: {str(e)}")
    
    def calculate_stability(self):
        """优化后的稳定性计算"""
        try:
            # 获取输入值(转换为米)
            L = self.length_var.get() / 100  # 厘米转米
            D = self.diameter_var.get() / 100  # 厘米转米
            nose_length = self.nose_length_var.get() / 100  # 厘米转米
            nose_shape = self.nose_shape_var.get()
            
            # 质量转换
            w_front = self.front_weight_var.get() / 1000  # 克转千克
            w_mid = self.mid_weight_var.get() / 1000      # 克转千克
            w_rear = self.rear_weight_var.get() / 1000    # 克转千克
            
            wind_speed = self.wind_speed_var.get()
            launch_angle = self.launch_angle_var.get()
            
            # 计算总质量
            total_weight = w_front + w_mid + w_rear
            
            # 优化重心计算 - 考虑鼻锥和分段质量分布
            # 假设质量分布更加均匀
            front_position = nose_length / 2  # 鼻锥质量集中在鼻锥中部
            mid_position = nose_length + (L - nose_length) * 0.5  # 中部质量均匀分布
            rear_position = L * 0.85  # 后部质量集中在后段
            
            # 计算重心位置
            cg = (w_front * front_position + w_mid * mid_position + w_rear * rear_position) / total_weight
            
            # 计算压力中心 (改进模型)
            # 考虑鼻锥形状的影响
            nose_shape_factor = self.get_nose_shape_factor(nose_shape)
            
            # 计算尾翼参数
            wing_position = L * (self.wing_position_var.get() / 100)
            wing_count = self.wing_count_var.get()
            root_chord_cm = self.root_chord_var.get() / 100  # 转米
            tip_chord_cm = self.tip_chord_var.get() / 100    # 转米
            wing_span_cm = self.wing_span_var.get() / 100    # 转米
            
            # 计算尾翼面积
            if self.wing_shape_var.get() == "梯形":
                wing_area = (root_chord_cm + tip_chord_cm) * wing_span_cm / 2
            elif self.wing_shape_var.get() == "三角形":
                wing_area = root_chord_cm * wing_span_cm / 2
            elif self.wing_shape_var.get() == "矩形":
                wing_area = root_chord_cm * wing_span_cm
            else:
                # 近似为梯形
                wing_area = (root_chord_cm + tip_chord_cm) * wing_span_cm / 2
            
            total_wing_area = wing_area * wing_count
            
            # 计算火箭体侧面积
            body_length = L - nose_length
            body_side_area = np.pi * D * body_length
            
            # 计算鼻锥压力中心
            nose_cp_distance = nose_length * nose_shape_factor
            
            # 计算箭体压力中心
            body_cp_distance = nose_length + body_length * 0.5
            
            # 计算尾翼压力中心
            wing_cp_distance = wing_position + root_chord_cm * 0.25  # 假设压力中心在弦长的25%处
            
            # 计算综合压力中心 (面积加权平均)
            total_area = nose_length * D + body_side_area + total_wing_area
            
            # 简化计算
            if total_area > 0:
                cp = (nose_length * D * nose_cp_distance + 
                      body_side_area * body_cp_distance + 
                      total_wing_area * wing_cp_distance) / total_area
            else:
                cp = L * 0.6  # 默认值
            
            # 确保压力中心在重心之后
            if cp <= cg:
                cp = cg + D * 1.5  # 确保至少1.5倍直径的稳定性裕度
            
            # 计算稳定性裕度 (更精确的计算)
            stability_margin_cal = (cp - cg) / D  # 以火箭直径为单位
            
            # 计算稳定性裕度百分比
            stability_margin_percent = (cp - cg) / L * 100
            
            # 计算风偏角 (改进模型)
            air_density = 1.225  # kg/m³
            cross_area = np.pi * (D/2)**2
            
            # 计算动压
            dynamic_pressure = 0.5 * air_density * wind_speed**2
            
            # 计算侧向力
            side_force = dynamic_pressure * cross_area * 1.2  # 假设阻力系数1.2
            
            # 计算侧向力矩
            side_moment = side_force * (cp - cg)
            
            # 计算恢复力矩 (重力矩)
            g = 9.81  # m/s²
            weight_force = total_weight * g
            tilt_angle_rad = np.radians(5)  # 假设5度倾斜
            restoring_moment = weight_force * (cp - cg) * np.sin(tilt_angle_rad)
            
            # 计算稳定性比率
            if side_moment > 0:
                stability_ratio = restoring_moment / side_moment
            else:
                stability_ratio = 999  # 极大值
            
            # 获取尾翼尺寸(厘米)
            root_chord_cm_display = self.root_chord_var.get()
            tip_chord_cm_display = self.tip_chord_var.get()
            wing_span_cm_display = self.wing_span_var.get()
            
            # 显示结果(使用厘米单位)
            self.result_text.delete(1.0, tk.END)
            self.result_text.insert(tk.END, f"=== 火箭稳定性分析报告 ===\n\n")
            self.result_text.insert(tk.END, f"【基本参数】\n")
            self.result_text.insert(tk.END, f"火箭总长: {L*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"火箭直径: {D*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"鼻锥长度: {nose_length*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"鼻锥形状: {nose_shape}\n")
            self.result_text.insert(tk.END, f"总质量: {total_weight:.2f} kg\n\n")
            
            self.result_text.insert(tk.END, f"【重心与压力中心】\n")
            self.result_text.insert(tk.END, f"重心位置: {cg*100:.1f} cm (距鼻锥顶端)\n")
            self.result_text.insert(tk.END, f"压力中心: {cp*100:.1f} cm (距鼻锥顶端)\n")
            self.result_text.insert(tk.END, f"重心与压力中心距离: {(cp-cg)*100:.1f} cm\n\n")
            
            self.result_text.insert(tk.END, f"【稳定性分析】\n")
            self.result_text.insert(tk.END, f"稳定性裕度: {stability_margin_cal:.2f} 倍直径\n")
            self.result_text.insert(tk.END, f"稳定性裕度百分比: {stability_margin_percent:.1f}%\n")
            
            # 详细稳定性评估
            self.result_text.insert(tk.END, f"\n【稳定性评估】\n")
            if stability_margin_cal < 1.0:
                self.result_text.insert(tk.END, f"⚠️ 警告: 稳定性严重不足! 火箭很可能失控\n")
                self.result_text.insert(tk.END, f"   建议: 增加尾翼面积或向前移动重心\n")
            elif stability_margin_cal < 1.5:
                self.result_text.insert(tk.END, f"⚠️ 注意: 稳定性较低\n")
                self.result_text.insert(tk.END, f"   建议: 适当增加尾翼尺寸或调整重心\n")
            elif stability_margin_cal < 2.0:
                self.result_text.insert(tk.END, f"✓ 稳定性良好\n")
                self.result_text.insert(tk.END, f"   火箭飞行稳定\n")
            else:
                self.result_text.insert(tk.END, f"✓ 稳定性优秀\n")
                self.result_text.insert(tk.END, f"   火箭飞行非常稳定\n")
            
            self.result_text.insert(tk.END, f"\n【风偏影响分析】\n")
            self.result_text.insert(tk.END, f"风速: {wind_speed:.1f} m/s\n")
            self.result_text.insert(tk.END, f"侧向力矩: {side_moment:.2f} N·m\n")
            self.result_text.insert(tk.END, f"恢复力矩: {restoring_moment:.2f} N·m\n")
            self.result_text.insert(tk.END, f"稳定性比率: {stability_ratio:.2f}\n")
            
            if stability_ratio > 3.0:
                self.result_text.insert(tk.END, f"   抗风能力: 优秀\n")
            elif stability_ratio > 1.5:
                self.result_text.insert(tk.END, f"   抗风能力: 良好\n")
            else:
                self.result_text.insert(tk.END, f"   抗风能力: 较弱\n")
            
            self.result_text.insert(tk.END, f"\n【尾翼参数】\n")
            self.result_text.insert(tk.END, f"尾翼形状: {self.wing_shape_var.get()}\n")
            self.result_text.insert(tk.END, f"尾翼数量: {wing_count}片\n")
            self.result_text.insert(tk.END, f"单翼面积: {wing_area*10000:.1f} cm²\n")
            self.result_text.insert(tk.END, f"总翼面积: {total_wing_area*10000:.1f} cm²\n")
            self.result_text.insert(tk.END, f"翼面积与箭体侧面积比: {total_wing_area/body_side_area:.3f}\n")
            self.result_text.insert(tk.END, f"推荐尾翼位置: {L*0.7*100:.1f} - {L*0.85*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"实际安装位置: {wing_position*100:.1f} cm\n")
            self.result_text.insert(tk.END, f"根部弦长: {root_chord_cm_display:.1f} cm\n")
            self.result_text.insert(tk.END, f"尖部弦长: {tip_chord_cm_display:.1f} cm\n")
            self.result_text.insert(tk.END, f"翼展: {wing_span_cm_display:.1f} cm\n")
            
            # 尾翼建议
            self.result_text.insert(tk.END, f"\n【设计建议】\n")
            if total_wing_area/body_side_area < 0.05:
                self.result_text.insert(tk.END, f"建议: 增加尾翼面积,当前面积偏小\n")
            elif total_wing_area/body_side_area > 0.15:
                self.result_text.insert(tk.END, f"建议: 尾翼面积足够,可考虑优化形状\n")
            else:
                self.result_text.insert(tk.END, f"建议: 尾翼面积适中\n")
            
            # 更新尾翼示意图
            self.draw_wing()
            
            # 自动计算最大高度
            if hasattr(self, 'calculated_max_height'):
                self.height_result_label.config(text=f"最大高度: {self.calculated_max_height:.2f} m")
            
        except Exception as e:
            messagebox.showerror("计算错误", f"发生错误: {str(e)}")
    
    def get_nose_shape_factor(self, nose_shape):
        """获取鼻锥形状因子"""
        factors = {
            "锥形": 0.66,      # 圆锥形鼻锥的压力中心在2/3处
            "抛物线形": 0.50,  # 抛物线形鼻锥的压力中心在1/2处
            "半球形": 0.42,    # 半球形鼻锥的压力中心在0.42处
            "尖锥形": 0.75,    # 尖锥形鼻锥的压力中心在3/4处
            "椭圆形": 0.44     # 椭圆形鼻锥的压力中心在0.44处
        }
        return factors.get(nose_shape, 0.66)
    
    def draw_wing(self):
        # 清除画布
        self.wing_canvas.delete("all")
        
        # 获取尾翼参数(厘米)
        root_chord = self.root_chord_var.get() * 2  # 缩放以便显示
        tip_chord = self.tip_chord_var.get() * 2
        wing_span = self.wing_span_var.get() * 1.5
        shape = self.wing_shape_var.get()
        
        # 中心位置
        center_x, center_y = 150, 100
        
        # 根据形状绘制
        if shape == "矩形":
            points = [
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y + wing_span/2,
                center_x - root_chord/2, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightblue", outline="black", width=2)
        
        elif shape == "梯形":
            points = [
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y - wing_span/2,
                center_x + tip_chord/2, center_y + wing_span/2,
                center_x - tip_chord/2, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightgreen", outline="black", width=2)
        
        elif shape == "三角形":
            points = [
                center_x, center_y - wing_span/2,
                center_x + root_chord/2, center_y + wing_span/2,
                center_x - root_chord/2, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightyellow", outline="black", width=2)
        
        elif shape == "椭圆":
            self.wing_canvas.create_oval(
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/2, center_y + wing_span/2,
                fill="lightpink", outline="black", width=2
            )
        
        elif shape == "后掠":
            points = [
                center_x - root_chord/2, center_y - wing_span/2,
                center_x + root_chord/3, center_y - wing_span/2,
                center_x + tip_chord/2, center_y + wing_span/2,
                center_x - tip_chord/1.5, center_y + wing_span/2
            ]
            self.wing_canvas.create_polygon(points, fill="lightcyan", outline="black", width=2)
        
        # 添加标签
        self.wing_canvas.create_text(center_x, center_y - wing_span/2 - 25, 
                                   text=f"{self.wing_count_var.get()}片 {shape}尾翼",
                                   font=("Arial", 11, "bold"))
        
        # 添加尺寸标注
        self.wing_canvas.create_line(center_x - root_chord/2, center_y - wing_span/2 - 10,
                                   center_x + root_chord/2, center_y - wing_span/2 - 10,
                                   fill="red", width=2)
        self.wing_canvas.create_text(center_x, center_y - wing_span/2 - 20, 
                                   text=f"根弦: {self.root_chord_var.get()}cm",
                                   font=("Arial", 9), fill="red")
        
        self.wing_canvas.create_line(center_x - root_chord/2 - 10, center_y - wing_span/2,
                                   center_x - root_chord/2 - 10, center_y + wing_span/2,
                                   fill="blue", width=2)
        self.wing_canvas.create_text(center_x - root_chord/2 - 20, center_y, 
                                   text=f"翼展: {self.wing_span_var.get()}cm",
                                   font=("Arial", 9), fill="blue", angle=90)
    
    def export_dxf(self):
        file_path = filedialog.asksaveasfilename(
            defaultextension=".dxf",
            filetypes=[("DXF 文件", "*.dxf"), ("所有文件", "*.*")]
        )
        
        if not file_path:
            return
        
        try:
            # 创建DXF文件
            dwg = dxf.drawing(file_path)
            
            # 获取尾翼参数(厘米)
            shape = self.wing_shape_var.get()
            count = self.wing_count_var.get()
            root_chord = self.root_chord_var.get()
            tip_chord = self.tip_chord_var.get()
            wing_span = self.wing_span_var.get()
            
            # 添加尾翼形状(使用厘米单位)
            if shape == "矩形":
                points = [
                    (0, 0),
                    (root_chord, 0),
                    (root_chord, wing_span),
                    (0, wing_span),
                    (0, 0)
                ]
                dwg.add(dxf.polyline(points, layer='WING'))
            
            elif shape == "梯形":
                points = [
                    (0, 0),
                    (root_chord, 0),
                    (root_chord - (root_chord - tip_chord)/2, wing_span),
                    ((root_chord - tip_chord)/2, wing_span),
                    (0, 0)
                ]
                dwg.add(dxf.polyline(points, layer='WING'))
            
            elif shape == "三角形":
                points = [
                    (root_chord/2, 0),
                    (root_chord, wing_span),
                    (0, wing_span),
                    (root_chord/2, 0)
                ]
                dwg.add(dxf.polyline(points, layer='WING'))
            
            # 保存文件
            dwg.save()
            messagebox.showinfo("导出成功", f"尾翼设计已保存为 DXF 文件:\n{file_path}")
            
        except Exception as e:
            messagebox.showerror("导出错误", f"无法保存 DXF 文件: {str(e)}")
    
    def reset_parameters(self):
        # 重置所有输入变量
        self.length_var.set(500.0)  # 厘米
        self.diameter_var.set(20.0)  # 厘米
        self.nose_length_var.set(80.0)  # 厘米
        self.nose_shape_var.set("锥形")
        self.front_weight_var.set(10000.0)  # 克
        self.mid_weight_var.set(20000.0)    # 克
        self.rear_weight_var.set(15000.0)   # 克
        self.wind_speed_var.set(5.0)
        self.launch_angle_var.set(45.0)
        self.target_altitude_var.set(1000.0)
        self.wing_shape_var.set("梯形")
        self.wing_count_var.set(4)
        self.root_chord_var.set(30.0)  # 厘米
        self.tip_chord_var.set(15.0)   # 厘米
        self.wing_span_var.set(40.0)   # 厘米
        self.wing_position_var.set(80.0)
        
        # 重置最大高度参数
        self.water_velocity_var.set(30.0)
        self.drag_coeff_var.set(0.75)
        self.air_density_var.set(1.225)
        self.cross_area_var.set(0.0314)
        self.initial_mass_var.set(45.0)
        self.final_mass_var.set(25.0)
        self.gravity_var.set(9.81)
        
        # 清除结果
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(tk.END, "参数已重置,请重新计算...")
        
        # 重置高度结果
        self.height_result_label.config(text="最大高度: 未计算")
        if hasattr(self, 'calculated_max_height'):
            del self.calculated_max_height
        
        # 重绘图
        self.draw_wing()

# 主程序
if __name__ == "__main__":
    root = tk.Tk()
    app = RocketStabilityCalculator(root)
    root.mainloop()

界面设计也好了不少

今天就写着欢迎后续共同开发

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐