張國宏
(清遠市勘察測繪院,廣東 清遠511515)
CASS成圖系統是基于AutoCAD平臺二次開發出來的產品,因AutoCAD簡單易學,操作方便靈活,能以多種方式創建直線、圓、橢圓、多邊形、樣條曲線等基本圖形對象,因此CASS成圖系統在測量領域應用廣泛。隨著測量技術的不斷完善,GIS逐步運用到測量領域中,并逐漸成為主導,ArcGIS軟件平臺是當前主流的地理信息系統應用平臺之一。GIS操作的對象是空間數據和屬性數據,Esri公司的Geodatabase數據模型采用全關系數據庫管理空間數據,與各種商用關系數據庫兼容。Geodatabase提供了Personal Geodatabase可伸縮的空間數據存儲方案,適用于單機環境下的GIS應用,實際上就是一個Access數據庫,通過Microsoft Jet Engine將空間數據存放在Access數據庫中,將空間幾何信息、屬性信息,拓撲信息、三維信息及多媒體信息有機地結合在一起。本文擬使用C#.NET語言,來探討CASS數據轉化成ArcGIS軟件平臺支持的Access數據庫的方法。
ArcGIS 數據結構是空間數據和關系數據的結合,為了更好地展現所包含的信息,每個圖形都包含與之相對應的屬性,并根據要素屬性編碼顯示對應的符號。其數據分層嚴格按照幾何類型劃分,如點、線、面、文字等,同一圖層中只能含有一種幾何類型。因此,Access數據結構可以用代碼創建或在ArcCatalog下創建,數據結構的OBJECTID、SHAPE字段是創建結構時自動產生的,不可缺少。其中,OBJECTID字段用來存儲數據的自動編號;SHAPE字段的數據類型是OLE對象,用來存儲空間幾何坐標(X,Y,Z),該字段的值可以設置或讀取,是一個非常重要的字段;CASSCODE、FEATURENAME、ANGLE是擴展字段,可以使用Microsoft Office Access 2003軟件創建修改,用來存儲屬性數據(見表1)。

