python-CAD绘制路基横断面

基于python的CAD路基横断面绘制 源代码 # _*_ coding:utf-8- _*_ from pyautocad import APoint, Autocad, aDouble import win32com.client import numpy as np """ 设计高程:(2)1654.0m 填土边坡与路堑边坡坡率:(1)填方上部1:1.2(高度≤8m),填方下部1:1.4(高度≤12m) ;挖方1:0.9(高度≤20m) 路基宽度:(2) 路面宽7.0米,硬路肩宽0.75米,土路肩宽0.75米 以下数据单位:m """ design_height = 1654.0 # 设计高程 slop_fill_up = 1.2 # 坡率填方上部(高度≤8m) slop_fill_down = 1.4 # 坡率填方下部(高度≤12m) slop_cut = 0.9 # 坡率挖方(高度≤20m) surface_width = 7.0 # 路面宽 hard_shoulder = 0.75 # 硬路肩宽 dirt_shoulder = 0.75 # 土路肩宽 ctfs = 10 # 出图坐标放缩倍数 distance_sections = 60 # 修改为出图时横断面桩号间距 # 连接excel读取数据 xlapp = win32com.client.Dispatch("Excel.Application") wb = xlapp.ActiveWorkbook ws = xlapp.ActiveWorkbook.ActiveSheet # points是原始地面点高程 ground_points = [] row = 2 while row <= 20: i = 6 # 左侧数据 j = 8 # 右侧数据 # 桩号点绘图坐标 x0 = 0 + (distance_sections * (row - 2))//3 y0 = ws.cells(row, 7).value p0 = APoint(x0, y0) pts = [] pts.append(p0) # 拾取左侧点数据 while i >= 1: try: y_ = ws.cells(row, i).value x_ = - ws.cells(row + 1, i).value pti = pts[0] + (x_, y_, 0) pts.insert(0, pti) except: pass i -= 1 # 拾取右侧点数据 while ws.cells(row, j).value: y_ = ws.cells(row, j).value x_ = ws.cells(row + 1, j).value ptj = pts[-1] + (x_, y_, 0) pts.append(ptj) j += 1 ground_points.append(pts) for i in pts: print(i) print("") row = row + 3 # 连接cad,并输出结果 acad = Autocad(create_if_not_exists=True) acad.prompt("connect with the Autocad successfully.") print("connect with the Autocad successfully.") dwg = acad.ActiveDocument "原始地面线" # 定义原始地面线 图层 ysdmx = acad.doc.layers.add("原始地面线") ysdmx.color = 7 ysdmx.LineWeight = 25 dwg.ActiveLayer = ysdmx # 绘制原始地面线,使用多段线(PLine) for line_pts in ground_points: pt = aDouble([j for i in line_pts for j in i * ctfs]) acad.model.AddPolyLine(pt).LineWeight = 25 "路基线" # 绘制路基线,所有横断面路基线按一样绘制,手动修改 # 生成路基线关键点坐标 orginal_middl_pts = [] pt0 = APoint(0, design_height) orginal_middl_pts.append(pt0) rightpts = [(surface_width/2, 0), (hard_shoulder, 0), (dirt_shoulder, 0), (0.6, - 0.6), (0.6, 0), (0.6, 0.6), (1, 0), (20 * slop_cut, 20)] leftpts = [(surface_width/2, 0), (hard_shoulder, 0), (dirt_shoulder, 0), (8 * slop_fill_up, 8), (2, 0), (12 * slop_fill_down, 12)] for i in leftpts: pti = orginal_middl_pts[0] - (i[0], i[1], 0) orginal_middl_pts.insert(0, pti) for j in rightpts: ptj = orginal_middl_pts[-1] + (j[0], j[1], 0) orginal_middl_pts.append(ptj) # 定义路基线 图层 ljx = acad.doc.layers.add("路基线") ljx.color = 1 ljx.LineWeight = 100 dwg.ActiveLayer = ljx # 绘制路基,使用多段线(PLine) pt = aDouble([i for j in orginal_middl_pts for i in j * ctfs]) ljx_drawn = acad.model.AddPolyLine(pt) ljx_drawn.LineWeight = 100 "道路中心线" # 得到坐标 # 定义图层属性 zxj = acad.doc.layers.add("道路中心线") zxj.color = 2 zxj.LineWeight = 25 try: acad.ActiveDocument.Linetypes.Load("ACAD_ISO10W100", "acadiso.lin") except: pass zxj.Linetype = "ACAD_ISO10W100" dwg.ActiveLayer = zxj # 绘制中线 zxj_drewn = acad.model.addline(ctfs * (pt0 - (0, 2, 0)), ctfs * (pt0 + (0, 2, 0))) zxj_drewn.LineWeight = 25 # [中心线、路基线]向右复制6次 for i in range(6): _ = ljx_drawn.copy() _.Move(APoint(0, 0), APoint(distance_sections * (i + 1), 0) * ctfs) del _ _ = zxj_drewn.copy() _.Move(APoint(0, 0), APoint(distance_sections * (i + 1), 0) * ctfs) "添加桩号标注" # 得到坐标 # 定义图层 zh = acad.doc.layers.add("桩号标注") dwg.ActiveLayer = zh # 添加注释 for i in range(7): text_string = "K58+%d" % (70 + 10 * i) insertpt = APoint((distance_sections * i), design_height - 7) * ctfs height = 2.5 * ctfs textobj = acad.model.addtext(text_string, insertpt, height) textobj.Alignment = 7 textobj.textalignmentpoint = insertpt

