以地籍庫為例介紹AutoCAD數據庫連接

以地籍庫為例介紹AutoCAD數據庫連接


李玲


(廣西第一測繪院)



【摘 要】 以地籍庫為例,介紹AutoCAD2000的數據庫連接功能dbConnect。通過地籍庫的建立及維護過程,介紹數據庫的連接、圖形與數據維護的一致性。


【關鍵詞】 AutoCAD 數據庫連接 維護 一致性



1 引言


  自從AutoCAD R12將AutoCAD SQL Extension (ASE)引入后,AutoCAD用戶就有了將AutoCAD對象鏈接到外部數據庫的能力。AutoCAD 2000將其所有的數據庫連接功能組合在一起,形成單一的易于理解的用戶界面,稱之為dbConnect,dbConnect完全取代了AutoCAD早期版本中老的ASE界面。在AutoCAD 2000中,數據庫連接的特點是基于微軟的OLE DB技術,通過一個組件對象模型(COM)編程界面——ActiveX數據對象(ADO),可以完全控制OLE DB。ADO能夠用在支持COM的任何計算機語言中,也包括AutoCAD編程環境,例如VBA 和 Visual LISP。本文以地籍庫為例,以Visual LISP為編程環境,介紹AutoCAD 2000的數據庫連接及圖形與數據庫維護的一致性。


2 圖形與數據庫的連接


  在AutoCAD中,用數據庫進行任何工作之前,必須先建立到數據庫的連接。


2.1 建立數據庫連接


2.1.1 配置數據源


  設D:\宗地\目錄下有Access的Parcel.mdb文件,其中表Table1,表的結構如下:


  Table1:



ID 街道號 街坊號 宗地號 土地利用類別 權屬人 宗地面積



  現在要在名為Parcels的圖形中連接Parcels.mdb,連接方法可以手工連接,也可以用程序自動連接。手工連接的方法如下:


  1)打開parcels.dwg


  2)從Tools菜單中選擇dbConnect。出現dbConnect管理器。


  3)在dbConnect管理器中右擊Data Sources,并從捷菜單中選擇Configure a Data Source,顯示Configure a Data Source對話框。


  4)鍵入 parcels作為數據源名,點擊OK。出現Data Link Properties對話框。


  5)在OLE DB Providers列表框中選擇Microsoft Jet 3.51 OLE DB Provider,按Next>>。


  6)鍵入Parcel.mdb文件的完整路徑。


  7)點擊Test Connection 校驗連接是否建立。


  8)點擊OK。


  一旦數據源配置完成,在DATA Links目錄生成一個UDL文件,它的名字出現在dbConnect管理器窗口中的Data Sources節點下。


  自動創建連接的過程其實就是通過程序創建如上所述的UDL文件的過程,這里不再詳述。


2.1.2 用ADO獲取連接到AutoCAD設置的數據源


  用LoadAdo函數獲取連接到ACAD設置的數據源,為下面的函數連接數據庫作準備。


(defun LoadAdo( / gADO-DLLpath )


  (vl-load-com) ;裝載ActiveX


  (setq acadObj (vlax-get-acad-object)


     acadDoc (vla-get-ActiveDocument acadObj)


  gADO-DLLpath "c:\\program files\\common files\\system\\ado\\msado15.dll")


(if (null ado-adOpenDynamic)


(vlax-import-type-library


  :tlb-filename gADO-DLLpath


  :methods-prefix "ado-"


  :properties-prefix "ado-"


  :constants-prefix "ado-"


  ) ;裝載ADO Library


)


(setq ADOConnect (vlax-create-object "ADODB.Connection")) ;創建全程變量ADOConnect


(setq wsPath (vlax-get-property


        (vlax-get-property


           (vlax-get-property


                (vlax-get-acad-object)


           "Preferences"


         )


        "Files"


         )


        "WorkspacePath"


     )


   name ( getvar "dwgname")


   len (strlen name)


   name (substr name 1 (- len 3))


   name (strcat name "udl")


adoString (strcat "File Name=" wsPath "\\" name ";User ID=;Password=;" )


) ;取數據源udl文件路徑


(vlax-put-property ADOConnect "ConnectionString" adoString)


; ADOConnect 將 name.mdb 連接到name.udl文件


(vlax-invoke-method ADOConnect "Open" adoString "" "" -1)


); end LoadAdo


2.2 建立鏈接模板


2.2.1建立鏈接模板


  鏈接對象到數據庫之前,必須先建立鏈接模板,建立鏈接模板的過程如下:


  1)打開上面已連接數據庫的Parcels圖形。


  2)打開dbConnect管理器并連接到parcels數據源。


  3)右擊Table1表,并選擇New Link Template。顯示New Link Template對話框。


  4)將鏈接的默認名稱Table1_DataLink1改為Parcels(與圖形名相同)。點擊Continue進入Link Template對話框,點擊ID旁邊的框指定ID為關鍵列,然后點擊OK?,F在dbConnect管理器中會看到在圖形parcels下面的Parcels節點。


