2026年3月20日 星期五

[AutoTower] 自訂變數

    有別於 AutoCAD 變數,自訂變數對於自己寫的程式來說特別重要,尤其是要寫一整套的外掛(3rd Party Program)。

    AutoCAD 是一套通用型繪圖系統,它並沒有為使用者特別制定繪圖時的單位與比例,有的只是 1 單位,而這個「單位」可以是 1inch、1mm 或 1cm...。

    想要寫一整套的外掛程式,就得對圖紙單位和比例加以設定與管理,尤其是在一個模型空間中同時擁有不同繪圖單位與比例尺的圖面。每一張圖紙都有它自己的繪圖單位與比例尺,但模型空間只有一個,此時就需要自訂變數,好讓程式們在運作時畫出適當比例的圖形。

    在 AutoCAD 裡的自訂變數與一般程式 (例如 C 或 Python) 的變數大同小異,如果你會寫程式,那麼一些觀念都可以應用到這裡。


AutoCAD 變數類型

整數(Integers)
實數(reals)
字符串(Strings)
列表(lists)
選擇集(Selection sets)
實體名(entity names)
vla對象(VLA-objects)
文件描述符(file descriptors)
符號和變量(Symbols and Variables)


自訂變數類型

項目自然繼承自 AutoCAD,但似乎可以精簡一些。



預定義的常數

AutoCAD 常數 0 或 PI 可以用來表示 0度和 180度,但在程式裡使用到其他角度的機會也很多,例如 90 度、270度...之類的。你應該不會寫上數萬次諸如下列的語句吧?

(setq 90deg (* PI 0.5))

(setq 270deg (* PI 1.5))

此時你應該可以想到這麼做,在主程式裡寫上

(setq 90deg  (* PI 0.5))        

        270deg (* PI 1.5)

)

在啟用 AutoCAD 時順便將其載入到記憶體,然後你就可以用 90deg 和 270deg 來代表 90度和 270度了。


再例如,你也可以將所有角鋼規格設為預定義常數,例如

(setq StlAngle ("L45x4" "L60x5" "L75x6"...))

(setq StlAngle ("L45x4,R,W" "L60x5,R,W" "L75x6,R,W"...))


管理自訂變數

建立變數名稱的規則

全域變數的優點是存取方便快速,但具有被其他使用者 '汙染' 的風險。以全域變數名稱「DwgScale」為例,你存放的值是「30」,而後來他人程式存的值是「1:30」,接著你再取出來用,此時將會造成不可預期的後果,不是變數的型態錯誤就是變數值超過範圍。解決的方式是在你的變數名稱加入前綴字元,例如 'at$'。

儲存在圖面字典裡的變數會跟著圖面走,它雖然不像全域變數那般方便存取,但卻具有不被其他使用者 '汙染' 的風險。你可以將

'AutoTower' 命名為字典名稱,除非他人也同樣使用 'AutoTower'  這個字典名稱。

外部檔案可以讓使用者直接修改變數值,它最大的風險是檔案內容被改到壞掉,變成格式錯亂或無法取檔案。

像 AutoCAD 那樣擁有管理自訂變數的指令

(at_varSet   var   val)  存入變數

(at_varGet   var   val   filename)  取出變數

c:atVarManager 可以管理數個變數檔案。


實作

在開發 AutoCAD 第三方軟體時,為了避免「寫死」(Hard-coded)參數並兼顧使用者的修改便利性,通常會採用層級式管理

以下是針對您的需求,建議的儲存位置選擇以及資料存取流程:


1. 自訂變數的儲存位置選擇

根據資料的性質(是屬於「個人偏好」還是「圖面規範」),通常會分開存放:

A. 外部檔案(設定檔):適合「全域參數」

這類變數與特定圖檔無關(例如:公司標準圖層名稱、零件路徑、UI 顏色)。

  • 格式: 建議使用 JSONXML(Lisp 可搭配 VL-FILENAME-BASE 讀取,Python 則有內建模組)。

  • 優點: 繪圖者可以直接用記事本修改,不需打開 AutoCAD。

  • 管理: 存放在軟體安裝目錄或 AppData 使用者資料夾下。