2022年5月24日 · 3 分钟 · Vinkey

python-CAD绘制等高线

基于python的CAD等高线绘制 这是我本科在做《路基工程课程设计》挡土墙设计的时候,老师只给了原始地面数据点,因为疫情在家时间充裕,我就摸索了python画CAD,最终实现了绘制不同等高距的等高线绘制。 python面向对象编程。 基础知识 我这个代码只适合地面趋势简单的,通过差值得到固定整数高程点,然后将相同高程点依次连接。 note: 当时是在windows先写的代码,因为要用到win32com.client这个库,所以我估计 Mac下应该用不了,但可以修改代码绘制dxf文件,不调用CAD。 后续我再补充 Excel文件、输出CAD的文件及效果图 源代码 # _*_ coding:utf-8- _*_ from pyautocad import APoint, Autocad, aDouble import win32com.client import numpy as np dgj = 0.5 # 等高距 ctfs = 10 # 放大倍数,本身采取m为单位绘制,可能放大10倍后输出效果好些 """ 等高线计算 """ #连接excel读取数据,这个地方可以做一个前处理,直接把excel数据作为数组或者numpy数组进行处理 xlapp = win32com.client.Dispatch("Excel.Application") wb = xlapp.ActiveWorkbook ws = xlapp.ActiveWorkbook.ActiveSheet """ K58+70向右走为前进方向,绘制在 """ """ First 定义一个类,输入 list,其元素为APoint 内部函数得到插值的数据点,打印点数据 """ class nei_cha: def __init__(self, pnts = [APoint(0,1)], dgj = 0.5, gu_ding_cha_zhi = "X" ): # gu_ding_cz = "X" 意思是不进行固定插值操作 self.pnts = pnts self.dgj = dgj self.gu_ding_cha_zhi = gu_ding_cha_zhi # 输入两个三维坐标,x/y是相等的,内插得到所需高程 # 返回的是,该区间内得到的点组成的list def do_two_points(self, p1 = APoint(0), p2 = APoint(0)): if self.gu_ding_cha_zhi == "X": nmax = int(max(p1.z, p2.z) // self.dgj) nmin = int(min(p1.z, p2.z) // self.dgj) if nmax == nmin: # 这两个点之间内插不出来 return 0 else: nmax = self.gu_ding_cha_zhi nmin = self.gu_ding_cha_zhi - 1 if (p1.z - nmax) * (p2.z - nmin) > 0: # 固定插值不在区间内 return 0 if p1.x == p2.x: # x坐标一样,需要内插Z到y """ 求直线方程,y """ k = (p1.y - p2.y)/(p1.z - p2.z) b = p1.y - k * p1.z if self.gu_ding_cha_zhi == "X": ni = np.array(range(nmin, nmax)).reshape(int(nmax - nmin), 1) zi = (ni + 1) * self.dgj else: ni = np.array([self.gu_ding_cha_zhi]).reshape(int(nmax - nmin), 1) zi = ni yi = np.around(k * zi + b, 3) #yi = np.interp(zi, [p1.z, p2.z], [p1.y, p2.y]) xi = np.full((len(yi), 1), p1.x) pts_np = np.hstack((xi, yi, zi)) return pts_np else: # y坐标一样,需要内插Z得到x return 0 def do_it(self): pnts_np = np.array([]) for i in range(len(self.pnts) - 1): p_np_i = self.do_two_points(self.pnts[i], self.pnts[i+1]) if type(p_np_i) != type(0): try: pnts_np = np.vstack((pnts_np, p_np_i)) except: pnts_np = p_np_i if len(pnts_np) != len(np.array([])): return pnts_np else: return 0 # points是原始地面点高程 ground_points = [] row = 2 while row <= 20: i = 6 # 左侧数据 j = 8 # 右侧数据 # 桩号点绘图坐标 x0 = ((row - 2) / 3) * 10 + 70 y0 = 0 z0 = ws.cells(row, 7).value p0 = APoint(x0, y0, z0) pts = [] pts.append(p0) # 拾取左侧点数据 while i >= 1: try: z_ = ws.cells(row, i).value y_ = ws.cells(row + 1, i).value pti = pts[-1] + (0, y_, z_) pts.append(pti) except: pass i -= 1 # 拾取右侧点数据 while ws.cells(row, j).value: try: z_ = ws.cells(row, j).value y_ = - ws.cells(row + 1, j).value ptj = pts[0] + (0, y_, z_) pts.insert(0, ptj) except: print("右侧点拾取失败了:cells(%d,%d)"% (row, j)) pass j += 1 ground_points.append(pts) for i in pts: print(i) print("") row = row + 3 # 利用上方点开始使用类进行,插值 all_np = [] for i in ground_points: cha_zhi_la = nei_cha(i, dgj) a = cha_zhi_la.do_it() try: all_np = np.vstack((all_np, a)) except: all_np = a pts_all = [APoint(list(i)) for i in all_np] pts_all.sort(key = lambda x:x.z) del all_np h_min = pts_all[0].z h_max = pts_all[-1].z zzzi = h_min sorted_pts = [] while zzzi <= h_max: _ = [i for i in pts_all if i.z == zzzi] _.sort(key = lambda x:x[0]) sorted_pts.append(_) zzzi += dgj del pts_all for i in sorted_pts: elevation = i[0].z print("高程为 %s 的数据点"% elevation) for l_ in i: print(l_) # 连接cad,并输出结果 del sorted_pts[0:11] del sorted_pts[-10:-1] acad = Autocad(create_if_not_exists=True) acad.prompt("connect with the Autocad successfully.") print("connect with the Autocad successfully.") dwg = acad.ActiveDocument # 定义等高线图层 dgx = acad.doc.layers.add("等高线") dgx.LineWeight = 25 dwg.ActiveLayer = dgx dgxbz = acad.doc.layers.add("等高线标注") for m in range(len(sorted_pts)): i = sorted_pts[m] elevation = i[0].z print("高程为 %s 的数据点"% elevation) for l_ in i: print(l_) try: for j in i: j.z = 0 pt = aDouble([j for _ in i for j in _ * ctfs]) hl = acad.model.AddPolyLine(pt) hl.LineWeight = 25 hl.Elevation = elevation hl.Thickness = 900 if m % 5 == 0: hl.LineWeight = 100 hl.color = 1 text_string = elevation insertpt = i[0] * ctfs textobj = acad.model.addMtext(insertpt, 26, text_string) textobj.Height = 8 textobj.BackgroundFill = True textobj.color = 1 textobj.layer = "等高线标注" except: print('*' * 10, "高程为 %s 的数据点不足,跳过绘制此等高线"% elevation) pass

2022年5月24日 · 3 分钟 · Vinkey