明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 542|回复: 5

隧道断面数据复核计算

[复制链接]
发表于 2025-10-20 19:21:52 | 显示全部楼层 |阅读模式
import tkinter as tk
import math
from tkinter import ttk, messagebox

class SurveyCalculator:
    def __init__(self, root):
        self.root = root
        self.root.title("隧道断面数据复核计算")
        self.root.geometry("950x750")
        self.root.configure(bg='#f0f0f0')

        # 设置样式
        self.setup_styles()

        self.main_frame = ttk.Frame(root, style='Main.TFrame')
        self.main_frame.pack(fill="both", expand=True, padx=15, pady=15)

        self.setup_main_interface()

    def setup_styles(self):
        style = ttk.Style()
        style.configure('Main.TFrame', background='#f0f0f0')
        style.configure('Title.TLabel', background='#f0f0f0', font=('微软雅黑', 10, 'bold'))
        style.configure('Card.TFrame', background='white', relief='raised', borderwidth=1)

    def setup_main_interface(self):
        # 基础参数输入区域
        param_frame = tk.Frame(self.main_frame, bg='white', relief='raised', bd=1)
        param_frame.pack(fill="x", pady=(0, 10))

        # 标题栏
        title_frame = tk.Frame(param_frame, bg='#2c3e50', height=30)
        title_frame.pack(fill="x", pady=(0, 10))
        title_frame.pack_propagate(False)
        tk.Label(title_frame, text="基础参数", bg='#2c3e50', fg='white',
                font=('微软雅黑', 10, 'bold')).pack(side="left", padx=10)

        # 测设点和圆心输入
        input_control_frame = tk.Frame(param_frame, bg='white')
        input_control_frame.pack(fill="x", padx=15, pady=8)

        btn_frame = tk.Frame(input_control_frame, bg='white')
        btn_frame.pack(fill="x")

        tk.Button(btn_frame, text="📋 粘贴", command=self.paste_station_data,
                 bg='#3498db', fg='white', font=('微软雅黑', 9), width=8, height=1).pack(side="left", padx=2)
        tk.Button(btn_frame, text="🗑️ 清空", command=self.clear_station_data,
                 bg='#e74c3c', fg='white', font=('微软雅黑', 9), width=8, height=1).pack(side="left", padx=2)

        self.station_center_entry = tk.Text(param_frame, height=2, width=80, font=('Consolas', 9),
                                           bg='#f8f9fa', relief='solid', bd=1)
        self.station_center_entry.pack(fill="x", padx=15, pady=(0, 10))

        # 参数配置
        config_frame = tk.Frame(param_frame, bg='white')
        config_frame.pack(fill="x", padx=15, pady=10)

        # 第一行配置
        config_row1 = tk.Frame(config_frame, bg='white')
        config_row1.pack(fill="x", pady=2)

        tk.Label(config_row1, text="位置:", bg='white', font=('微软雅黑', 9)).pack(side="left", padx=5)
        self.center_position = tk.StringVar(value="left")
        tk.Radiobutton(config_row1, text="左幅", variable=self.center_position, value="left",
                      bg='white', font=('微软雅黑', 9)).pack(side="left", padx=2)
        tk.Radiobutton(config_row1, text="右幅", variable=self.center_position, value="right",
                      bg='white', font=('微软雅黑', 9)).pack(side="left", padx=2)

        tk.Label(config_row1, text="高差参数:", bg='white', font=('微软雅黑', 9)).pack(side="left", padx=(20,5))
        self.height_param = tk.Entry(config_row1, width=8, font=('微软雅黑', 9), justify='center',
                                   bg='#f8f9fa', relief='solid', bd=1)
        self.height_param.insert(0, "1.61")
        self.height_param.pack(side="left", padx=5)

        tk.Label(config_row1, text="半径:", bg='white', font=('微软雅黑', 9)).pack(side="left", padx=(20,5))
        self.radius_entry = tk.Entry(config_row1, width=8, font=('微软雅黑', 9), justify='center',
                                   bg='#f8f9fa', relief='solid', bd=1)
        self.radius_entry.insert(0, "5.5")
        self.radius_entry.pack(side="left", padx=5)

        # 计算类型选择
        type_frame = tk.Frame(param_frame, bg='white')
        type_frame.pack(fill="x", padx=15, pady=(5, 10))

        self.calc_type = tk.StringVar(value="coord_to_offset")

        type_buttons = [
            ("📍 坐标→偏距高差", "coord_to_offset", "#27ae60"),
            ("📐 偏距高差→坐标", "offset_to_coord", "#e67e22"),
            ("🎯 实际→设计坐标", "actual_to_design", "#9b59b6")
        ]

        for text, value, color in type_buttons:
            tk.Radiobutton(type_frame, text=text, variable=self.calc_type, value=value,
                          bg='white', font=('微软雅黑', 9), selectcolor=color,
                          activebackground='white').pack(side="left", padx=8)

        # 数据输入和输出区域容器
        data_frame = tk.Frame(self.main_frame, bg='#f0f0f0')
        data_frame.pack(fill="both", expand=True, pady=(0, 10))

        # 数据输入区域
        input_frame = tk.Frame(data_frame, bg='white', relief='raised', bd=1)
        input_frame.pack(side="left", fill="both", expand=True, padx=(0, 5))

        # 输入标题栏
        input_title_frame = tk.Frame(input_frame, bg='#34495e', height=30)
        input_title_frame.pack(fill="x", pady=(0, 8))
        input_title_frame.pack_propagate(False)
        tk.Label(input_title_frame, text="数据输入", bg='#34495e', fg='white',
                font=('微软雅黑', 10, 'bold')).pack(side="left", padx=10)

        input_btn_frame = tk.Frame(input_frame, bg='white')
        input_btn_frame.pack(fill="x", padx=10, pady=(0, 8))

        tk.Button(input_btn_frame, text="📋 粘贴", command=self.paste_data,
                 bg='#3498db', fg='white', font=('微软雅黑', 9), width=8).pack(side="left", padx=2)
        tk.Button(input_btn_frame, text="🗑️ 清空", command=self.clear_input,
                 bg='#e74c3c', fg='white', font=('微软雅黑', 9), width=8).pack(side="left", padx=2)

        self.input_text = tk.Text(input_frame, height=20, wrap="none", font=("Consolas", 9),
                                 bg='#f8f9fa', relief='solid', bd=1)
        input_scrollbar = tk.Scrollbar(input_frame, command=self.input_text.yview)
        self.input_text.config(yscrollcommand=input_scrollbar.set)

        self.input_text.pack(side="left", fill="both", expand=True, padx=(10, 0), pady=(0, 10))
        input_scrollbar.pack(side="right", fill="y", padx=(0, 10), pady=(0, 10))

        # 结果显示区域
        output_frame = tk.Frame(data_frame, bg='white', relief='raised', bd=1)
        output_frame.pack(side="right", fill="both", expand=True, padx=(5, 0))

        # 输出标题栏
        output_title_frame = tk.Frame(output_frame, bg='#27ae60', height=30)
        output_title_frame.pack(fill="x", pady=(0, 8))
        output_title_frame.pack_propagate(False)
        tk.Label(output_title_frame, text="计算结果", bg='#27ae60', fg='white',
                font=('微软雅黑', 10, 'bold')).pack(side="left", padx=10)

        output_btn_frame = tk.Frame(output_frame, bg='white')
        output_btn_frame.pack(fill="x", padx=10, pady=(0, 8))

        tk.Button(output_btn_frame, text="🗑️ 清空", command=self.clear_output,
                 bg='#e74c3c', fg='white', font=('微软雅黑', 9), width=8).pack(side="left", padx=2)

        self.output_text = tk.Text(output_frame, height=20, wrap="none", font=("Consolas", 9),
                                  bg='#f8f9fa', relief='solid', bd=1)
        output_scrollbar = tk.Scrollbar(output_frame, command=self.output_text.yview)
        self.output_text.config(yscrollcommand=output_scrollbar.set)

        self.output_text.pack(side="left", fill="both", expand=True, padx=(10, 0), pady=(0, 10))
        output_scrollbar.pack(side="right", fill="y", padx=(0, 10), pady=(0, 10))

        # 按钮区域
        button_frame = tk.Frame(self.main_frame, bg='#f0f0f0')
        button_frame.pack(fill="x", pady=10)

        buttons = [
            ("🚀 计算", self.calculate, "#27ae60"),
            ("📤 复制结果", self.copy_results, "#3498db"),
            ("🧹 清空全部", self.clear_all, "#e74c3c")
        ]

        for text, command, color in buttons:
            tk.Button(button_frame, text=text, command=command, bg=color,
                     fg="white", font=('微软雅黑', 10, 'bold'), width=12, height=1,
                     relief='raised', bd=2).pack(side="left", padx=8)

    def parse_line(self, line):
        line = line.strip()
        while '  ' in line:
            line = line.replace('  ', ' ')
        line = line.replace(' ', ',')
        return [part.strip() for part in line.split(',') if part.strip()]

    def paste_station_data(self):
        try:
            clipboard_data = self.root.clipboard_get()
            self.station_center_entry.delete(1.0, tk.END)
            self.station_center_entry.insert(1.0, clipboard_data)
        except Exception:
            pass

    def clear_station_data(self):
        self.station_center_entry.delete(1.0, tk.END)

    def paste_data(self):
        try:
            clipboard_data = self.root.clipboard_get()
            self.input_text.delete(1.0, tk.END)
            self.input_text.insert(1.0, clipboard_data)
        except Exception:
            pass

    def copy_results(self):
        try:
            result_text = self.output_text.get(1.0, tk.END).strip()
            if result_text:
                self.root.clipboard_clear()
                self.root.clipboard_append(result_text)
                messagebox.showinfo("成功", "结果已复制到剪贴板")
        except Exception:
            pass

    def parse_station_center(self, text):
        parts = text.strip().split()
        if len(parts) < 2:
            raise ValueError("输入格式错误")

        station_parts = parts[0].split(',')
        center_parts = parts[1].split(',')

        if len(station_parts) != 3:
            raise ValueError("测设点坐标格式错误")

        if len(center_parts) != 2:
            raise ValueError("圆心坐标格式错误")

        return {
            'station_x': station_parts[0].strip(),
            'station_y': station_parts[1].strip(),
            'station_h': station_parts[2].strip(),
            'center_x': center_parts[0].strip(),
            'center_y': center_parts[1].strip()
        }

    def calculate_forward_azimuth(self, station_x, station_y, center_x, center_y, center_position):
        delta_x = float(center_x) - float(station_x)
        delta_y = float(center_y) - float(station_y)

        azimuth = math.atan2(delta_y, delta_x)

        if center_position == "left":
            forward_azimuth = azimuth + math.pi/2
        else:
            forward_azimuth = azimuth - math.pi/2

        if forward_azimuth < 0:
            forward_azimuth += 2 * math.pi
        elif forward_azimuth >= 2 * math.pi:
            forward_azimuth -= 2 * math.pi

        return forward_azimuth

    def calculate_offset(self, station_x, station_y, point_x, point_y, forward_azimuth):
        delta_x = float(point_x) - float(station_x)
        delta_y = float(point_y) - float(station_y)
        offset = -delta_x * math.sin(forward_azimuth) + delta_y * math.cos(forward_azimuth)
        return offset

    def calculate_coord_to_offset(self, station_center_data, points):
        station_x = station_center_data['station_x']
        station_y = station_center_data['station_y']
        center_x = station_center_data['center_x']
        center_y = station_center_data['center_y']
        center_h = float(station_center_data['station_h']) + float(self.height_param.get())
        center_position = self.center_position.get()

        forward_azimuth = self.calculate_forward_azimuth(
            station_x, station_y, center_x, center_y, center_position)

        center_offset = self.calculate_offset(
            station_x, station_y, center_x, center_y, forward_azimuth)

        results = []
        for line in points:
            parts = self.parse_line(line)
            if len(parts) >= 3:
                try:
                    x, y, h = parts[0], parts[1], parts[2]

                    offset = self.calculate_offset(station_x, station_y, x, y, forward_azimuth)
                    translated_offset = offset - center_offset
                    height_diff = float(h) - center_h

                    results.append(f"{translated_offset:.3f},{height_diff:.3f}")
                except ValueError:
                    continue

        return results

    def calculate_offset_to_coord(self, station_center_data, points):
        station_x = float(station_center_data['station_x'])
        station_y = float(station_center_data['station_y'])
        center_x = float(station_center_data['center_x'])
        center_y = float(station_center_data['center_y'])
        center_h = float(station_center_data['station_h']) + float(self.height_param.get())
        center_position = self.center_position.get()

        forward_azimuth = self.calculate_forward_azimuth(
            station_x, station_y, center_x, center_y, center_position)

        center_offset = self.calculate_offset(
            station_x, station_y, center_x, center_y, forward_azimuth)

        results = []
        for line in points:
            parts = self.parse_line(line)
            if len(parts) >= 2:
                try:
                    offset = float(parts[0])
                    height_diff = float(parts[1])

                    actual_offset = offset + center_offset
                    delta_x = -actual_offset * math.sin(forward_azimuth)
                    delta_y = actual_offset * math.cos(forward_azimuth)

                    point_x = station_x + delta_x
                    point_y = station_y + delta_y
                    point_h = center_h + height_diff

                    results.append(f"{point_x:.3f},{point_y:.3f},{point_h:.3f}")
                except ValueError:
                    continue

        return results

    def calculate_actual_to_design(self, station_center_data, points):
        station_x = float(station_center_data['station_x'])
        station_y = float(station_center_data['station_y'])
        station_h = float(station_center_data['station_h'])
        center_x = float(station_center_data['center_x'])
        center_y = float(station_center_data['center_y'])
        radius = float(self.radius_entry.get())
        center_h = station_h + float(self.height_param.get())

        results = []
        for line in points:
            parts = self.parse_line(line)
            if len(parts) >= 3:
                try:
                    actual_x, actual_y, actual_h = float(parts[0]), float(parts[1]), float(parts[2])

                    result_dict = self.calculate_design_and_excavation(
                        float(self.height_param.get()), radius, station_x, station_y, station_h,
                        center_x, center_y, actual_x, actual_y, actual_h
                    )

                    excavation_type = f"超挖{result_dict['over_excavation']:.3f}" if result_dict['over_excavation'] >= 0 else f"欠挖{abs(result_dict['over_excavation']):.3f}"
                    results.append(f"{result_dict['design_x']:.3f},{result_dict['design_y']:.3f},{result_dict['design_h']:.3f},{excavation_type}")

                except ValueError:
                    continue

        return results

    def calculate_design_and_excavation(self, height_param, r, setup_x, setup_y, setup_h,
                                      center_x, center_y, actual_x, actual_y, actual_h):
        center_h = setup_h + height_param

        dx = actual_x - center_x
        dy = actual_y - center_y
        s = math.sqrt(dx**2 + dy**2)

        h_diff = actual_h - center_h
        d = math.sqrt(s**2 + h_diff**2)
        over_excavation = d - r

        cos_theta = h_diff / d if d != 0 else 0
        s_prime = math.sqrt(1 - cos_theta**2) * r
        h_prime = cos_theta * r

        if s != 0:
            direction_x = dx / s
            direction_y = dy / s
        else:
            direction_x = 0
            direction_y = 0

        design_x = center_x + direction_x * s_prime
        design_y = center_y + direction_y * s_prime
        design_h = center_h + h_prime

        return {
            'design_x': design_x,
            'design_y': design_y,
            'design_h': design_h,
            'over_excavation': over_excavation
        }

    def calculate(self):
        try:
            station_center_text = self.station_center_entry.get(1.0, tk.END).strip()
            if not station_center_text:
                messagebox.showerror("错误", "请输入基础参数")
                return

            station_center_data = self.parse_station_center(station_center_text)

            input_text = self.input_text.get(1.0, tk.END).strip()
            if not input_text:
                messagebox.showerror("错误", "请输入数据")
                return

            points = [line for line in input_text.split('\n') if line.strip()]

            calc_type = self.calc_type.get()
            if calc_type == "coord_to_offset":
                results = self.calculate_coord_to_offset(station_center_data, points)
            elif calc_type == "offset_to_coord":
                results = self.calculate_offset_to_coord(station_center_data, points)
            elif calc_type == "actual_to_design":
                results = self.calculate_actual_to_design(station_center_data, points)
            else:
                messagebox.showerror("错误", "请选择计算类型")
                return

            self.output_text.delete(1.0, tk.END)
            if results:
                self.output_text.insert(1.0, "\n".join(results))
            else:
                self.output_text.insert(1.0, "无计算结果")

        except Exception as e:
            messagebox.showerror("错误", f"计算过程中发生错误: {str(e)}")

    def clear_input(self):
        self.input_text.delete(1.0, tk.END)

    def clear_output(self):
        self.output_text.delete(1.0, tk.END)

    def clear_all(self):
        self.clear_station_data()
        self.clear_input()
        self.clear_output()