表1 Access數據結構
CASS圖形保存的數據為AutoCAD格式,圖形中的圖層、顏色、線型、線寬、填充、圖塊等基本信息都是利用AutoCAD的機制來存儲,數據圖層可以任意放置不同類型的對象,對象的基本屬性信息全部存儲在DXF群碼里,CASS編碼存儲在對象的XData擴展數據里,并用該編碼來顯示對應的符號。實例為:
((-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數據轉換到Access數據庫實質就是圖形的幾何要素重寫的過程,獲取對象的幾何坐標及相關的屬性信息、CASS編碼并按照一定數據格式重新組成一個新的數據文件。
CASS數據幾何類型分布在不同的圖層中,獲取幾何坐標時首先判斷對象的幾何類型,因為不同的幾何類型獲取坐標的方式不一樣。在對象的XData擴展數據獲取CASS編碼并關聯INDEX.INI文件調用實體名稱,把獲取到CASS編碼和實體名稱分別寫入CASSCODE和FEATURENAME字段里存儲。如圖1所示。

圖1 INDEX.INI
CASS數據點狀地物是以塊的方式來定義的(如稻田、菜地等),塊的插入點即為該點狀地物的幾何坐標。獲取點狀地物的幾何坐標時先要獲取該實體BlockReference對象的Position屬性值,該屬性值返回的是Point3d坐標。獲取點狀地物幾何坐標及屬性代碼段如下:
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);∥實體名稱
if(objType=="BlockReference"&layer=="DMTZ")
{
BlockReference block=entity as
BlockReference;
Point3d position=block.Position;
string angle=
zgh_MatchFormula.zgh_RadianConvertDegree(block.Rotation).
ToString();∥角度
∥對象類型*圖層*顏色*cass編碼*實體名稱*角度*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數據線狀地物分為多段線和二維多段線,它們的坐標獲取的方式不一樣,多段線的坐標直接用GetPoint3dAt方法獲取,返回的是Point3d類型的坐標。獲取二維多段線的坐標時先要把二維多段線Polyline2d轉換成Vertex2d對象類型,獲取該對象下的Position屬性值,其返回的是Point3d類型坐標。
(1)獲取多段線坐標代碼段
相關代碼如下:
for(int i=0;i<pline.NumberOfVertices;i++)
{
Point3d Point=pline.GetPoint3dAt(i);
}
(2)獲取二維多段線坐標代碼段
相關代碼如下:
foreach(ObjectId vid in pline2d)
{
Vertex2d v2d=trans.GetObject(vid,
OpenMode.ForWrite)as Vertex2d;
Point3d Point=v2d.Position;
}
(3)獲取線狀地物幾何坐標及屬性代碼段
相關代碼如下:
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);∥實體名稱
if(objType=="Polyline"&layer=="DMTZ")∥多段線
{
Autodesk.AutoCAD.DatabaseServices.Polyline pline=entity as
Autodesk.AutoCAD.DatabaseServices.Polyline;
string xyzString=
zgh_polyline.zgh_getPLineXYZCoord(pline);
∥對象類型*圖層*顏色*線型*cass編碼*實體名稱*坐標
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);∥將數據添加到坐標信息集
}
}
CASS數據面狀地物都是由多段線構成,如一般房屋等。面狀地物的對象Closed屬性值等于true,僅憑這一點很難準確地分析出面狀地物,因為有些線狀地物Closed屬性值也等于true,這時需要獲取對象的XData擴展數據CASS編碼關聯INDEX.INI文件來判斷。面狀地物幾何坐標的獲取與線狀地物幾何坐標的獲取方法一樣,唯一不同的是面狀地物頂點坐標首尾需閉合,否則在ArcMap中不能正常顯示。
CASS數據的文字信息獲取比較簡單,坐標存儲在對象的AlignmentPoint屬性里,返回的是Point3d坐標。文字內容在對象的TextString屬性里,返回的string。文字角度在Rotation屬性里,返回的是double。
獲取文字幾何坐標及屬性代碼段相關代碼如下:
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);∥實體名稱
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;
∥對象類型*圖層*顏色*文字內容*字高*角度*cass編碼*實體名稱*X*Y*Z
string coordString=objType+"*"+layer+"*"+colorIndex+"*"+textString+"*"+textHeight+"*"+textAngle+"*"+cassCode+"*"+cassName+"*"+position.X.ToString()+","+position.Y.ToString();
DMTZ_Text_List.Add(coordString);
}
}
在開始寫入數據前,需要先獲取圖層的要素類,該要素類的FeatureClass屬性提供了要素類的返回,將獲取的要素類轉為IDataset集合,該接口的Workspace屬性可以獲取到要素類的工作空間。編輯工作空間繼承自工作空間,提供了兩對方法:StartEding和StopEding、StartEditOperation和StopEditOperation。其中StartEditOperation和StopEditOperation必須在StartEding方法之后,在StopEding方法之前執行形成一個閉合的嵌套結構。通過CreateFeature方法創建一個新的要素對象,該對象的Shape屬性用于設置或獲取對象的幾何形狀,如點、線、面。set_Value方法用于設置字段的屬性值。Store方法用于存儲數據。向Access數據庫寫入空間數據及關系數據代碼如下:
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,"一般高程點");
qFeature.set_Value(4,0);
qFeature.Store();
qWorkspaceEdit.StopEditOperation();
qWorkspaceEdit.StopEditing(true);
根據轉換前、后的圖形比較檢查,發現其幾何要素、CASS屬性未發現遺漏,效果較為理想。
轉換前數據如圖2所示。

圖2 轉換前數據
轉換后數據如圖3所示。

圖3 轉換后數據
通過試驗分析,本文介紹的方法能夠方便地將CASS數據轉換到ArcGIS支持的Access數據庫,能夠實現數據分層和屬性構建,以及必要的屬性內容轉換,可以較直觀地實現基于ArcGIS的基礎地形圖庫動態更新。
[1] 邱洪鋼,張青蓮,熊友誼.ArcGIS Engine地理信息系統開發從入門到精通[M].北京:人民郵電出版社,2013:34-35,125.
[2] 蘭小機,劉德兒,魏瑞娟.基于ArcObjects與C#.NET的GIS應用開發[M].北京:冶金工業出版社,2013:215.
[3] 曾洪飛,盧擇臨,張帆.AutoCAD VBA&VB.NET開發基礎與實例教程(C#版)[M].北京:中國電力出版社,2013.