劉超 湯人杰 尹竹瑩
(中車株洲電力機車有限公司 湖南株洲 412001)
軌道交通車輛牽引計算需要使用線路的坡度和坡長數據。傳統的提取方式為人工讀取CAD文件,將數據逐一錄入到Excel 中。在CAD 文件中,與整條線路相比,坡度坡長數據的字體不大;相鄰數據間隔較大。若放大圖紙,一次讀取的數據較少,將大幅增加錄入時間;若不放大圖紙,某些數字容易讀錯,將直接影響牽引計算的精度。
基于VBA的CAD二次開發功能,可以使用程序批量處理大量文檔數據,已經用于軟件及插件開發[1-2]、圖紙繪制及修改[3-8]、數據提取[9-11]等。
為自動提取坡度坡長數據,本文編寫了VBA 程序。讀取設計坡度和設計標高所在圖層的數據,將其導出到Excel,排序后確定上行線、下行線和環線數據,通過設計標高得到坡度值的正負號。實際應用結果驗證了程序的有效性和可行性。
通過InputBox( )得到手動輸入的設計坡度、設計標高圖層名稱。
一張圖紙中可能同時存在上行線、下行線、環線,不同線路設計坡度、設計標高所在圖層的名稱可能不同,故需要判定是否包含多個圖層,若存在多個圖層,分離出每個圖層名稱和圖層總數。
對于設計標高圖層的數據,若圖層名稱和設計標高圖層名稱相同、類型為文本,則將字符串、坐標保存到數組中,通過計數器變量實時更新總數。
設計坡度圖層中除了坡度和坡長以外,還存在旋轉了90°的數據,如圖1 所示,故除了圖層名稱和類型需滿足要求外,還需限定旋轉角度為0。
圖1 圖紙示例
設計坡度圖層中,每一段路程的起點和終點有一條豎線,如圖1 所示,讀取豎線的坐標,用于匹配坡度坡長數據、更新起點站和終點站的坡長。
本文使用的是中望CAD,文本、線條類型分別為ZcadText和ZcadLine。不同類型的對象的屬性不完全相同,故在獲取數據時,滿足類型相同后才判斷其他條件。
一般圖紙中起點站左邊、終點站右邊均存在少量線路數據,故需要獲取起點站、終點站的坐標,用于標記有用數據。
每條線路最左側會有注釋,如圖1 中的“設計坡度”和“設計標高”。獲取“設計坡度”和“設計標高”的坐標,用于分離每條線路的數據。
圖紙中文字可能存在空格,如“設 計 標 高”,故對于文本類型的對象,需要對每個字符進行匹配,同時滿足時將坐標存儲于數組中。
若圖紙只有一條線路,默認為上行線;若包含環線且終點站在環線上,默認環線位于上行線或下行線的右側。
CAD VBA 讀取數據的原則是根據數據放置的先后順序,則讀取的數據不一定按照橫坐標從小到大的順序排列,本文借助Excel 對其進行排序。通過CAD VBA 新建Excel 文件,新增3 個空白工作簿,分別保存坡度坡長、標高、豎線的數據。
寫入數據時,先將保存在數組中的變量賦值給Variant變量,再賦值給Excel,將無用的數據清除。
將豎線的橫坐標按照升序進行排序,調整豎線的起點和終點,始終滿足起點的縱坐標小于終點的縱坐標。
圖2 為每條線路的標注,一般設計標高和設計坡度不在兩端,則兩條線路之間的距離大于豎線的長度。此外,同一條線路的豎線的長度不一定相同,可能存在細微偏差,如圖3所示。
圖2 圖紙標注示例
圖3 上行線和下行線劃分
記橫坐標最小的豎線V0的起點坐標和終點坐標分別為(xst,yst)和(xed,yed),長度為l0。以V0為基準,將y≥yed+l0的豎線標記為上行線,此時上行線標志位flag_sxx=1;y≤yst-l0的豎線標記為下行線,下行線標志位flag_xxx=1;yed-l0≤y≤yst+l0的豎線標記為中線,如圖3所示。
(1)若flag_sxx=1 且flag_xxx=1,則同時存在上行線、下行線和環線,此時不更新標記。
(2)若flag_sxx=1且flag_xxx=0,則存在一條線路在上方,默認縱坐標大的線路為上行線,將中線改為下行線。
(3)除上述情況外,將中線改為上行線。
更新標記后,進行以下處理。
(1)按照標記升序的原則進行排序。
(2)對于相鄰、橫坐標之差小于1 的豎線,刪除其中一條。
(3)確定上行線和下行線的分界點和分界線,見圖4。
圖4 上行線和下行線分界線
分界線縱坐標表達式為ysx=(ysxx0+yxxx0)/2,ysxx0、yxxx0分別為上行線第一條豎線起點縱坐標和下行線第一條豎線終點縱坐標。若圖紙中只有一條線路,則ysx=0。
通過分界點確定下行線數據個數,可能存在個別上行線豎線偏離其他豎線,被判定為下行線的情況,故假定下行線數據個數大于3個時才計算分界線。
若存在環線,環線數據位于上行線或下行線數據中,則存在一個“設計坡度”的橫坐標xzy滿足(xzy-xxx0)(xzy-xxxk)<0,其中xxx0、xxxk分別為上行線或下行線的起點和終點的橫坐標,設定該橫坐標xzy為環線的分界線。
將上行線和下行線中橫坐標大于xzy的豎線標記為環線。
通過ysx將標高數據標記為上行線和下行線,然后按照標記升序進行排序,確定上行線和下行線的分界點;通過xzy標記標高環線數據。
相鄰標高數據,若滿足標高值、橫坐標和縱坐標之差的絕對值小于1,則刪除其中一個標高數據。圖5是環線分界線圖。
圖5 環線分界線
可能存在位于兩條豎線之間的標高值,如圖6 所示。一條豎線對應一個標高數據,對于第k個標高數據,從第k-n條豎線開始判斷,若標高的橫坐標和豎線的橫坐標之差的絕對值大于10,清除該行的標高數據。n為第k個標高數據之前被清空數據的標高的總數,每清空一個標高數據時通過n=n+1更新n值。所有的標高數據均核對后,將清空形成的空白行刪除。
圖6 冗余的標高數據
和標高數據的處理方式相同,通過ysx和xzy標記上行線、下行線和環線。排序后確定上行線和下行線的分界點。
將坡度坡長數據放到左側最近的標高數據所在行,以圖6為例,將坡度值-2、坡長值430及坐標放到標高11.64所在行。
由于同一組坡度坡長未合并到同一行,對于第n個坡度坡長,從第Roundup(n/2)個標高數據開始遍歷,當坡度或坡長的橫坐標介于第m個和m+1個標高的橫坐標之間時,將第n個坡度坡長放在第m個標高數據所在行,滿足先坡度后坡長;然后通過標高值確定坡度的正負號,若第m個標高值大于第m+1個標高值,則坡度符號為正,否則為負。
只考慮兩種站點標注方式,第一種如圖7所示,每個站點標注了相鄰站點的名稱。
圖7 站點標注
第二種只標注每個站點的名稱。站點個數為奇數時,以中間站為真實站點;為偶數個時,對于起點站,以橫坐標較小的為真實站點;對于終點站,以橫坐標較大的為真實站點。
如圖8所示,以起點站為例,起點站到右側豎線的距離表達式為d=p(xn+1-xqdz)/(xn+1-xn),p為坡度值,xqdz、xn、xn+1分別為起點站、第n條豎線、第n+1條豎線的橫坐標。
圖8 起點站路段
對于起點站,直接更新第n個標高所在行的坡長值;對于終點站,在第n個和第n+1 個標高之間插入空白行,此時空白行為第n+1個數據,將第n行賦給第n+1行,更新第n個和第n+1個坡長值。
若存在環線,默認終點站左側的數據屬于上行線,右側數據屬于下行線。按照上行線/下行線、環線進行排序,排序后下行線數據順序為先環線再主線,按照橫坐標從大到小的順序對主線進行排序。保存提取的數據默認保存在D盤根目錄。
以某項目為例,無環線,上行線和下行線分別單獨放在一張圖紙中。程序運行后,彈出4個對話框,分別要求手動輸入坡度圖層、標高圖層、起點站名稱、終點站名稱,如圖9所示。
圖9 輸入對話框
4個對話框均輸入后,程序自動運行,輸出的部分結果如圖10 所示,原始圖紙如圖11 所示。坡度值、坡長值滿足要求,坡度的正負號符合要求。
圖10 提取的部分數據
圖11 原始圖紙
該圖紙中存在個別坡度坡長數據的圖層為0,如圖12所示,程序讀取的結果如圖13所示。
圖12 坡度坡長異常數據
圖13 坡度坡長異常數據提取結果
該路段不在兩端,坡度坡長數據為空,標高不為空,設計人員可以通過標高值快速找到異常數據的位置。
以包含環線的項目的圖紙進行測試,部分結果如圖14 所示。上行線最后一條豎線沒有對應的坡度坡長值,和實際相符。
圖14 環線提取結果
由上述結果可知,程序提取結果滿足要求。
為了自動從CAD 圖紙中提取線路的坡度坡長數據,編寫了VBA 程序,只需人工輸入起點站和終點站名稱、坡度坡長和標高所在圖層,操作簡單。測試結果表明:由程序提取的坡度坡長的準確性滿足要求;與傳統方法相比,大幅減少了數據錄入的時間。