在PDMS中使用python直接生成管口方位圖(開源分享第三集)
距離上一次發推送已有5個月之久,上周立了冬,這二季我為五鬥米折了腰,最近才緩過氣來。
令我沒想到的是,大家竟然對這個主題這麼有興趣,有關注者幾次在私信詢問我什麼時候更新,大家的期盼無形之中給了我繼續分享的動力。
上一集給大家介紹了如何生成裝置的輪廓及相位中心線。
這一集裡要完成生成3個頂部管口的平面圖形及位号标注功能。
其主要步驟如下:
1:提取裝置管口的基本資訊(這裡可以通過宏檔案在PDMS提取,本集不做詳細介紹),其提取的資訊要包含如下内容:管口号,管口端面型式,端面坐标,管口朝向,管口法蘭OD值及管口接管的OD值;
2:生成管口圖形,其圖形将以2個同心圓表示,這兩個同心圓分别表示法蘭外徑及接管端的外徑;
3:生成管口位号标簽(管口号外面以一個圈的型式表示)。
本集主要的精華部分在将管口圖形及管口位号标簽以塊的型式生成,特别是管口位号标簽塊是以屬性塊的型式表示(如下圖所示)。

其對應視訊如下:
原代碼如下(本集代碼與上一集代碼的增加集中在第81行至116行):
1 | __author__ = '[email protected]' |
2 | # [email protected] |
3 | import ezdxf # 導入ezdxf子產品 |
4 | import math # 導入math子產品 |
5 | # ezdxf 文檔網址為https://ezdxf.mozman.at/docs/ |
6 | dxfile = 'd:\\nozzdraft.dxf' # 将要生成的NOZZ方位檔案 |
7 | doc = ezdxf.new('R2010', setup=True) # 2010 格式, setup值為True時會加載預設的線型等設定,建議設定為True |
8 | doc.header['$INSUNITS'] = 4 # 檔案為mm為機關 |
9 | msp = doc.modelspace() # modelspace 與CAD裡的model模型相對應 |
10 | |
11 | # layer setting 下面将定義層建立一個清單 |
12 | # [層名稱 線型 顔色索引 線寬(-1表示預設,30表示的的是0.3mm, 線寬依次類推] |
13 | layerset = (['level_cl', 'CENTER2', 255, -1], # 中心線用 |
14 | ['level_nozz', 'CONTINUOUS', 3, 30], # 管口圖型用 |
15 | ['level_outline', 'CONTINUOUS', 1, 30], # 裝置外形用 |
16 | ['level_tagText', 'CONTINUOUS', 2, -1], # 管口TAG用 |
17 | ['level_Dim', 'CONTINUOUS', 1, -1], # 标注用 |
18 | ['level_brd', 'CONTINUOUS', 5, 30]) # 圖框用 |
19 | for layer in layerset: # 循環向圖形中加載清單中的層設定 |
20 | # 名稱 屬性 線型 顔色 線寬 |
21 | doc.layers.new(name=layer[0], dxfattribs={'linetype': layer[1], 'color': layer[2], 'lineweight': layer[3]}) |
22 | |
23 | # fonts setting 字型設定/建立一個清單 |
24 | # 【字型名稱 西文字型 中文字型 字型大小 寬度因子】 |
25 | fonts = (['nozz_Style', 'Tssdeng.shx', 'TSSDCHN.shx', 50, 0.75], |
26 | ['table_Style', 'romand.shx', 'TSSDCHN.shx', 50, 0.75],) |
27 | |
28 | for font in fonts: # 循環向圖形中加載字型設定 |
29 | doc.styles.new(font[0], dxfattribs={'font': font[1], 'bigfont': font[2], 'height': font[3], 'width': font[4]}) |
30 | styles = doc.styles |
31 | # /TK-2020,CYLI,13000mm,E 0mm N 0mm U 7250mm WRT /*,13500mm |
32 | # 以上為裝置資訊通過PML語言可以從PDMS提取,并以“,”為分隔依次表示裝置位号, |
33 | # /TK-2020 |
34 | # 直徑13000mm |
35 | # CYLI表示PDMS中的元件類型圓柱, |
36 | # 坐标E 0mm N 0mm U 7250mm WRT /* |
37 | # 13500mm高 |
38 | # 為簡化處理過程這次我們直接改寫成最終我們需要的清單型式,我們隻需要裝置位号,坐标X/Y對應該E/N, 圓柱直徑 |
39 | #eqpinfo = ['TK-2020', (0, 0), 13000] |
40 | eqpinfo = ['TK-2020', (0, 0), 13000] |
41 | eqpname = eqpinfo[0] # 裝置名稱 |
42 | eqpori = eqpinfo[1] # 裝置原點X/Y對應該E/N坐标 |
43 | eqpradius = eqpinfo[2]/2 # 裝置半徑 |
44 | ### |
45 | # 以下為使用add_circle()函數向dxf圖形中添加裝置的外圓圈 |
46 | msp.add_circle(eqpori, eqpradius, dxfattribs={'layer': 'level_outline'}) # level_outline來自layerset |
47 | |
48 | # 為畫出過圓心的中心線先定義一個函數linecoordinate(ori, cllen, angle)可以根據圓的中心點個中心線長及角度算出線起點和終點的坐标 |
49 | def linecoordinate(ori, cllen, angle): #ori:線要過的中心點坐示, clen:中心線長,angle在笛卡爾坐标系中的角度,今後會提到極坐标 |
50 | clenhalf = 0.5*cllen |
51 | angle = math.radians(angle) |
52 | pointsv = (ori[0]-clenhalf*math.cos(angle), ori[1]-clenhalf*math.sin(angle)) |
53 | pointev = (ori[0]+clenhalf*math.cos(angle), ori[1]+clenhalf*math.sin(angle)) |
54 | return pointsv, pointev |
55 | |
56 | |
57 | # 以下将為使用add_line()函數為裝置的外圓圈添加中心線 |
58 | pointendarr = [] #pointendarr用來接收中心線起始點的坐标。 |
59 | for deg in [0, 90]: #中心線就是0和90度 |
60 | #clhorpoint[0], clhorpoint[1], dxfattribs={'layer': layercl, 'ltscale': ltscale} |
61 | cllen = 1.2*eqpradius*2 #中心線按圓形的直徑1.2倍 |
62 | cllinepoint = linecoordinate(eqpori, cllen, deg) |
63 | msp.add_line(cllinepoint[0], cllinepoint[1], dxfattribs={'layer': 'layer_cl', 'linetype': 'CENTER2', 'ltscale': 1000}) |
64 | pointendarr.append(cllinepoint) # 把0°/90°起始點收到pointendarr清單中,下面為中心線端部添加0°,90°,180°, 270°文字要用到 |
65 | # cllinepoint[0]表示起點, cllinepoint[1]表示終點 |
66 | # 'layer_cl'來自layerset |
67 | # ltscale 表示線形比例為讓點畫線型比較合适表示建議設定為中心線長/10 |
68 | #以下将為中心線的兩頭添加0°,90°,180°, 270°文字, 定義了phase相位角的字典資料庫 |
69 | phasedeg = {90: (pointendarr[0][1], 'MIDDLE_LEFT'), |
70 | 0: (pointendarr[1][1], 'BOTTOM_CENTER'), |
71 | 270: (pointendarr[0][0], 'MIDDLE_RIGHT'), |
72 | 180: (pointendarr[1][0], 'TOP_CENTER')} |
73 | for deg in [0, 90, 180, 270]: |
74 | msp.add_text(str(deg) + '%%d', dxfattribs={'style': 'nozz_Style', 'height': 500, 'color': 6, 'width': 0.75}). set_pos(phasedeg[deg][0], align=phasedeg[deg][1]) |
75 | |
76 | msp.add_text(eqpname, dxfattribs={'style': 'nozz_Style', 'height': 1000, 'color': 4, 'width': 0.75}). set_pos(phasedeg[deg][0], align=phasedeg[deg][1]) |
77 | |
78 | |
79 | ########################### 以下第80行~116行為本次分享所補充的内容,本次要完成3個頂部管口的繪制及管口号的生成 |
80 | #Nozzle table 自PDMS中導出,此處不做介紹, 以下管口M,A,B為頂部的三個管口 |
81 | #以下的82~84中資訊以逗号為分隔,包括了管口号,管口端面型式,端面坐标,管口朝向,管口法蘭OD及管口管道的OD |
82 | nozztable = ['/TK-2020/M,600mm,FBP,E 0mm N 0mm U 15500mm WRT /*,U WRT /*,812.8,610', |
83 | '/TK-2020/A,200mm,FBP,E 4000mm N 4000mm U 15500mm WRT /*,U WRT /*,340,219', |
84 | '/TK-2020/B,200mm,FBP,W 4000mm N 4000mm U 15500mm WRT /*,U WRT /*,340,219'] |
85 | #以下的清單中元組表示需要對PDMS抽出來的坐标進行處理,如W, S, D表示“-” |
86 | directsign = [('WRT /*',''), ('E', ''), ('N', ''), ('U', ''), ('W', '-'), ('S', '-'), ('D', '-'), (' ', ''), ('mm', ',')] |
87 | #以下開始周遊第46中的清單,提取管口号,管口位置,管口外徑等資訊。 |
88 | for nozz in nozztable: |
89 | nozzarr = nozz.split(',') |
90 | nozzblkname = 'nozz'+nozzarr[0].replace('/', '_') #定義管口圖形block塊的名稱定義 |
91 | print(nozzblkname) |
92 | nozzpos = nozzarr[3] |
93 | for direct in directsign: |
94 | nozzpos = nozzpos.replace(direct[0], direct[1]) |
95 | nozzcoordinate = (float(nozzpos.split(',')[0]), float(nozzpos.split(',')[1])) |
96 | nozzflgOD = float(nozzarr[5]) #管口法蘭外徑,就是管口圖形中的外圈 |
97 | nozzpipeOD = float(nozzarr[6]) #管口接管的外徑,就是管口圖形中的内圈 |
98 | print(nozzcoordinate) |
99 | nozzflag = doc.blocks.new(name=nozzblkname) #開始向管口圖形block塊中添加圖形元素 |
100 | nozzflag.add_circle(eqpori, nozzflgOD*0.5, dxfattribs={'layer': 'level_nozz'}) |
101 | nozzflag.add_circle(eqpori, nozzpipeOD * 0.5, dxfattribs={'layer': 'level_nozz'}) |
102 | nozzflag.add_point(eqpori, dxfattribs={'layer': 'level_nozz', 'lineweight': 13}) |
103 | msp.add_blockref(nozzblkname, nozzcoordinate) #管口圖形block塊中添加圖形元素結束 |
104 | |
105 | tagblk = 'tag'+nozzarr[0].replace('/', '_') #定義管口位号(帶屬性)block名稱 |
106 | tagflag = doc.blocks.new(name=tagblk) #開始向管口位号block屬性塊中添加圖形元素 |
107 | tagflag.add_circle(eqpori, 150, dxfattribs={'layer': 'level_tagText'}) #管口号屬性塊的外圈 |
108 | tagflag.add_attdef('NAME', eqpori, dxfattribs={'style': 'nozz_Style', 'layer': 'level_tagText', 'height': 150}).\ |
109 | set_pos(eqpori,) #定義一個'NAME'字段做為屬性塊來存儲管号号 |
110 | inserttagPosX = nozzcoordinate[0] |
111 | inserttagPosY = nozzcoordinate[1] + 50 + nozzflgOD |
112 | insertagPos = (inserttagPosX, inserttagPosY) #這表示管口号屬性塊在圖面中的位置,其實就是位于管口号的正上方,看第75行, Y坐标有偏移 |
113 | blockref = msp.add_blockref(tagblk, insertagPos) #管口号屬性塊元素添加結束 |
114 | values = {'NAME': nozzarr[0].split('/')[2]} #為管口号屬性塊的"NAME"字段添加文字,如管口号"A" |
115 | blockref.add_auto_attribs(values) #管口号屬性塊的"NAME"字段屬性添加結束 |
116 | ########################### |
117 | doc.saveas(dxfile) # 儲存以上所有操作進dxf檔案中,下面可以去檢視'd:\\nozzdraft.dxf'下生成的檔案了 |
往期回顧:
在PDMS中使用python直接生成管口方位圖(開源分享第二集)
在PDMS中使用python直接生成管口方位圖(開源分享第一集)