- 积分
- 6102
- 明经币
- 个
- 注册时间
- 2022-9-23
- 在线时间
- 小时
- 威望
-
- 金钱
- 个
- 贡献
-
- 激情
-
|
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()
|
|