2.2.2 用CAO獲取鏈接模板


(defun LoadCao( / linkTemplates name linkname MDBname len index)


 (if (null caom-GetLinkTemplates) ;檢查CAO library 是否裝載


 (progn


  (vlax-import-type-library


   :tlb-filename "cao15.dll"


   :methods-prefix "caom-"


   :properties-prefix "caop-"


   :constants-prefix "caok-"


  ) ;裝載CAO Liabrary


))


(setq CAOConnect (vlax-create-object "CAO.DbConnect"))


(setq linkTemplates (vl-catch-all-apply 'caom-GetLinkTemplates


          (list CAOConnect acadDoc))


)


 (setq name (getvar "dwgname")


    len (strlen name)


    name (substr name 1 (- len 4))


    index 0


    count (vlax-get-property linkTemplates "Count")


   MDBname ""


   linkTemplate nil


  )


(while (< index count)


(setq linkTemplate (vlax-invoke-method linkTemplates "Item" index)


    linkname (vlax-get-property linkTemplate "Name")


    MDBname (vlax-get-propertylinkTemplate "DataSource")


    index (1+ index)


)


   (if (= name MDBname)


    (setq index count)


   )


);在圖形鏈接模板庫中搜尋Parcels鏈接模板


 (if (/= name MDBname)


   (setq linkTemplate nil)


 )


linkTemplate ;使函數返回Table1的鏈接模板


)


2.3宗地與數據庫的自動鏈接


  在parcels圖形中畫一權屬界線,并將其鏈接到數據庫(以界線對應的圖形句柄作為數據庫中表Table1的ID號,因為AutoCAD中圖形句柄是唯一的):


(defun draw (/)


 (setq p (getpoint \n權屬界線第一點:))


 (while p


  (setq plist (append plist (list p)))


  (setq p (getpoint \n下一點:))


)


(if plist


(progn


 (setq ename (LandPline plist));函數LandPline根據節點列表畫出權屬界線,并返回對應的實體名


 (append_DB ename) ;在數據庫中加入權屬界線對應的數據記錄


 (MakeLink ename) ;將權屬界線鏈接到數據庫中對應的數據記錄


))


);end defun draw



  其中,append_DB及MakeLink函數定義如下:


(defun append_DB (ename / Object ID area m_plist RS fields fields Count Index


             thisField value)


 (setq Object (vlax-ename->vla-object ename))


       ID (vla-get-Handle Object) ;取實體的句柄


      area (vla-get-area Object) ;取實體面積


)


(setq m_plist (list ID "" "" "" "" "" (rtos area 2 6)));預定義數據記錄各字段的數值


(cond


  ; Create the ADO Recordset object


  ((null (setq RS (vlax-create-object "ADODB.Recordset")))


  (princ "\nUnable to create ADODB.Recordset object.")


)


  ((null (ok 'ado-Open (list RS "Table1" ADOConnect ado-adOpenDynamic


          ado-adLockOptimistic ado-adOptionUnspecified)));其中ADOConnect為函數LoadADO中返回的數據庫連接


)


(T


  (ado-AddNew RS) ;在Table1中追加一空白記錄


  (setq fields (ado-get-Fields RS)


     fieldsCount (vlax-get-property fields "Count")


        index 0


)


  (while (< index fieldsCount)


  (setq thisField (vlax-get-property fields "item" index)


       value (nth index m_plist)


       index (1+ index)


  )


  (ado-put-Value thisField value ) ;將預定義的數值賦予各字段


 ) ;將空白記錄各字段賦值


 (ado-Update RS) ;向數據庫提交變化


)


);end cond


  (ReleaseRS RS)


);End Defun append_DB


 (defun ReleaseRS (RS)


  (if RS


  (progn


   (if (= (ado-get-State RS) ado-adStateOpen)


    (ado-Close RS)


   )


   (vlax-release-object RS)


   (setq RS nil)


  ))


)


  以上的append_DB在數據庫記錄中加入ID和宗地面積,使宗地圖形與數據庫記錄一一對應,宗地的其他屬性可以在數據庫中手工錄入。


