From c56703e6099d97f25eb1bac10b24fee927cf676d Mon Sep 17 00:00:00 2001 From: n3040 Date: Mon, 25 Jul 2022 14:03:25 +0800 Subject: [PATCH] =?UTF-8?q?1.=E5=91=BD=E4=BB=A4=E8=A1=8C=E5=9F=BA=E6=9C=AC?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=B7=B2=E6=89=93=E9=80=9A=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PWFile.py | 470 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 466 insertions(+), 4 deletions(-) diff --git a/PWFile.py b/PWFile.py index 0c62053..af95f52 100644 --- a/PWFile.py +++ b/PWFile.py @@ -1,6 +1,16 @@ +import os.path from collections import OrderedDict import re +import pandas as pd from attrs import define +from tkinter.messagebox import NO +import xlwings as xw +from Apyautocad import Apyautocad, APoint +import os +import numpy as np +from time import sleep +from attrs import define +from typing import List @define @@ -11,7 +21,7 @@ class SEntry: mileage_in_s: int = 0 back_k: float = 0 forth_k: float = 0 - altitude_off: float = 0#中心桩高差 + altitude_off: float = 0 # 中心桩高差 foundation_low: float = 0 # 基降 fitting: str = "" # 金具 is_tension_tower: bool = False @@ -92,8 +102,460 @@ class Fitting: fit_name = fit[0] fit_parameter = next(ite) self.fitting_length_dic[fit_name] = float(fit_parameter[2]) / 1000 + + @define class ColorEnume: - wire_color_rgb=[122, 219, 245] - tree_color_rgb=[122, 219, 245] - ground_color_rgb=[116, 230, 165] \ No newline at end of file + wire_color_rgb = [122, 219, 245] + tree_color_rgb = [240, 226, 81] + ground_color_rgb = [82, 79, 254] + + +# 读取Z文件,找到Z断面第一个点的坐标 +def plane_z_origin(z_file_path): + with open(z_file_path) as zfile: + content = zfile.read() + norm_content = re.sub("\s+", ",", content) + sep = norm_content.split(",") + return np.array([float(sep[0]), float(sep[1])]) + + +def deduce_zfile_from_cad_path(cad_file_path): + dwg_file_name = os.path.split(cad_file_path) + dwg_prefix = dwg_file_name[1].split(".")[0] + return os.path.join(dwg_file_name[0], f"Z{dwg_prefix}") + + +def deduce_fit_db_from_cad_path(cad_file_path): + dwg_file_name = os.path.split(cad_file_path) + dwg_prefix = dwg_file_name[1].split(".")[0] + return os.path.join(dwg_file_name[0], "Fit.db") + + +def curve_fun(x, span, k, gaocha): + return x * gaocha / span - x * (span - x) * k + + +def np2d_to_array(np2d): # 把2维numpy数组转换成cad可以用的数组 + t = np.hstack((np2d, np.zeros((np2d.shape[0], 1)))).reshape(1, np2d.shape[0] * 3) + return t[0] + + +class StringImpactExcel: + def __init__(self) -> None: + # self._wb=None + pass + + def read(self, wb, gaocha, span, tension): + pos代表档距 = "F13" + pos档距 = "L13" + pos高差 = "R13" + pos张力 = "AB18" + pos总串长 = "C8" + sheet = wb.sheets["模板"] + sheet.range(pos高差).value = gaocha + sheet.range(pos档距).value = span + sheet.range(pos张力).value = tension + string_length = sheet.range(pos总串长).value + # print(sheet.range("V25:V46").value) + x = np.linspace(string_length, span, int(span / 5), endpoint=True) + x[0] = sheet.range("E23").value + x[1] = sheet.range("E24").value + sheet.range(f"E25:E{25+len(x)-3}").value = x[2:].reshape(len(x[2:]), 1) + y = ( + np.array(sheet.range(f"V23:V{23+len(x)-1}").value) / 2 + ) # 表格是乘以了2的,为了和x保持一致,没有乘比例。 + return (x, y) + + +def set_true_color(object, r, g, b): + true_color = object.TrueColor + true_color.SetRGB(r, g, b) + object.TrueColor = true_color + + +@define +class StringImpactPlate: + _dwg_file_path: str + _s_file_path: str + _draw_start_tower_name: str + _continouse_tension_excel: str + _string_impact_curve_excel: str + _cad: None + + def _find_target_tower_index(self, start_tower_name: str, tower_dict): + index = [] + tower_key_list = list(tower_dict.keys()) + index.append(tower_key_list.index(start_tower_name)) + can_start_find = False + for tower_key in tower_key_list: + # index.append(start_tower_name.index(foo)) + tower_info = tower_dict[tower_key] + if tower_info.tower_name == start_tower_name: + can_start_find = True + continue + if can_start_find and tower_info.is_tension_tower == True: + found_tower_name = tower_info.tower_name + index.append(tower_key_list.index(found_tower_name)) + break + return index + + def _plot(self, cad, plot_x, plot_y): + plot_vector = np2d_to_array(np.hstack((plot_x, plot_y))) + added_curve = cad.model.AddPolyLine(plot_vector) + set_true_color(added_curve, *ColorEnume.wire_color_rgb) + plot_ground_y = plot_y - 18 * 2 + plot_ground_vector = np2d_to_array(np.hstack((plot_x, plot_ground_y))) + added_ground_curve = cad.model.AddPolyLine(plot_ground_vector) + set_true_color(added_ground_curve, *ColorEnume.ground_color_rgb) + plot_tree_y = plot_y - 13.5 * 2 + plot_tree_vector = np2d_to_array(np.hstack((plot_x, plot_tree_y))) + added_tree_curve = cad.model.AddPolyLine(plot_tree_vector) + set_true_color(added_tree_curve, *ColorEnume.tree_color_rgb) + + def _draw_action(self, excel_app, cad): + # 计算代表档距 + s_file = SFile() + s_file.open(self._s_file_path) + tower_dict = s_file.tower_dic + tower_key_list = list(tower_dict.keys()) + draw_tower_index = self._find_target_tower_index( + self._draw_start_tower_name, tower_dict + ) + fitting_file_path = deduce_fit_db_from_cad_path(self._dwg_file_path) + fitting = Fitting(fitting_file_path) + z_file_path = deduce_zfile_from_cad_path(self._dwg_file_path) + plate_origin = plane_z_origin(z_file_path) + continouse_wb = excel_app.books.open(self._continouse_tension_excel) + continouse_sheet = continouse_wb.sheets["模板"] + wb_string_impact = excel_app.books.open(self._string_impact_curve_excel) + stringImpactExcel = StringImpactExcel() + sleep(1) + draw_first_tower_key = tower_key_list[draw_tower_index[0]] + first_tower_info = tower_dict[draw_first_tower_key] + forth_reprtv_span = first_tower_info.forth_representive_span + continouse_sheet.range("B69").value = forth_reprtv_span + high_temperature_tension = continouse_sheet.range("L69").value + forth_tower_info = tower_dict[tower_key_list[draw_tower_index[0] + 1]] + gaocha_of_first_tower = ( + ( + forth_tower_info.tower_height + - forth_tower_info.foundation_low + - fitting.fitting_length_dic[forth_tower_info.fitting] + ) + - (first_tower_info.tower_height - first_tower_info.foundation_low) + + forth_tower_info.altitude_off + ) + span_of_first_tower = ( + forth_tower_info.mileage_in_s - first_tower_info.mileage_in_s + ) + (x, y) = stringImpactExcel.read( + wb_string_impact, + gaocha_of_first_tower, + span_of_first_tower, + high_temperature_tension, + ) + # TODO: 没有考虑断面中间有耐张塔的情况 + plot_x = (plate_origin[0] + x / 5).reshape(len(x), 1) + plot_y = ( + plate_origin[1] + + (first_tower_info.tower_height - first_tower_info.foundation_low + y) * 2 + ).reshape(len(x), 1) + self._plot(cad, plot_x, plot_y) + # 画右侧耐张塔的弧垂 + draw_last_tower_key = tower_key_list[draw_tower_index[-1]] + last_tower_info = tower_dict[draw_last_tower_key] + back_reprtv_span = last_tower_info.back_representive_span + back_tower_info = tower_dict[tower_key_list[draw_tower_index[-1] - 1]] + gaocha_of_last_tower = ( + ( + back_tower_info.tower_height + - back_tower_info.foundation_low + - fitting.fitting_length_dic[back_tower_info.fitting] + ) + - (last_tower_info.tower_height - last_tower_info.foundation_low) + - last_tower_info.altitude_off + ) + span_of_last_tower = last_tower_info.mileage_in_s - back_tower_info.mileage_in_s + (x, y) = stringImpactExcel.read( + wb_string_impact, + gaocha_of_last_tower, + span_of_last_tower, + high_temperature_tension, + ) + plot_last_tower_x = ( + plate_origin[0] + + ( + tower_dict[tower_key_list[draw_tower_index[-1]]].mileage_in_s + - tower_dict[tower_key_list[draw_tower_index[0]]].mileage_in_s + ) + / 5 + - x / 5 # 从右往左画 + ).reshape(len(x), 1) + accumulate_altitude_off = np.sum( + [ + tower_dict[tower_key_list[bar]].altitude_off + for bar in range(draw_tower_index[0] + 1, draw_tower_index[-1] + 1) + ] + ) + plot_last_tower_y = ( + plate_origin[1] + + accumulate_altitude_off * 2 + + (last_tower_info.tower_height - last_tower_info.foundation_low + y) * 2 + ).reshape(len(x), 1) + plot_last_tower_vector = np2d_to_array( + np.hstack((plot_last_tower_x, plot_last_tower_y)) + ) + self._plot(cad, plot_last_tower_x, plot_last_tower_y) + + def draw(self): + if self._cad: + with xw.App(visible=False) as excel_app: + self._draw_action(excel_app, self._cad) + else: + with xw.App(visible=False) as excel_app, Apyautocad( + create_if_not_exists=True, visible=True, auto_close=True + ) as cad: + cad.app.Documents.Open(self._dwg_file_path) + self._draw_action(excel_app, cad) + + def saveAs(self, save_to): + self._cad.SaveAs(save_to) + + +@define +class ContinuousPlate: + _dwg_file_path: str + _s_file_path: str + _from_tower_name: str + _end_tower_name: str + cad: object = None + + def draw(self): + s_file = SFile() + s_file_path = self._s_file_path + s_file.open(s_file_path) + dwg_file_path = self._dwg_file_path + with Apyautocad( + create_if_not_exists=True, visible=False, auto_close=False + ) as cad: + self.cad = cad + # self._end_tower_name='sdfsd' + doc = cad.app.Documents.Open(dwg_file_path) + sleep(1) + tower_dict = s_file.tower_dic + z_file_path = deduce_zfile_from_cad_path(dwg_file_path) + z_point = plane_z_origin(z_file_path) + fitting_file_path = deduce_fit_db_from_cad_path(dwg_file_path) + fitting = Fitting(fitting_file_path) + fitting_length_dict = fitting.fitting_length_dic + first_tower_point = z_point + last_tower_info = None # 上一个塔位信息 + accu_mileage = 0 # 累计档距 + accu_altitude_off = 0 # 累计高差 + is_first_tower = True + can_start_draw = -1 + start_tower_name = self._from_tower_name + tower_key_list = list(tower_dict.keys()) + draw_count_limit = ( + tower_key_list.index(self._end_tower_name) + - tower_key_list.index(self._from_tower_name) + + 1 + ) + draw_count = 0 + for tower in tower_dict: + tower_info = tower_dict[tower] + if tower_info.tower_name == start_tower_name: + can_start_draw = 0 + elif can_start_draw != 0: + continue + if not last_tower_info: + last_tower_info = tower_info + if draw_count > draw_count_limit - 1: + break + foundation_low = tower_info.foundation_low + accu_mileage = ( + accu_mileage + + tower_info.mileage_in_s + - last_tower_info.mileage_in_s + ) + if is_first_tower: + accu_altitude_off=0 + else: + accu_altitude_off = accu_altitude_off + tower_info.altitude_off # 中心桩高程 + tower_start = APoint( + *( + ( + first_tower_point + + np.array( + [ + accu_mileage / 5, + (accu_altitude_off - foundation_low) * 2, + ] + ) + ).tolist() + ) + ) + tower_height = tower_info.tower_height + # accu_altitude_off = np.sum( + # [ + # tower_dict[tower_key_list[bar]].altitude_off + # for bar in range( + # tower_key_list.index(start_tower_name) + 1, + # tower_key_list.index(start_tower_name) + draw_count, + # ) + # ] + # ) + tower_end = APoint( + *( + first_tower_point + + np.array( + [ + accu_mileage / 5, + (accu_altitude_off + tower_height - foundation_low) * 2, + ] + ) + ).tolist() + ) + # 画杆高 + cad.model.AddLine(tower_start, tower_end) + draw_count += 1 + # 画弧垂 + if not is_first_tower: # 从第二基塔开始画 + draw_k = tower_info.back_k + span = tower_info.mileage_in_s - last_tower_info.mileage_in_s + last_tower_fiting = last_tower_info.fitting + last_tower_fitting_length = fitting_length_dict[last_tower_fiting] + if last_tower_info.is_tension_tower: + last_tower_fitting_length = 0 + tower_fitting = tower_info.fitting + tower_fitting_length = fitting_length_dict[tower_fitting] + if tower_info.is_tension_tower: + tower_fitting_length = 0 + last_tower_height = last_tower_info.tower_height + last_foundation_low = last_tower_info.foundation_low + # 挂点高差 + fiting_altitude_off = ( + tower_info.altitude_off + + (tower_height - foundation_low - tower_fitting_length) + - ( + last_tower_height + - last_foundation_low + - last_tower_fitting_length + ) + ) # 前侧高为正 + # 画导线弧垂 + x = np.linspace(0, span, int(span), endpoint=True) + curve = curve_fun(x, span, draw_k, fiting_altitude_off) + draw_curve_x = (first_tower_point[0]) + ( + x + accu_mileage - span + ) / 5 + draw_curve_y = ( + first_tower_point[1] + + ( + +curve + + accu_altitude_off + - tower_info.altitude_off + - last_tower_info.foundation_low + + last_tower_info.tower_height + - last_tower_fitting_length + ) + * 2 + ) + draw_curve_x = draw_curve_x.reshape(len(draw_curve_x), 1) + draw_curve_y = draw_curve_y.reshape(len(draw_curve_y), 1) + draw_ground_curve_y = draw_curve_y - 18 * 2 # 切地线 + draw_tree_curve_y = draw_curve_y - 13.5 * 2 # 切树线 + draw_point = np.hstack( + (draw_curve_x, draw_curve_y, np.zeros((len(draw_curve_x), 1))) + ) + draw_ground_curve_point = np.hstack( + ( + draw_curve_x, + draw_ground_curve_y, + np.zeros((len(draw_curve_x), 1)), + ) + ) + draw_tree_curve_point = np.hstack( + ( + draw_curve_x, + draw_tree_curve_y, + np.zeros((len(draw_curve_x), 1)), + ) + ) + added_curve = cad.model.AddPolyLine( + draw_point.reshape(1, draw_curve_x.shape[0] * 3)[0] + ) + set_true_color(added_curve, *ColorEnume.wire_color_rgb) + added_ground_curve = cad.model.AddPolyLine( + draw_ground_curve_point.reshape( + 1, draw_ground_curve_y.shape[0] * 3 + )[0] + ) + set_true_color(added_ground_curve, *ColorEnume.ground_color_rgb) + added_tree_curve = cad.model.AddPolyLine( + draw_tree_curve_point.reshape( + 1, draw_tree_curve_y.shape[0] * 3 + )[0] + ) + set_true_color(added_tree_curve, *ColorEnume.tree_color_rgb) + is_first_tower = False + last_tower_info = tower_info + + def saveAs(self, save_to): + cad = self.cad + doc.SaveAs(save_to) + + +@define +class ControlFile: + _z_file_path: str = "" + _dwg_file_path: str = "" + _from_tower_name: str = "" + _end_tower_name: str = "" + _consider_string_weight: bool = False + _excel_string_weight_path: str = "" + _excel_continouse_path: str = "" + _s_file_path: str = "" + _dir_prefix: str = "" + _z_file_name: str = "" + + def __init__(self, z_excel_file_path): + excel_pf = pd.read_excel(z_excel_file_path) + pf_dict = excel_pf.to_dict("records")[0] + z_excel_path = os.path.split(z_excel_file_path) + self._z_file_name = pf_dict["Z文件"] + dir_prefix = z_excel_path[0] + self._dir_prefix = dir_prefix + self._from_tower_name = pf_dict["起始塔号"] + self._end_tower_name = pf_dict["终止塔号"] + if pf_dict["是否考虑耐张串影响"] == "是": + self._consider_string_weight = True + self._excel_string_weight_path = pf_dict["计算耐张串影响用表格"] + self._excel_continouse_path = pf_dict["计算连续档用表格"] + self._z_file_path = os.path.join(dir_prefix, pf_dict["Z文件"]) + self._dwg_file_path = os.path.join(dir_prefix, pf_dict["DWG文件"]) + self._s_file_path = os.path.join(dir_prefix, pf_dict["S文件"]) + + def draw(self): + continousePlate = ContinuousPlate( + self._dwg_file_path, + self._s_file_path, + self._from_tower_name, + self._end_tower_name, + ) + continousePlate.draw() + string_impact_plate = StringImpactPlate( + self._dwg_file_path, + self._s_file_path, + self._from_tower_name, + self._excel_continouse_path, + self._excel_string_weight_path, + continousePlate.cad, + ) + string_impact_plate.draw() + cad = continousePlate.cad + cad.doc.SaveAs( + os.path.join(self._dir_prefix, "ZT" + self._z_file_name + ".dwg") + ) + cad.doc.Close(False)