B. 命名物件字典 (Named Object Dictionary, NOD):適合「圖面參數」

這類變數隨 DWG 檔案保存(例如:這張圖的比例、特定計算結果、輸電塔的坡度參數)。

  • 機制: 在 DWG 內部的隱藏資料庫中建立 XRecord

  • 優點: 繪圖者在介面上看不到,不會誤刪,但程式可以隨時讀取。

  • 存取: 透過 (dictsearch (namedobjdict) "MY_APP_VAR") 存取。

C. 圖元擴展資料 (XData):適合「對象參數」

當變數必須綁定在某個特定的「物件」(如某根電桿、某個圖框)時使用。


2. 變數存取與回存的順序邏輯

為了確保靈活性與正確性,建議採用以下**「優先級讀取順序」**:

第一階段:啟動與載入 (Loading)

  1. 讀取預設值: 程式內部定義一組最基本的 Default 值(防錯機制)。

  2. 讀取外部設定檔: 覆蓋預設值,取得使用者的全域偏好。

  3. 掃描圖面字典 (NOD): 如果該圖檔已存在舊有的設定,以此為準(因為這代表該圖檔的特定規格)。

  4. 存入記憶體 (Global Variables): 將最終決定的數值存入 Lisp 全域變數或 Python 物件中,供指令執行時快速調用。


變數讀取順序:
程式預設值 > 如果全域變數為真則取代預設值 > 如果圖面字典為真則取代預設值 > 如果外部檔案為真則取代預設值 
(defun at_varGet  (變數名稱  預設值  外部檔案) ...

變數儲存順序:
同時儲存到全域變數和圖面字典。
(defun at_varSet  (變數名稱  值) ...

外部變數檔案管理:
使用交談框存取檔案。
(defun c:atVarManager () ...


第二階段:執行與互動 (Interaction)

  1. 顯示對話框 (DCL): 將目前的變數顯示在 UI 上。

  2. 使用者修改: 繪圖者在介面上即時調整。

  3. 暫存變數: 使用者點擊「確定」後,先更新記憶體中的變數。


第三階段:儲存與同步 (Saving)

  1. 寫回圖面 (NOD): 立即將修改後的參數同步回該 DWG 的字典中,確保存檔後資料不遺失。

  2. (選配)更新外部檔案: 如果使用者勾選「設為往後預設值」,則將數值寫回外部 JSON/XML。


3. 實務建議架構

變數類型儲存媒介使用者修改方式
全域環境設定.json / .cfg 檔案外部編輯器或軟體設定頁面
圖面專屬參數XRecord (Dictionary)程式提供的對話框 (DCL)
暫存運算值Setq / Global Var僅限程式執行期間自動處理

管理技巧:

  • 版本控制: 在儲存資料時,建議多存一個 Version 欄位。當未來軟體升級、變數結構改變時,程式可以判斷是否需要進行資料格式轉換。

  • 防呆機制: 讀取外部檔案或字典時,務必加上 if 判斷,若資料毀損或不存在,需能自動回退 (Fallback) 到預設值。

這樣的方式既保證了程式的靈活度,也能讓繪圖者在不需要接觸代碼的情況下,透過 UI 或設定檔輕鬆完成自訂。


指令

(at_ldataSet "DwgScale" "1:40")    將變數值存入圖檔中

(at_ldataGet "DwgScale")    從圖檔中讀取變數值


at$FnVariable 公用變數的值為 "C:\\AutoTower\\User\\_Variable.txt"

(at_ldataImport (setq fn at$FnVariable))  匯入AutoTower變數

(at_ldataExport (setq fn at$FnVariable))  匯出AutoTower變數:

c:atSetvar   列出所有AutoTower存在圖檔內的變數


沒有留言:

張貼留言