(defun MakeLink( ename / VlaObj objectID vlax-obj currKeyValues OneKeyValue linkResult)


  (setq linkTemplate (LoadCao))


  (setq VlaObj (vlax-ename->vla-object ename)


  objectID (vla-get-Handle VlaObj)


  vlax-obj (vlax-get-property VlaObj "ObjectID")


 currKeyValues (vlax-create-object "CAO.keyValues")


  OneKeyValue (vlax-create-object "CAO.KeyValue")


)


(vlax-put-property OneKeyValue "FieldName" "ID")


(vlax-put-property OneKeyValue "Value" objectID)


(vlax-invoke-method currKeyValues "Add" OneKeyValue)


(setq linkResult (vl-catch-all-apply 'caom-CreateLink (list linkTemplate lax-obj currKeyValues) ))


 (if (vl-catch-all-error-p linkResult)


     (princ "\n Trying to execute CreateLink() caused an ActiveX error:")


 )


);end defun MakeLink


3 圖形與數據的一致性


  宗地的變化包括權屬界線的節點的變化(刪點、增點、移點)和宗地的分割、合并。節點的變化僅引起圖形和數據記錄的改變,圖形與數據間的鏈接關系不變;宗地的分割、合并不僅會引起圖形的變化、記錄的增減,圖形與數據間的鏈接關系也相應發生改變。


3.1 權屬界線節點變化


  以移點為例:


  (defun c:MoveDot ( / ename ss point newpoint oldpoint xylist vlaxobj objID area)


  (setq point (getpoint "\n請選待移動的界址點: [或回車=退出]"))


  (if point


  (progn


   (setq newpoint (getpoint "\n移動到點:"))


   (setq ss (ssget point))


   (setq ename (ssname ss 0))


   (setq xylist (GetPlXY ename) ) ;函數GetPLXY取界線的節點列表


   (setq oldpoint (Plist-DotAt xylist point) ;函數Plist-DotAt返回節點列表中最靠近point的節點


   (Update-ename ename oldpoint newpoint) ;函數Update-ename將界線對象ename中的oldpoint替換成newpoint


   (setq vlaxObj (vlax-ename->vla-object ename)


      objID (vla-get-Handle vlaxObj)


      area (rtos (vla-get-area vlaxObj) 2 6)


   )


  (setq SQLstr (strcat "UPDATE " table " SET 宗地面積='"area "' where ID='" objID "'" )) ;定義SQL語句


    (if (null (ok 'ado-Execute (list db SQLstr nil ado-adOptionUnspecified))) ;執行SQL語句,將數據記錄中的宗地面積更新


  (progn


  (princ "\nUnable to Update record.")


  (exit)


  ))


)


3.2 宗地分割與合并


  以宗地分割為例,如圖1所示:權屬界線由點1至點7構成,分割線由點t1至點t3構成,分割線將宗地分割為Z1、Z2宗地。




  (defun c:Split ( / ename iename xylist inplist plist enam1 ename2 vlaxObj ID SQLstr)(setq ename (car(entsel \n選取欲分割的權屬界線:))


(setq iename (car (entsel \n選取分割線:)))


(setq inplist (GetPlXY iename)) ;函數GetPlXY 返回分割線節點列表


(setq xylist (GetPlXY ename));函數GetPlXY 返回權屬界線節點列表



(setq plist (SplitPlist xylist inplist));SplitPlist函數返回分割后的兩個復合線列表:((點1 點2 i1 t2 i2 點7) (i1 點3 點4 點5 點6 i2 t2))


(setq xylist1 (car plist) xylist2 (cadr plist))


(setq ename1 (LandPline xylist1) ename2 (LandPline xylist2))


LandPline函數根據節點列表構造權屬界線,并返回界線對應的實體名


(setq vlaxObj (vlax-ename->vla-object ename)


    ID (vla-get-Handle vlaxObj)


)


(setq SQLstr (strcat "DELETE FROM " table " where ID='" ID "'") )


(if (null (ok 'ado-Execute (list ADOConnect SQLstr nil


               ado-adOptionUnspecified)))


 (progn


  (princ "\nUnable to delete record.")


  (exit)


 )


)


  ;執行SQL語句,將原權屬界線對應的數據記錄刪除,相應的鏈接關系也被刪除


  (command "erase" ename "") ;將原權屬界線刪除


  (append_DB ename1) ;在數據庫中建立宗地Z1對應的數據記錄


  (Make_Link ename1) ;將宗地Z1的權屬界線鏈接到對應的數據記錄


  (Append_DB ename2) ;在數據庫中建立宗地Z2對應的數據記錄


  (Make_Link ename1) ;將宗地Z2的權屬界線鏈接到對應的數據記錄


);End Defun Split


4 結束語


  本文以地籍庫的建立及維護過程為例,較詳細的介紹了AutoCAD2000的數據庫連接dbConnect功能。出于篇幅考慮,文中與dbConnect無緊密聯系的函數略去不表。希望本文能對讀者取到參考作用。



參考文獻:


[1] ?。溃㏒cott McFarlane著;羅阿理等譯.AutoCAD數據庫連接.機械工業出版社,2001.5


[2]  郭劍蜂,陳杉,王寧編著.用Visual LISP開發AutoCAD 2000應用程序. 人民郵電出版社,2000.1


[3]  湯峻編.AutoCAD2000高級應用與Visual LISP 開發寶典. 人民郵電出版社,2001.1


登錄后免費查看全文
立即登錄
App下載
技術鄰APP
工程師必備
  • 項目客服
  • 培訓客服
  • 平臺客服

TOP