張國(guó)宏
(清遠(yuǎn)市勘察測(cè)繪院,廣東 清遠(yuǎn)511515)
CASS成圖系統(tǒng)是基于AutoCAD平臺(tái)二次開發(fā)出來(lái)的產(chǎn)品,因AutoCAD簡(jiǎn)單易學(xué),操作方便靈活,能以多種方式創(chuàng)建直線、圓、橢圓、多邊形、樣條曲線等基本圖形對(duì)象,因此CASS成圖系統(tǒng)在測(cè)量領(lǐng)域應(yīng)用廣泛。隨著測(cè)量技術(shù)的不斷完善,GIS逐步運(yùn)用到測(cè)量領(lǐng)域中,并逐漸成為主導(dǎo),ArcGIS軟件平臺(tái)是當(dāng)前主流的地理信息系統(tǒng)應(yīng)用平臺(tái)之一。GIS操作的對(duì)象是空間數(shù)據(jù)和屬性數(shù)據(jù),Esri公司的Geodatabase數(shù)據(jù)模型采用全關(guān)系數(shù)據(jù)庫(kù)管理空間數(shù)據(jù),與各種商用關(guān)系數(shù)據(jù)庫(kù)兼容。Geodatabase提供了Personal Geodatabase可伸縮的空間數(shù)據(jù)存儲(chǔ)方案,適用于單機(jī)環(huán)境下的GIS應(yīng)用,實(shí)際上就是一個(gè)Access數(shù)據(jù)庫(kù),通過(guò)Microsoft Jet Engine將空間數(shù)據(jù)存放在Access數(shù)據(jù)庫(kù)中,將空間幾何信息、屬性信息,拓?fù)湫畔?、三維信息及多媒體信息有機(jī)地結(jié)合在一起。本文擬使用C#.NET語(yǔ)言,來(lái)探討CASS數(shù)據(jù)轉(zhuǎn)化成ArcGIS軟件平臺(tái)支持的Access數(shù)據(jù)庫(kù)的方法。
ArcGIS 數(shù)據(jù)結(jié)構(gòu)是空間數(shù)據(jù)和關(guān)系數(shù)據(jù)的結(jié)合,為了更好地展現(xiàn)所包含的信息,每個(gè)圖形都包含與之相對(duì)應(yīng)的屬性,并根據(jù)要素屬性編碼顯示對(duì)應(yīng)的符號(hào)。其數(shù)據(jù)分層嚴(yán)格按照幾何類型劃分,如點(diǎn)、線、面、文字等,同一圖層中只能含有一種幾何類型。因此,Access數(shù)據(jù)結(jié)構(gòu)可以用代碼創(chuàng)建或在ArcCatalog下創(chuàng)建,數(shù)據(jù)結(jié)構(gòu)的OBJECTID、SHAPE字段是創(chuàng)建結(jié)構(gòu)時(shí)自動(dòng)產(chǎn)生的,不可缺少。其中,OBJECTID字段用來(lái)存儲(chǔ)數(shù)據(jù)的自動(dòng)編號(hào);SHAPE字段的數(shù)據(jù)類型是OLE對(duì)象,用來(lái)存儲(chǔ)空間幾何坐標(biāo)(X,Y,Z),該字段的值可以設(shè)置或讀取,是一個(gè)非常重要的字段;CASSCODE、FEATURENAME、ANGLE是擴(kuò)展字段,可以使用Microsoft Office Access 2003軟件創(chuàng)建修改,用來(lái)存儲(chǔ)屬性數(shù)據(jù)(見表1)。
表1 Access數(shù)據(jù)結(jié)構(gòu)
CASS圖形保存的數(shù)據(jù)為AutoCAD格式,圖形中的圖層、顏色、線型、線寬、填充、圖塊等基本信息都是利用AutoCAD的機(jī)制來(lái)存儲(chǔ),數(shù)據(jù)圖層可以任意放置不同類型的對(duì)象,對(duì)象的基本屬性信息全部存儲(chǔ)在DXF群碼里,CASS編碼存儲(chǔ)在對(duì)象的XData擴(kuò)展數(shù)據(jù)里,并用該編碼來(lái)顯示對(duì)應(yīng)的符號(hào)。實(shí)例為:
((-1.<圖元名:7ef759a8>)(0."INSERT")(330.<圖元名:7ef73cc0>)(5."4A5")(100."AcDbEntity")(67.0)(410."Model")(8."GCD")(6."Continuous")(100."AcDbBlockReference")(66.1)(2."GC200")(10 244.31 70.4556 11.0)(41.0.5)(42.0.5)(43.0.5)(50.0.0)(70.0)(71.0)(44.0.0)(45.0.0)(210 0.0 0.0 1.0)(-3("SOUTH"(1000."202101"))))
CASS數(shù)據(jù)轉(zhuǎn)換到Access數(shù)據(jù)庫(kù)實(shí)質(zhì)就是圖形的幾何要素重寫的過(guò)程,獲取對(duì)象的幾何坐標(biāo)及相關(guān)的屬性信息、CASS編碼并按照一定數(shù)據(jù)格式重新組成一個(gè)新的數(shù)據(jù)文件。
CASS數(shù)據(jù)幾何類型分布在不同的圖層中,獲取幾何坐標(biāo)時(shí)首先判斷對(duì)象的幾何類型,因?yàn)椴煌膸缀晤愋瞳@取坐標(biāo)的方式不一樣。在對(duì)象的XData擴(kuò)展數(shù)據(jù)獲取CASS編碼并關(guān)聯(lián)INDEX.INI文件調(diào)用實(shí)體名稱,把獲取到CASS編碼和實(shí)體名稱分別寫入CASSCODE和FEATURENAME字段里存儲(chǔ)。如圖1所示。
圖1 INDEX.INI
CASS數(shù)據(jù)點(diǎn)狀地物是以塊的方式來(lái)定義的(如稻田、菜地等),塊的插入點(diǎn)即為該點(diǎn)狀地物的幾何坐標(biāo)。獲取點(diǎn)狀地物的幾何坐標(biāo)時(shí)先要獲取該實(shí)體BlockReference對(duì)象的Position屬性值,該屬性值返回的是Point3d坐標(biāo)。獲取點(diǎn)狀地物幾何坐標(biāo)及屬性代碼段如下:
foreach(ObjectId id in SSet.GetObjectIds())
{
Entity entity=id.GetObject(OpenMode.ForRead)as Entity;
string objType=entity.GetType().Name;
string cassAttrib=zgh_XData.zgh_getXData(db,id);
string[]cassAttArry;
string cassCode="";
if(cassAttrib!="")
{
cassAttArry=cassAttrib.Split(',');
cassCode=cassAttArry[1].ToString();∥CASS編碼
}
string layer=entity.Layer;∥圖層
int colorIndex=entity.ColorIndex;∥顏色
string cassName=
zgh_Access.zgh_getAccessTableFiledValue(odcConnection,
cassCode);∥實(shí)體名稱
if(objType=="BlockReference"&layer=="DMTZ")
{
BlockReference block=entity as
BlockReference;
Point3d position=block.Position;
string angle=
zgh_MatchFormula.zgh_RadianConvertDegree(block.Rotation).
ToString();∥角度
∥對(duì)象類型*圖層*顏色*cass編碼*實(shí)體名稱*角度*X*Y*Z
string coordString=objType+"*"+layer+"*"+colorIndex+"*"+cassCode+"*"+cassName+"*"+angle+"*"+position.X.ToString()+","+position.Y.ToString()+","+position.Z.ToString();
DMTZ_Point_List.Add(coordString);
}
}
CASS數(shù)據(jù)線狀地物分為多段線和二維多段線,它們的坐標(biāo)獲取的方式不一樣,多段線的坐標(biāo)直接用GetPoint3dAt方法獲取,返回的是Point3d類型的坐標(biāo)。獲取二維多段線的坐標(biāo)時(shí)先要把二維多段線Polyline2d轉(zhuǎn)換成Vertex2d對(duì)象類型,獲取該對(duì)象下的Position屬性值,其返回的是Point3d類型坐標(biāo)。
(1)獲取多段線坐標(biāo)代碼段
相關(guān)代碼如下:
for(int i=0;i<pline.NumberOfVertices;i++)
{
Point3d Point=pline.GetPoint3dAt(i);
}
(2)獲取二維多段線坐標(biāo)代碼段
相關(guān)代碼如下:
foreach(ObjectId vid in pline2d)
{
Vertex2d v2d=trans.GetObject(vid,
OpenMode.ForWrite)as Vertex2d;
Point3d Point=v2d.Position;
}
(3)獲取線狀地物幾何坐標(biāo)及屬性代碼段
相關(guān)代碼如下:
foreach(ObjectId id in SSet.GetObjectIds())
{
Entity entity=id.GetObject(OpenMode.ForRead)as Entity;
string objType=entity.GetType().Name;
string cassAttrib=zgh_XData.zgh_getXData(db,id);
string[]cassAttArry;
string cassCode="";
if(cassAttrib!="")
{
cassAttArry=cassAttrib.Split(',');
cassCode=cassAttArry[1].ToString();∥CASS編碼
}
string layer=entity.Layer;∥圖層
int colorIndex=entity.ColorIndex;∥顏色
string cassName=
zgh_Access.zgh_getAccessTableFiledValue(odcConnection,cassCode);∥實(shí)體名稱
if(objType=="Polyline"&layer=="DMTZ")∥多段線
{
Autodesk.AutoCAD.DatabaseServices.Polyline pline=entity as
Autodesk.AutoCAD.DatabaseServices.Polyline;
string xyzString=
zgh_polyline.zgh_getPLineXYZCoord(pline);
∥對(duì)象類型*圖層*顏色*線型*cass編碼*實(shí)體名稱*坐標(biāo)
string coordString=objType+"*"+layer+"*"+colorIndex+"*"+lineType+"*"+cassCode+"*"+cassName+"*"+xyzString;
DMTZ_Polyline_List.Add(coordString);
}
if(objType=="Polyline2d"&layer=="DMTZ")∥二維多段線
{
Polyline2d pline2d=entity as Polyline2d;
string xyzString=
zgh_polyline.zgh_get2PLineXYZCoord(trans,pline2d);
tryError=tryError+","+xyzString;
string coordString=objType+"*"+layer+"*"+colorIndex+"*"+lineType+"*"+cassCode+"*"+cassName+"*"+xyzString;
DMTZ_Polyline_List.Add(coordString);∥將數(shù)據(jù)添加到坐標(biāo)信息集
}
}
CASS數(shù)據(jù)面狀地物都是由多段線構(gòu)成,如一般房屋等。面狀地物的對(duì)象Closed屬性值等于true,僅憑這一點(diǎn)很難準(zhǔn)確地分析出面狀地物,因?yàn)橛行┚€狀地物Closed屬性值也等于true,這時(shí)需要獲取對(duì)象的XData擴(kuò)展數(shù)據(jù)CASS編碼關(guān)聯(lián)INDEX.INI文件來(lái)判斷。面狀地物幾何坐標(biāo)的獲取與線狀地物幾何坐標(biāo)的獲取方法一樣,唯一不同的是面狀地物頂點(diǎn)坐標(biāo)首尾需閉合,否則在ArcMap中不能正常顯示。
CASS數(shù)據(jù)的文字信息獲取比較簡(jiǎn)單,坐標(biāo)存儲(chǔ)在對(duì)象的AlignmentPoint屬性里,返回的是Point3d坐標(biāo)。文字內(nèi)容在對(duì)象的TextString屬性里,返回的string。文字角度在Rotation屬性里,返回的是double。
獲取文字幾何坐標(biāo)及屬性代碼段相關(guān)代碼如下:
foreach(ObjectId id in SSet.GetObjectIds())
{
Entity entity=id.GetObject(OpenMode.ForRead)as Entity;
string objType=entity.GetType().Name;
string cassAttrib=zgh_XData.zgh_getXData(db,id);
string[]cassAttArry;
string cassCode="";
if(cassAttrib!="")
{
cassAttArry=cassAttrib.Split(',');
cassCode=cassAttArry[1].ToString();∥CASS編碼
}
string layer=entity.Layer;∥圖層
int colorIndex=entity.ColorIndex;∥顏色
string cassName=
zgh_Access.zgh_getAccessTableFiledValue(odcConnection,cassCode);∥實(shí)體名稱
if(objType=="DBText"&layer=="DMTZ")
{
DBText textEntity=entity as DBText;
string textString=textEntity.TextString;
string textHeight=
textEntity.Height.ToString("0.00");
string textAngle=
zgh_MatchFormula.zgh_RadianConvertDegree(textEntity.Rotation).ToString("0.000000");
Point3d position=textEntity.AlignmentPoint;
∥對(duì)象類型*圖層*顏色*文字內(nèi)容*字高*角度*cass編碼*實(shí)體名稱*X*Y*Z
string coordString=objType+"*"+layer+"*"+colorIndex+"*"+textString+"*"+textHeight+"*"+textAngle+"*"+cassCode+"*"+cassName+"*"+position.X.ToString()+","+position.Y.ToString();
DMTZ_Text_List.Add(coordString);
}
}
在開始寫入數(shù)據(jù)前,需要先獲取圖層的要素類,該要素類的FeatureClass屬性提供了要素類的返回,將獲取的要素類轉(zhuǎn)為IDataset集合,該接口的Workspace屬性可以獲取到要素類的工作空間。編輯工作空間繼承自工作空間,提供了兩對(duì)方法:StartEding和StopEding、StartEditOperation和StopEditOperation。其中StartEditOperation和StopEditOperation必須在StartEding方法之后,在StopEding方法之前執(zhí)行形成一個(gè)閉合的嵌套結(jié)構(gòu)。通過(guò)CreateFeature方法創(chuàng)建一個(gè)新的要素對(duì)象,該對(duì)象的Shape屬性用于設(shè)置或獲取對(duì)象的幾何形狀,如點(diǎn)、線、面。set_Value方法用于設(shè)置字段的屬性值。Store方法用于存儲(chǔ)數(shù)據(jù)。向Access數(shù)據(jù)庫(kù)寫入空間數(shù)據(jù)及關(guān)系數(shù)據(jù)代碼如下:
IFeatureLayer qFeatureLayer=layer as
IFeatureLayer;
IFeatureClass qFeatureClass=
qFeatureLayer.FeatureClass;
IDataset dataset=qFeatureClass as IDataset;
IWorkspaceEdit qWorkspaceEdit=
dataset.Workspace as IWorkspaceEdit;
qWorkspaceEdit.StartEditing(true);
qWorkspaceEdit.StartEditOperation();
IFeature qFeature=
qFeatureClass.CreateFeature();
Point point=new Point();
double x=Convert.ToDouble(coordArry[0]);∥X
double y=Convert.ToDouble(coordArry[1]);∥Y
point.PutCoords(x,y);
qFeature.Shape=point as IGeometry;
qFeature.set_Value(2,"202101");
qFeature.set_Value(3,"一般高程點(diǎn)");
qFeature.set_Value(4,0);
qFeature.Store();
qWorkspaceEdit.StopEditOperation();
qWorkspaceEdit.StopEditing(true);
根據(jù)轉(zhuǎn)換前、后的圖形比較檢查,發(fā)現(xiàn)其幾何要素、CASS屬性未發(fā)現(xiàn)遺漏,效果較為理想。
轉(zhuǎn)換前數(shù)據(jù)如圖2所示。
圖2 轉(zhuǎn)換前數(shù)據(jù)
轉(zhuǎn)換后數(shù)據(jù)如圖3所示。
圖3 轉(zhuǎn)換后數(shù)據(jù)
通過(guò)試驗(yàn)分析,本文介紹的方法能夠方便地將CASS數(shù)據(jù)轉(zhuǎn)換到ArcGIS支持的Access數(shù)據(jù)庫(kù),能夠?qū)崿F(xiàn)數(shù)據(jù)分層和屬性構(gòu)建,以及必要的屬性內(nèi)容轉(zhuǎn)換,可以較直觀地實(shí)現(xiàn)基于ArcGIS的基礎(chǔ)地形圖庫(kù)動(dòng)態(tài)更新。
[1] 邱洪鋼,張青蓮,熊友誼.ArcGIS Engine地理信息系統(tǒng)開發(fā)從入門到精通[M].北京:人民郵電出版社,2013:34-35,125.
[2] 蘭小機(jī),劉德兒,魏瑞娟.基于ArcObjects與C#.NET的GIS應(yīng)用開發(fā)[M].北京:冶金工業(yè)出版社,2013:215.
[3] 曾洪飛,盧擇臨,張帆.AutoCAD VBA&VB.NET開發(fā)基礎(chǔ)與實(shí)例教程(C#版)[M].北京:中國(guó)電力出版社,2013.