■ 李玲
(廣西壯族自治區(qū)地理國情監(jiān)測院廣西南寧530023)
基于AutoCAD的多段線點坐標提取
■李玲
(廣西壯族自治區(qū)地理國情監(jiān)測院廣西南寧530023)
本文主要介紹AutoCAD不同類型的多段線數(shù)據(jù)存儲結(jié)構及相應的點坐標提取算法。
多段線坐標凸度弧段逆時針順時針樣條擬合
在AutoCAD中,實現(xiàn)要素的制圖表現(xiàn)或提取坐標信息的過程中,我們不可避免地要讀取要素骨架線(點)的圖形信息特別是空間信息,以確定相輔的點、線、文本的空間位置。AutoCAD中點、線段、文本、插入塊等的坐標提取都相對簡單,相對于其他實體,多點線段也稱多段線或稱復合線(以下統(tǒng)稱多段線)在AutoCAD中有不同的表現(xiàn)形式和存儲結(jié)構,其線上的結(jié)點坐標提取也較為復雜。
自R14版本的AutoCAD開始,多線段由原來的POLYLINE分化為LWPOLYLINE和POLYLINE,兩種類型的多段線在AUTOCAD中的存儲結(jié)構不一致,表現(xiàn)形式也多種多樣:
LWPOLYLINE為簡單實體,其實體存儲列表中可以通過簡單的函數(shù)獲取。LWPOLYLINE多段線上每個結(jié)點的高程一致,整根線段的標高由其實體存儲列表中的組碼38對應的數(shù)據(jù)項決定,實體存儲列表中組碼70對應的數(shù)據(jù)項為LWPOLYLINE的特征值,設特征值的二進制形式如下:
其中,當X0值為1時LWPOLYLINE為閉合線,當X7值為1 時LWPOLYLINE整段線線型規(guī)范化表示。在表現(xiàn)形式上,LWPOLYLINE可分為:折線LWPOLYLINE——結(jié)點與結(jié)點間以直線段相連接;含弧段的LWPOLYLINE——結(jié)點與結(jié)點間或以直線段相連,或以弧段相連。LWPOLYLINE也稱超輕線,存儲所占字節(jié)相對POLYLINE較小,但LWPOLYLINE一經(jīng)曲線光滑處理(算法分擬合和樣條擬合兩種)后,其數(shù)據(jù)類型就會轉(zhuǎn)換成POLYLINE。
POLYLINE為復雜實體:多段線為主實體,有相應的實體存儲列表,線上的每個結(jié)點為子實體,在圖形中各自有相應的實體存儲列表。每個結(jié)點允許有不同的高程值,因此,POLYLINE也稱三維多段線。整根POLYLINE的結(jié)點搜索要通過由主實體引導的每個子實體存儲列表的循環(huán)來完成。POLYLINE主實體存儲列表中組碼70對應的數(shù)據(jù)項為POLYLINE的特征值,設特征值的二進制形式如下:
其中,當X0值為1時POLYLINE為閉合線,當X7值為1時POLYLINE整段線線型規(guī)范化表示,當X1為1時POLYLINE為擬合法生成的光滑曲線,當X2為1時POLYLINE為樣條擬合法生成的光滑曲線。在表現(xiàn)形式上,POLYLINE可分為:折線POLYLINE——結(jié)點間以直線段相連,擬合POLYLINE——由擬合法生成的光滑曲線,樣條POLYLINE——樣條擬合法生成的光滑曲線。
LWPOLYLINE和POLYLINE不同的存儲結(jié)構和多種表現(xiàn)形式導致在點坐標提取中要詳細分析,分別處理。
如前所述,LWPOLYLINE在表現(xiàn)形式上,可分為:折線LWPOLYLINE——結(jié)點與結(jié)點間以直線段相連接和含弧段的LWPOLYLINE——結(jié)點與結(jié)點間或以直線段相連,或以弧段相連。在地形圖的數(shù)據(jù)采集中,許多要素如圍墻、鐵路、房屋、道路等通常用LWPOLYLINE多段線表示,而在要素的骨架線采集中,經(jīng)常需要在多段線中加入弧段:如弧形陽臺,弧形圍墻等等。
我們先來看看LWPLOLYLINE的數(shù)據(jù)結(jié)構。
如圖1為一LWPOLYLINE多段線,結(jié)點1,2間為直線段,結(jié)點2,3間為弧段a1,其圓心為點c1,結(jié)點3,4間為弧段,其圓心為c2,結(jié)點4,5間為直線段。在AUTOCAD中獲取此多段線的實體存儲列表如下:
((-1.<圖元名:4009a500>)(0."LWPOLYLINE")(330.<圖元名:4008cc10>)(5."118")(100."AcDbEntity")(67.0)(410."Model") (8."0")(100."AcDbPolyline")(90.5)(70.0)(43.1.0)(38.0.0)(39. 0.0)(10 80.7448 199.489)(40.1.0)(41.1.0)(42.0.0)(10 127.561 129.576)(40.1.0)(41.1.0)(42.0.366517)(10 215.933 104.344)(40. 1.0)(41.1.0)(42.-0.366517)(10 311.471 77.0665)(40.1.0)(41.1.0) (42.0.0)(10 383.645 100.228)(40.1.0)(41.1.0)(42.0.0)(210 0.0 0.0 1.0))
其中,組碼10對應的數(shù)據(jù)項記錄了多段線的幾個結(jié)點(1,2,3,4,5)的點坐標,組碼42對應的數(shù)據(jù)項的值為弧段凸度(Bugle),其值為0時表示前后兩結(jié)點組成直線段(如1,2結(jié)點),其值大于0時表示前后兩結(jié)點組成前進方向右邊的(可以理解為順時針)弧段(如2,3結(jié)點),其值小于0時表示前后兩結(jié)點組成前進方向左邊的(可以理解為逆時針)弧段(如3,4結(jié)點)。
在獲取LWPOLYLINE結(jié)點坐標時,我們要根據(jù)多段線的存儲結(jié)構作相應的處理。
2.1折線LWPOLYLINE的點坐標提取
提取折線LWPOLYLINE中的點坐標方法很簡單,只需循環(huán)讀取多段線存儲列表中組碼為10對應的數(shù)據(jù)項即可。假設實體列表賦值為EN,則讀取結(jié)點坐標并賦值到PLIST結(jié)點列表的LISP程序代碼為:
(SETQ I 0 LEN(LENGTH EN))
(WHILE(
(SETQ VN(LIST(NTH I EN))P(CDR(ASSOC 10 VN)))
(IF P(SETQ PLIST(CONS P PLIST)))
(SETQ I(1+I))
);End of While
程序代碼段1折線LWPOLYLINE中的點坐標提取
2.2含弧段的LWPOLYLINE的點坐標提取
當骨架線中含有弧段時,我們需要在不失真的情況下按一定間隔提取弧段上的點坐標。由前面的數(shù)據(jù)分析,我們知道多段線的存儲列表中僅記錄連接弧線段的前后兩個的坐標和此弧段的凸度。因此,為了提取弧段上的點坐標,我們必須先了解AUTOCAD中關于凸度的定義。
凸度也稱弓弦比,其絕對值為弦高和弦長之比的兩倍,即2× H/D之值(如圖2),當凸度值為1.0或-1.0時,弧段為半圓。凸度值為0時表示前后兩結(jié)點組成直線段,值大于0時表示前后兩結(jié)點組成前進方向右邊的(可以理解為順時針)弧段,值小于0時表示前后兩結(jié)點組成前進方向左邊的(可以理解為逆時針)弧段。
如圖2,假設我們知道一多段線LWPOLYLINE線上的兩結(jié)點坐標分別為P1和P2,采集方向從P1點到P2點,P1和P2兩結(jié)點間的凸度值為Bulge,因為Bulge的絕對值等于2×H/D,則H/D= Bulge的絕對值/2.0,而弦長D為結(jié)點P1和P2的距離,可用函數(shù)(DISTANCE P1 P2)輕易求出,因此H的值也能求出。
下面我們根據(jù)H和D的值求圓心C0的坐標和弧段半徑r:
在三角形△P1C0P2中利用勾股定律,有r 2=(D/2)2+(r-H)2,求出r=(D/H/8.0+H/D/2.0)×D。
圓心C0的求取要根據(jù)弧段的方向(順時針或逆時針)來判斷,設弦P1P2的中點坐標為MidP,P1到P2的方位角為ANG,ang90為PI/2.0,ang_90為-PI/2.0,則逆時針弧段的圓心坐標C0可用函數(shù)(POLAR midp(+ang ang90)(-r h))求得,順時針弧段的圓心坐標C0可用函數(shù)(POLAR midp(+ang ang_90)(-r h))求得。
求得圓心C0和半徑r之后,弧段內(nèi)插點的坐標就容易求出來了。如圖2,設C0到P1的方位角為ang1,C0到P2的方位角為ang2,ang1到ang2的弧度增量為dispang,以ang=ang1為起始角度,按dispang弧度大小遞增,即ang=(+ang dispang),則結(jié)點P1與P2間的弧段內(nèi)插點坐標為P=(polar cent ang r),循環(huán)提取內(nèi)插點坐標直至ang>=ang2。
弧度增量dispang的絕對值大小與提取精度有關,值太小則點太密,導出的弧段點太密,值太大則導出的弧段嚴重失真?;《翁崛〉难h(huán)方式與弧段的方向(順時針還是逆時針)和方位角ang1與ang2之間的大小關系密切相關,我們將在下面內(nèi)容中分逆時針弧段和順時針弧段詳細討論。
由以上的分析,我們知道,多段線上的弧段信息對于我們提取結(jié)點坐標來說至關重要,因此,我們在獲取LWPOLYLINE中的結(jié)點坐標的同時,也要獲取與結(jié)點相關的弧段凸度Bulge的信息。在多段線LWPOLYLINE實體存儲列表中,組碼10對應的數(shù)據(jù)項記錄了多段線的幾個結(jié)點(1,2,3,4,5)的點坐標,組碼42對應的數(shù)據(jù)項的值為弧段凸度(Bugle)。將程序代碼段1修改如下(提取出來的結(jié)點列表賦值為PLIST,凸度列表賦值為BULGE_LIST):
(SETQ EN(ENTGET ENAME))
(SETQ I 0 LEN(LENGTH EN))
(WHILE(
(SETQ VN(LIST(NTH I EN)))
(SETQ BULGE(CDR(ASSOC 42 VN)))
(SETQ P(CDR(ASSOC 10 VN)))
(IF P(SETQ PLIST(APPEND PLIST(LIST P))))
(IF BULGE(SETQ BULGE_LIST(APPEND BULGE_LIST(LIST BULGE))))
(SETQ I(1+I))
);End of While
(IF(/=(LOGAND(CDR(ASSOC 70 VN))1)0);判斷多段線是否閉合
(SETQ PLIST(APPEND PLIST(LIST(NTH 0PLIST))) BULGE_LIST(APPEND BULGE_LIST(LIST 0)))
);閉合多段線添加第一個結(jié)點
程序代碼段2點列表和凸度列表的提取
2.2.1逆時針弧段的點提取
如圖3所示,假設我們知道一多段線LWPOLYLINE線上的兩結(jié)點(第i點和第i+1結(jié)點)坐標分別為P1和P2,采集方向從P1點到P2點,P1和P2兩結(jié)點間的凸度值為Bulge。設已求出半徑r和圓心C0,并設程序代碼段2提取出來的結(jié)點列表賦值為PLIST,凸度列表賦值為BULGE_LIST,則Bulge=(nth i Bulge_list),p1=(nth i plist),p2=(nth(1+i)plist)。
設ang1、ang2分別為圓心C0到結(jié)點P1、圓心C0到結(jié)點P2的方位角,當弧段提取間隔為0.5米的時候,相應的弧度增量大小絕對值為dispang=(/0.5 r)。
當ang1
(SETQ ANG ANG1)
(WHILE(<(+ANG DISPANG)ANG2)
(SETQ ANG(+ANG DISPANG))
(SETQ P(POLAR C0 ANG R))
(SETQ BULGE_PLIST(APPEND BULGE_PLIST(LIST P)))
);While end
程序代碼段3逆時針弧段點坐標提取
當ang1>ang2時,如圖4所示,將ang1改為(-ang1(*pi 2.0)),程序代碼段3不變。
2.2.2順時針弧段的點提取
當Bulge<0,ang1>ang2時(如圖5),以ang=ang2為起始角度,ang=(+ang dispang),則P1與P2間的間隔點為p=(polar cent ang r),循環(huán)直至ang>=ang1,然后將取得的弧段內(nèi)插點列表轉(zhuǎn)置。循環(huán)部分的程序代碼如下(設Bulge_Plist為存儲結(jié)點P1和結(jié)點P2間弧段內(nèi)插點的點列表):
(SETQ ANG ANG2)
(WHILE(<(+ANG DISPANG)ANG1)
(SETQ ANG(+ANG DISPANG)
(SETQ P(POLAR C0 ANG R))
(SETQ BULGE_PLIST(APPEND BULGE_PLIST(LIST P)))
);While end
(SETQ BULGE_PLIST(REVERSE BULGE_PLIST));/*轉(zhuǎn)置結(jié)點列表
程序代碼段4順時針弧段點坐標提取
當ang1 盡管LWPOLYLINE的存儲字節(jié)小,但某些情況下它不能滿足我們的成圖需要,當我們需要光滑曲線時,我們要將LWPOLYLINE按擬合或樣條擬合進行光滑處理,變成POLYLINE。 由前面的數(shù)據(jù)分析,我們了解POLYLINE為復雜實體:多段線為主實體,有相應的實體存儲列表,線上的每個結(jié)點為子實體,在圖形中各自有相應的實體存儲列表。每個結(jié)點允許有不同的高程值。在表現(xiàn)形式上,POLYLINE分為:折線POLYLINE——結(jié)點間以直線段相連,擬合POLYLINE——由擬合法生成的光滑曲線,樣條POLYLINE——樣條擬合法生成的光滑曲線。 POLYLINE主實體存儲列表中組碼70對應的數(shù)據(jù)項為特征值,由前所述,特征值二進制形式中的X1值為1時表示POLYLINE為擬合法生成的光滑曲線,X2值為1時POLYLINE為樣條擬合法生成的光滑曲線。我們可以通過對特征值的數(shù)值分析以區(qū)分POLYLINE的表現(xiàn)形式。 我們來看看擬合法生成的光滑曲線與樣條擬合法生成的光滑曲線的區(qū)別。如圖7,設折線3為一LWPOLYLINE,則曲線1為其經(jīng)擬合法后生成的光滑曲線,曲線2為其經(jīng)樣條擬合法后生成的光滑曲線。曲線1和曲線2兩者之間有本質(zhì)上的區(qū)別:擬合法生成的光滑曲線仍通過原折線采集點,但在原折線兩采集結(jié)點分別插入弧段;而樣條擬合法后生成的光滑曲線以原折線結(jié)點作控制點光滑內(nèi)插,偏離了原折線采集點。 我們在提取POLYLINE的結(jié)點坐標時,要根據(jù)其不同的表現(xiàn)形式,按不同的算法提取。 3.1折線POLYLINE的點坐標提取 我們知道POLYLINE為復雜實體,其每個結(jié)點在AUTOCAD中作為子實體,有相應的存儲列表對應。整根POLYLINE多段線的結(jié)點提取可以通過由主實體引導的每個結(jié)點存儲列表的組碼為10對應的數(shù)據(jù)項的循環(huán)搜索來完成。假如一POLYLINE實體名賦值為Ename,則它的第一個結(jié)點子實體Vname可通過 (entnext ename)獲取,下一個結(jié)點子實體則通過(entnext Vname)獲取,循環(huán)直到子實體類型為"SEQEND"時結(jié)束。 實體名為ename的POLYLINE的點坐標提取程序代碼為(點坐標提取列表賦值為Plist): (SETQ V(ENTNEXT ENAME)VN(ENTGET V))(WHILE(= (CDR(ASSOC 0 VN))"VERTEX") (SETQ PLIST(APPEND PLIST(LIST(CDR(ASSOC 10 VN))))) (SETQ V(ENTNEXT V)VN(ENTGET V)) );END WHILE 程序代碼段5折線POLYLINE的點坐標提取 3.2擬合POLYLINE的點坐標提取 如圖8所示,加粗線為LWPOLYLINE多段線,細實線為其經(jīng)擬合后生成的光滑曲線。擬合后生成的光滑曲線,其數(shù)據(jù)結(jié)構中,除記錄原折線上的結(jié)點1,2,3外,還新增了控制點C1,C2。擬合后的曲線以結(jié)點1,c1,2,c2,3為控制點分別在兩結(jié)點間內(nèi)插弧段,形成光滑曲線。 結(jié)點1,2,3為原結(jié)點,其結(jié)點實體列表(VN1)為: ((-1.<圖元名:400ab090>)(0."VERTEX")(330.<圖元名: 400ab080>)(5."292")(100."AcDbEntity")(67.0)(410."Model")(8. "JJ")(62.3)(100."AcDbVertex")(100."AcDb2dVertex")(10-146.87 491.48 0.0)(40.0.0)(41.0.0)(42.0.1182)(70.0)(50.0.0)) 結(jié)點C1,C2為曲線擬合后插入結(jié)點,其結(jié)點實體列表(VN2)為: ((-1.<圖元名:400ab0d0>)(0.“VERTEX”)(330.<圖元名: 400ab080>)(5.“29A”)(100.“AcDbEntity”)(67.0)(410.“Model”)(8.“JJ”)(62.3)(100.“AcDbVertex”)(100.“AcDb2dVertex”)(10 233.201 422.065 0.0)(40.0.0)(41.0.0)(42.0.313944)(70.1)(50. 0.0)) 對比以上兩個列表,組碼70對應的數(shù)據(jù)項的值分別為0和1,這是原結(jié)點與曲線擬合插入結(jié)點的根本區(qū)別。 如果僅提取原結(jié)點,那么在程序代碼段5中只需加上對70組碼對應的數(shù)據(jù)項的判斷,僅提取數(shù)據(jù)項值為0對應的結(jié)點坐標即可。修改后的程序代碼為: (SETQ V(ENTNEXT ENAME)VN(ENTGET V)) (WHILE(=(CDR(ASSOC 0 VN))"VERTEX")(IF(= (CDR(ASSOC 70 VN))0) (SETQ PLIST(APPEND PLIST(LIST(CDR(ASSOC 10 VN))))) );End of If (SETQ V(ENTNEXT V)VN(ENTGET V)) );END WHILE 程序代碼段6擬合曲線原折線點坐標提取 如果需要不失真地提取擬合曲線上的點坐標,則需要將曲線擬合后內(nèi)插的弧段按一定間隔提取坐標點。 這與含弧段的LWPolyLine的點提取算法大致相同,不同的是結(jié)點列表和凸度列表的提取方法不一樣,只需將2.2節(jié)中的程序代碼段2修改為(提取出來的結(jié)點列表賦值為PLIST,凸度列表賦值為BULGE_LIST): (SETQ V(ENTNEXT ENAME)VN(ENTGET V)) (WHILE(=(CDR(ASSOC 0 VN))"VERTEX") (SETQ BULGE(CDR(ASSOC 42 VN))) (SETQ P(CDR(ASSOC 10 VN))) (IF P(SETQ PLIST(APPEND PLIST(LIST P)))) (IF BULGE(SETQ BULGE_LIST(APPEND BULGE_LIST (LIST BULGE)))) (SETQ V(ENTNEXT V)VN(ENTGET V)) );End Of While (IF(/=(LOGAND(CDR(ASSOC 70 VN))1)0);判斷多段線是否閉合 (SETQ PLIST(APPENDPLIST(LIST(NTH 0PLIST))) BULGE_LIST(APPEND BULGE_LIST(LIST 0)));閉合多段線添加第一個結(jié)點 程序代碼段7擬合POLYLINE結(jié)點列表和凸度列表的提取 其余算法和程序代碼與2.2節(jié)中的一致。 3.3樣條POLYLINE的點坐標提取 如圖9所示,加粗線為原LWPOLYLINE線,細實線為其經(jīng)樣條曲線化后生成的POLYLINE。圓框點為原結(jié)點,也稱樣條曲線控制點,其結(jié)點實體列表為: ((-1.<圖元名:400a2740>)(0."VERTEX")(330.<圖元名: 400a2720>)(5."180")(100."AcDbEntity")(67.0)(410."Model")(8. "GCD")(62.3)(100."AcDbVertex")(100."AcDb2dVertex")(10 172.918 144.49 0.0)(40.0.0)(41.0.0)(42.0.0)(70.16)(50.0.0)) 方框點為樣條曲線擬合插入點,其結(jié)點實體列表為: ((-1.<圖元名:400a2780>)(0."VERTEX")(330.<圖元名: 400a2720>)(5."188")(100."AcDbEntity")(67.0)(410."Model")(8. "GCD")(62.3)(100."AcDbVertex")(100."AcDb2dVertex")(10 172.918 144.49 0.0)(40.0.0)(41.0.0)(42.0.0)(70.8)(50.0.0)) 對比兩個列表,70組碼的值分別為16和8,如果是三維POLYLINE樣條擬合后生成的POLYLINE,則70組碼的值分別為48和40,這是原結(jié)點與樣條曲線擬合插入點的根本區(qū)別。 分析70組碼對應的數(shù)據(jù)項,將其值按二進制形式表示為: 則X3值為1時,結(jié)點為原結(jié)點,X2值為1時結(jié)點為樣條曲線擬合插入點。 如果僅提取原結(jié)點,那么在程序代碼段7中只需加上對組碼70對應的數(shù)據(jù)項的值的判斷,僅提取數(shù)據(jù)項中X3值為1對應的結(jié)點坐標即可。修改后的程序代碼為: (SETQ V(ENTNEXT ENAME)VN(ENTGET V)) (WHILE(=(CDR(ASSOC 0 VN))"VERTEX") (IF(/=(LOGAND(CDR(ASSOC 70 VN))16)0) ((SETQ PLIST(APPEND PLIST(LIST(CDR(ASSOC 10 VN)))) ) );End of If (SETQ V(ENTNEXT V)VN(ENTGET V)) );END WHILE 程序代碼段8樣條曲線原折線點坐標提取 如果要不失真地提取樣條曲線點坐標,則提取數(shù)據(jù)項中X2值為1對應的結(jié)點坐標即可。程序代碼為: (SETQ V(ENTNEXT ENAME)VN(ENTGET V)) (WHILE(=(CDR(ASSOC 0 VN))"VERTEX") (IF(/=(LOGAND(CDR(ASSOC 70 VN))8)0) ((SETQ PLIST(APPEND PLIST(LIST(CDR(ASSOC 10 VN)))) ) );End of If (SETQ V(ENTNEXT V)VN(ENTGET V)) );END WHILE 程序代碼段9樣條曲線不失真點坐標提取 在國土系統(tǒng)的征地或規(guī)劃設計、土地整治等項目中經(jīng)常需要在AutoCAD中提取多段線的坐標信息,以上論文中所介紹的幾種不同類別的多段線點坐標信息提取,都可用于實際工作中,將文中程序代碼段中收集整理好的PLIST列表,輸出到文本文件中,便可得到想要的坐標文件。 [1]AutoCAD開發(fā)幫助.AutoDesk公司 [2]Visual LISP中文版開發(fā)人員手冊.AutoDesk公司 The algorithm of polyline coordinate extraction in AutoCAD Li Ling (Geographical conditions Monitoring Institute of Guangxi Zhuang People Autonomous Region,Guangxi,Jianzheng Road,Nanning 530023) To describes the different types of AutoCAD polyline data storage structure and the corresponding point coordinate extraction algorithm. Polylines Coordinate Crown Arc Clockwise Counterclockwise Spline fitting G633.55[文獻碼]B 1000-405X(2016)-3-312-1 李玲,女,碩士,高級工程師,研究方向為地理信息系統(tǒng)的開發(fā)與應用。3 POLYLINE的點坐標提取
4 結(jié)束語