if __name__ == "__main__":
    root = tk.Tk()
    app = SurveyCalculator(root)
    root.mainloop()


回复

使用道具 举报

 楼主| 发表于 2025-10-20 19:24:02 | 显示全部楼层
137000
2732299.706,517205.969,1465.060
2732296.390,517201.809

2732300.273,517206.679,1466.996  
2732299.87,517206.174,1469.094  
2732299.147,517205.267,1470.957  
2732298.038,517203.876,1472.133  
2732296.229,517201.606,1472.863  
2732294.298,517199.185,1471.828  
2732293.177,517197.779,1470.053  
2732292.732,517197.22,1468.24  
2732292.557,517197.001,1466.668数据示例
回复 支持 反对

使用道具 举报

发表于 2025-10-20 20:48:45 | 显示全部楼层
纯支持,代码真看不懂
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-10-20 22:46:53 | 显示全部楼层
import tkinter as tk
import math
from tkinter import messagebox

class SurveyCalculator:
    def __init__(self, root):
        self.root = root
        self.root.title("隧道断面数据复核批量计算")
        self.root.geometry("1000x800")
        
        self.main_frame = tk.Frame(root, bg='#f0f0f0')
        self.main_frame.pack(fill="both", expand=True, padx=15, pady=15)
        
        self.setup_interface()
   
    def setup_interface(self):
        # 批量设置区域
        batch_frame = tk.Frame(self.main_frame, bg='white', relief='raised', bd=1)
        batch_frame.pack(fill="x", pady=(0, 10))
        
        batch_config = tk.Frame(batch_frame, bg='white')
        batch_config.pack(fill="x", padx=15, pady=10)
        
        tk.Label(batch_config, text="分隔符:", bg='white').pack(side="left", padx=5)
        self.batch_separator = tk.StringVar(value="blank")
        tk.Radiobutton(batch_config, text="空行", variable=self.batch_separator, value="blank",
                      bg='white').pack(side="left", padx=2)
        tk.Label(batch_config, text="位置:", bg='white').pack(side="left", padx=(20,5))
        self.batch_position = tk.StringVar(value="left")
        tk.Radiobutton(batch_config, text="左幅", variable=self.batch_position, value="left",
                      bg='white').pack(side="left", padx=2)
        tk.Radiobutton(batch_config, text="右幅", variable=self.batch_position, value="right",
                      bg='white').pack(side="left", padx=2)
        
        tk.Label(batch_config, text="高差参数:", bg='white').pack(side="left", padx=(20,5))
        self.height_param = tk.Entry(batch_config, width=8, justify='center')
        self.height_param.insert(0, "1.61")
        self.height_param.pack(side="left", padx=5)
        
        tk.Label(batch_config, text="半径:", bg='white').pack(side="left", padx=(20,5))
        self.radius_entry = tk.Entry(batch_config, width=8, justify='center')
        self.radius_entry.insert(0, "5.5")
        self.radius_entry.pack(side="left", padx=5)
        
        # 计算类型选择
        type_frame = tk.Frame(batch_config, bg='white')
        type_frame.pack(side="left", padx=(20,0))
        
        self.calc_type = tk.StringVar(value="coord_to_offset")
        tk.Radiobutton(type_frame, text="坐标→偏距高差", variable=self.calc_type, value="coord_to_offset",
                      bg='white').pack(side="left", padx=5)
        tk.Radiobutton(type_frame, text="偏距高差→坐标", variable=self.calc_type, value="offset_to_coord",
                      bg='white').pack(side="left", padx=5)
        tk.Radiobutton(type_frame, text="实际→设计坐标", variable=self.calc_type, value="actual_to_design",
                      bg='white').pack(side="left", padx=5)
        
        # 基础参数输入区域
        param_frame = tk.Frame(self.main_frame, bg='white', relief='raised', bd=1)
        param_frame.pack(fill="x", pady=(0, 10))
        
        param_header = tk.Frame(param_frame, bg='#2c3e50', height=30)
        param_header.pack(fill="x", pady=(0, 10))
        param_header.pack_propagate(False)
        tk.Label(param_header, text="基础参数(每组一行:测设点X,测设点Y,测设点H 圆心X,圆心Y [半径])",
                bg='#2c3e50', fg='white').pack(side="left", padx=10)
        
        btn_frame = tk.Frame(param_frame, bg='white')
        btn_frame.pack(fill="x", padx=15, pady=8)
        
        tk.Button(btn_frame, text="粘贴", command=self.paste_station_data,
                 bg='#3498db', fg='white', width=8).pack(side="left", padx=2)
        tk.Button(btn_frame, text="清空", command=self.clear_station_data,
                 bg='#e74c3c', fg='white', width=8).pack(side="left", padx=2)
        
        self.station_center_entry = tk.Text(param_frame, height=4, font=('Consolas', 9),
                                           bg='#f8f9fa', relief='solid', bd=1)
        self.station_center_entry.pack(fill="x", padx=15, pady=(0, 10))
        
        # 数据输入和输出区域
        data_frame = tk.Frame(self.main_frame, bg='#f0f0f0')
        data_frame.pack(fill="both", expand=True, pady=(0, 10))
        
        # 数据输入区域
        input_frame = tk.Frame(data_frame, bg='white', relief='raised', bd=1)
        input_frame.pack(side="left", fill="both", expand=True, padx=(0, 5))
        
        input_header = tk.Frame(input_frame, bg='#34495e', height=30)
        input_header.pack(fill="x", pady=(0, 8))
        input_header.pack_propagate(False)
        tk.Label(input_header, text="数据输入", bg='#34495e', fg='white').pack(side="left", padx=10)
        
        input_btn_frame = tk.Frame(input_frame, bg='white')
        input_btn_frame.pack(fill="x", padx=10, pady=(0, 8))
        
        tk.Button(input_btn_frame, text="粘贴", command=self.paste_data,
                 bg='#3498db', fg='white', width=8).pack(side="left", padx=2)
        tk.Button(input_btn_frame, text="清空", command=self.clear_input,
                 bg='#e74c3c', fg='white', width=8).pack(side="left", padx=2)
        
        self.input_text = tk.Text(input_frame, height=20, wrap="none", font=("Consolas", 9),
                                 bg='#f8f9fa', relief='solid', bd=1)
        input_scrollbar = tk.Scrollbar(input_frame, command=self.input_text.yview)
        self.input_text.config(yscrollcommand=input_scrollbar.set)
        
        self.input_text.pack(side="left", fill="both", expand=True, padx=(10, 0), pady=(0, 10))
        input_scrollbar.pack(side="right", fill="y", padx=(0, 10), pady=(0, 10))
        
        # 结果显示区域
        output_frame = tk.Frame(data_frame, bg='white', relief='raised', bd=1)
        output_frame.pack(side="right", fill="both", expand=True, padx=(5, 0))
        
        output_header = tk.Frame(output_frame, bg='#27ae60', height=30)
        output_header.pack(fill="x", pady=(0, 8))
        output_header.pack_propagate(False)
        tk.Label(output_header, text="计算结果", bg='#27ae60', fg='white').pack(side="left", padx=10)
        
        output_btn_frame = tk.Frame(output_frame, bg='white')
        output_btn_frame.pack(fill="x", padx=10, pady=(0, 8))
        
        tk.Button(output_btn_frame, text="清空", command=self.clear_output,
                 bg='#e74c3c', fg='white', width=8).pack(side="left", padx=2)
        
        self.output_text = tk.Text(output_frame, height=20, wrap="none", font=("Consolas", 9),
                                  bg='#f8f9fa', relief='solid', bd=1)
        output_scrollbar = tk.Scrollbar(output_frame, command=self.output_text.yview)
        self.output_text.config(yscrollcommand=output_scrollbar.set)
        
        self.output_text.pack(side="left", fill="both", expand=True, padx=(10, 0), pady=(0, 10))
        output_scrollbar.pack(side="right", fill="y", padx=(0, 10), pady=(0, 10))
        
        # 按钮区域
        button_frame = tk.Frame(self.main_frame, bg='#f0f0f0')
        button_frame.pack(fill="x", pady=10)
        
        tk.Button(button_frame, text="计算", command=self.calculate, bg='#27ae60',
                 fg="white", width=12, height=1).pack(side="left", padx=8)
        tk.Button(button_frame, text="复制结果", command=self.copy_results, bg='#3498db',
                 fg="white", width=12, height=1).pack(side="left", padx=8)
        tk.Button(button_frame, text="清空全部", command=self.clear_all, bg='#e74c3c',
                 fg="white", width=12, height=1).pack(side="left", padx=8)
   
    def parse_line(self, line):
        line = line.strip()
        while '  ' in line:
            line = line.replace('  ', ' ')
        line = line.replace(' ', ',')
        return [part.strip() for part in line.split(',') if part.strip()]
   
    def paste_station_data(self):
        try:
            clipboard_data = self.root.clipboard_get()
            self.station_center_entry.delete(1.0, tk.END)
            self.station_center_entry.insert(1.0, clipboard_data)
        except Exception:
            pass
   
    def clear_station_data(self):
        self.station_center_entry.delete(1.0, tk.END)
   
    def paste_data(self):
        try:
            clipboard_data = self.root.clipboard_get()
            self.input_text.delete(1.0, tk.END)
            self.input_text.insert(1.0, clipboard_data)
        except Exception:
            pass
   
    def copy_results(self):
        try:
            result_text = self.output_text.get(1.0, tk.END).strip()
            if result_text:
                self.root.clipboard_clear()
                self.root.clipboard_append(result_text)
                messagebox.showinfo("成功", "结果已复制到剪贴板")
        except Exception:
            pass
   
    def parse_station_center(self, text):
        lines = [line.strip() for line in text.split('\n') if line.strip()]
        station_center_data_list = []
        
        for line in lines:
            parts = line.strip().split()
            if len(parts) < 2:
                continue
            
            station_parts = parts[0].split(',')
            center_parts = parts[1].split(',')
            
            if len(station_parts) != 3 or len(center_parts) != 2:
                continue
            
            data = {
                'station_x': station_parts[0].strip(),
                'station_y': station_parts[1].strip(),
                'station_h': station_parts[2].strip(),
                'center_x': center_parts[0].strip(),
                'center_y': center_parts[1].strip()
            }
            
            if len(parts) >= 3:
                data['radius'] = parts[2].strip()
            else:
                data['radius'] = self.radius_entry.get().strip()
            
            station_center_data_list.append(data)
        
        return station_center_data_list
   
    def split_data_groups(self, input_text):
        separator = self.batch_separator.get()
        if separator == "blank":
            groups = []
            current_group = []
            for line in input_text.split('\n'):
                line = line.strip()
                if line:
                    current_group.append(line)
                else:
                    if current_group:
                        groups.append(current_group)
                        current_group = []
            if current_group:
                groups.append(current_group)
        else:
            groups = []
            current_group = []
            for line in input_text.split('\n'):
                line = line.strip()
                if line == "---":
                    if current_group:
                        groups.append(current_group)
                        current_group = []
                elif line:
                    current_group.append(line)
            if current_group:
                groups.append(current_group)
        
        return groups
   
    def calculate_forward_azimuth(self, station_x, station_y, center_x, center_y, center_position):
        delta_x = float(center_x) - float(station_x)
        delta_y = float(center_y) - float(station_y)
        
        azimuth = math.atan2(delta_y, delta_x)
        
        if center_position == "left":
            forward_azimuth = azimuth + math.pi/2
        else:
            forward_azimuth = azimuth - math.pi/2
            
        if forward_azimuth < 0:
            forward_azimuth += 2 * math.pi
        elif forward_azimuth >= 2 * math.pi:
            forward_azimuth -= 2 * math.pi
            
        return forward_azimuth
   
    def calculate_offset(self, station_x, station_y, point_x, point_y, forward_azimuth):
        delta_x = float(point_x) - float(station_x)
        delta_y = float(point_y) - float(station_y)
        offset = -delta_x * math.sin(forward_azimuth) + delta_y * math.cos(forward_azimuth)
        return offset
   
    def calculate_coord_to_offset(self, station_center_data, points):
        station_x = station_center_data['station_x']
        station_y = station_center_data['station_y']
        center_x = station_center_data['center_x']
        center_y = station_center_data['center_y']
        center_h = float(station_center_data['station_h']) + float(self.height_param.get())
        
        forward_azimuth = self.calculate_forward_azimuth(
            station_x, station_y, center_x, center_y, self.batch_position.get())
        
        center_offset = self.calculate_offset(
            station_x, station_y, center_x, center_y, forward_azimuth)
        
        results = []
        for line in points:
            parts = self.parse_line(line)
            if len(parts) >= 3:
                try:
                    x, y, h = parts[0], parts[1], parts[2]
                    
                    offset = self.calculate_offset(station_x, station_y, x, y, forward_azimuth)
                    translated_offset = offset - center_offset
                    height_diff = float(h) - center_h
                    
                    results.append(f"{translated_offset:.3f},{height_diff:.3f}")
                except ValueError:
                    continue
        
        return results
   
    def calculate_offset_to_coord(self, station_center_data, points):
        station_x = float(station_center_data['station_x'])
        station_y = float(station_center_data['station_y'])
        center_x = float(station_center_data['center_x'])
        center_y = float(station_center_data['center_y'])
        center_h = float(station_center_data['station_h']) + float(self.height_param.get())
        
        forward_azimuth = self.calculate_forward_azimuth(
            station_x, station_y, center_x, center_y, self.batch_position.get())
        
        center_offset = self.calculate_offset(
            station_x, station_y, center_x, center_y, forward_azimuth)
        
        results = []
        for line in points:
            parts = self.parse_line(line)
            if len(parts) >= 2:
                try:
                    offset = float(parts[0])
                    height_diff = float(parts[1])
                    
                    actual_offset = offset + center_offset
                    delta_x = -actual_offset * math.sin(forward_azimuth)
                    delta_y = actual_offset * math.cos(forward_azimuth)
                    
                    point_x = station_x + delta_x
                    point_y = station_y + delta_y
                    point_h = center_h + height_diff
                    
                    results.append(f"{point_x:.3f},{point_y:.3f},{point_h:.3f}")
                except ValueError:
                    continue
        
        return results
   
    def calculate_actual_to_design(self, station_center_data, points):
        station_x = float(station_center_data['station_x'])
        station_y = float(station_center_data['station_y'])
        station_h = float(station_center_data['station_h'])
        center_x = float(station_center_data['center_x'])
        center_y = float(station_center_data['center_y'])
        radius = float(station_center_data['radius'])
        center_h = station_h + float(self.height_param.get())
        
        results = []
        for line in points:
            parts = self.parse_line(line)
            if len(parts) >= 3:
                try:
                    actual_x, actual_y, actual_h = float(parts[0]), float(parts[1]), float(parts[2])
                    
                    dx = actual_x - center_x
                    dy = actual_y - center_y
                    s = math.sqrt(dx**2 + dy**2)
                    
                    h_diff = actual_h - center_h
                    d = math.sqrt(s**2 + h_diff**2)
                    over_excavation = d - radius
                    
                    cos_theta = h_diff / d if d != 0 else 0
                    s_prime = math.sqrt(1 - cos_theta**2) * radius
                    h_prime = cos_theta * radius
                    
                    if s != 0:
                        direction_x = dx / s
                        direction_y = dy / s
                    else:
                        direction_x = 0
                        direction_y = 0
                    
                    design_x = center_x + direction_x * s_prime
                    design_y = center_y + direction_y * s_prime
                    design_h = center_h + h_prime
                    
                    excavation_type = f"超挖{over_excavation:.3f}" if over_excavation >= 0 else f"欠挖{abs(over_excavation):.3f}"
                    results.append(f"{design_x:.3f},{design_y:.3f},{design_h:.3f},{excavation_type}")
                    
                except ValueError:
                    continue
        
        return results
   
    def calculate(self):
        try:
            station_center_text = self.station_center_entry.get(1.0, tk.END).strip()
            if not station_center_text:
                messagebox.showerror("错误", "请输入基础参数")
                return
            
            station_center_data_list = self.parse_station_center(station_center_text)
            if not station_center_data_list:
                messagebox.showerror("错误", "基础参数格式错误")
                return
            
            input_text = self.input_text.get(1.0, tk.END).strip()
            if not input_text:
                messagebox.showerror("错误", "请输入数据")
                return
            
            data_groups = self.split_data_groups(input_text)
            
            if len(station_center_data_list) != len(data_groups):
                messagebox.showerror("错误", f"基础参数组数({len(station_center_data_list)})与数据组数({len(data_groups)})不匹配")
                return
            
            calc_type = self.calc_type.get()
            all_results = []
            
            for i, (station_center_data, data_group) in enumerate(zip(station_center_data_list, data_groups)):
                if calc_type == "coord_to_offset":
                    results = self.calculate_coord_to_offset(station_center_data, data_group)
                elif calc_type == "offset_to_coord":
                    results = self.calculate_offset_to_coord(station_center_data, data_group)
                elif calc_type == "actual_to_design":
                    results = self.calculate_actual_to_design(station_center_data, data_group)
                else:
                    messagebox.showerror("错误", "请选择计算类型")
                    return
               
                all_results.append(results)
            
            self.output_text.delete(1.0, tk.END)
            if all_results:
                output_lines = []
                for i, results in enumerate(all_results):
                    if i > 0:
                        output_lines.append("")
                    output_lines.extend(results)
               
                self.output_text.insert(1.0, "\n".join(output_lines))
            else:
                self.output_text.insert(1.0, "无计算结果")
               
        except Exception as e:
            messagebox.showerror("错误", f"计算过程中发生错误: {str(e)}")
   
    def clear_input(self):
        self.input_text.delete(1.0, tk.END)
   
    def clear_output(self):
        self.output_text.delete(1.0, tk.END)
   
    def clear_all(self):
        self.clear_station_data()
        self.clear_input()
        self.clear_output()

if __name__ == "__main__":
    root = tk.Tk()
    app = SurveyCalculator(root)
    root.mainloop()
批量计算模式
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-10-20 22:53:46 | 显示全部楼层
基础参数(两组):
2732299.706,517205.969,1465.060 2732296.390,517201.809 6
2710099.854,508138.210,1049.918 2710104.769,508140.246 5.9

数据输入(第一组):
2732300.273,517206.679,1466.996
2732299.87,517206.174,1469.094
2732299.147,517205.267,1470.957
2732298.038,517203.876,1472.133
2732296.229,517201.606,1472.863
2732294.298,517199.185,1471.828
2732293.177,517197.779,1470.053
2732292.732,517197.22,1468.24
2732292.557,517197.001,1466.668

数据输入(第二组):
2710099.2080,508137.9387,1050.0886
2710099.2470,508137.8234,1050.6535
2710099.2200,508137.8412,1051.1086
2710099.0580,508138.1172,1051.6730
2710099.2190,508137.9394,1052.6990
2710099.3590,508138.1043,1053.4677
2710099.5800,508138.1464,1054.0562
2710099.9180,508138.2822,1054.7231
2710100.3560,508138.4239,1055.3791
2710100.9640,508138.4665,1056.0073
2710101.4700,508138.7700,1056.4655
2710102.1320,508139.3312,1056.9597
2710102.8000,508139.4834,1057.2632
2710103.5800,508139.8395,1057.4990
2710104.5100,508140.1454,1057.6005
2710105.4770,508140.5300,1057.5463
2710106.2000,508140.9229,1057.3729
2710106.9720,508141.0853,1057.0794
2710107.8910,508141.3964,1056.6018
2710109.6520,508142.1338,1054.5740
2710110.2000,508142.5886,1052.8950
2710110.3460,508142.5633,1052.2304

批量的数据示例
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2025-12-7 07:28 , Processed in 0.170735 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表