畢云華,馬 霖,羅 明
(1.黃山市國土資源信息中心, 安徽 黃山245000;2.安徽省基礎測繪信息中心,安徽 合肥 230031)
隨著“數(shù)字黃山”地理空間框架項目的建設實施,黃山市地理信息系統(tǒng)的應用范圍也越來越廣泛,已經(jīng)逐步在國土管理、公安警用、城市規(guī)劃、數(shù)字城管、旅游、交通等方面推廣應用。作為地理信息系統(tǒng)血液的地理空間數(shù)據(jù),是GIS應用的關鍵和核心[1]。本文在ArcMap中通過ID字段掛接清華山維MDB中的屬性表,將清華山維數(shù)據(jù)無損轉(zhuǎn)換至ArcGIS的Shape格式;通過編寫分層表,將轉(zhuǎn)換后的Shape格式數(shù)據(jù)進行分層,提取有用數(shù)據(jù),提高數(shù)據(jù)使用效率,集成不同平臺功能和數(shù)據(jù),為黃山市城鎮(zhèn)地籍數(shù)據(jù)庫和數(shù)字黃山地理空間框架等系統(tǒng)建設提供了方便。本文編譯的軟件也可為國內(nèi)現(xiàn)階段中小城市基礎測繪數(shù)據(jù)庫建設提供借鑒。
清華山維EPS平臺以關系型數(shù)據(jù)庫Access保存的MDB為基本存儲單位,每個MDB均由若干數(shù)量的二維表組成,表之間通過關鍵字段進行關聯(lián)。其數(shù)據(jù)類型可以分為空間數(shù)據(jù)和屬性數(shù)據(jù)??臻g數(shù)據(jù)有點類型、線類型、面類型和注記類型。屬性數(shù)據(jù)視具體的應用而定,不同的應用有不同的屬性表,但均通過關鍵字段ID和圖形進行掛接。清華山維和ArcGIS屬性數(shù)據(jù)的轉(zhuǎn)換可以在ArcMap中通過關鍵字段ID進行掛接,所以在此不分析具體的屬性數(shù)據(jù),只分析空間數(shù)據(jù)類型。4種類型的空間數(shù)據(jù)由相應的表構(gòu)成。
點類型的空間數(shù)據(jù)由GeoPointTB和CPointTB_p 2張表構(gòu)成。GeoPointTB表中的每條記錄對應于清華山維EPS軟件上的1個點。GeoPointTB表共有23個字段,其中字段ID為關鍵字段掛接CPointTB_p表及點類型屬性表,其余字段存儲該點的地物代碼、線型、顏色和所在圖層等信息。CPointTB_p表中的每條記錄保存每個點的X、Y坐標值。CPointTB_p表共有7個字段,其中ID為關鍵字段掛接GeoPointTB表,其余字段存儲每個點的X、Y坐標值及高程、點名、點類型等信息。
線類型的空間數(shù)據(jù)由GeoLineTB和CPointTB_l構(gòu)成。GeoLineTB表中的每條記錄對應于清華山維EPS軟件上的1條線。GeoLineTB表共有23個字段,其中字段ID為關鍵字段掛接CPointTB_l表及線類型的屬性表,其余字段存儲該線的地物代碼、線型、顏色和所在圖層等信息。CPointTB_l表共有7個字段,其中ID為關鍵字段掛接GeoLineTB表,其余字段存儲每條線的X、Y坐標值及構(gòu)成該線的點的高程、點名和點類型等信息。
面類型的空間數(shù)據(jù)由GeoAreaTB、CPointTB_a構(gòu)成。GeoAreaTB表中的每條記錄對應于清華山維EPS軟件上的1個面。GeoAreaTB表共有23個字段,其中字段ID為關鍵字段掛接CPointTB_a表及面類型的屬性表,其余字段存儲該面的地物代碼、顏色和所在圖層等信息。CPointTB_a表共有7個字段,其中ID為關鍵字段掛接GeoAreaTB表,其余字段存儲每個面的X、Y坐標值及構(gòu)成該面的點的高程、點名和點類型等信息。
注記類型的空間數(shù)據(jù)由MarkNoteTB、CPointTB_n構(gòu)成。MarkNoteTB表中的每條記錄對應于清華山維EPS軟件上的1個注記。GeoPointTB表共有34個字段,其中字段ID為關鍵字段掛接CPointTB_n表及注記類型的屬性表,其余字段存儲該注記的內(nèi)容、顏色等信息。CPointTB_n表中的每條記錄保存每個注記的X、Y坐標值。CPointTB_n表共有7個字段,其中ID為關鍵字段掛接MarkNoteTB表,其余字段存儲每個注記的X、Y坐標值、點名和點類型等信息。
ArcGIS的 數(shù) 據(jù) 格 式 主 要 有Shape、Coverage、Geodatabase和E00[2]。本文通過Shape文件格式進行數(shù)據(jù)轉(zhuǎn)換。一個ESRI的Shapefile數(shù)據(jù)包含一個主文件(.shp),一個索引文件(.shx)和一個dBASE(.dbf)表。主文件是直接訪問的變長記錄的文件,每一條記錄都描述一個形狀的一系列結(jié)點。在索引文件中,每一條記錄包含主文件相應記錄相對于主文件頭的偏移量。dBASE表中每條記錄表示一個要素的屬性。這種幾何結(jié)構(gòu)和屬性要素一對一的關系是通過記錄號來控制的,表中的屬性記錄的順序必須和主文件中的記錄順序相同。本文主要介紹主文件(.shp)。
表1 shp文件的頭文件結(jié)構(gòu)
主文件(.shp)包含一個定長的文件頭,之后就是變長的記錄。每一條變長的記錄都由一個定長的記錄頭和變長的記錄內(nèi)容組成。Shapefile的內(nèi)容分為2類:一是數(shù)據(jù)相關,包括主文件記錄內(nèi)容和主文件頭的數(shù)據(jù)描述范圍(形狀類型、最小矩形外框等);另一個是文件管理相關,包括文件和記錄的長度、記錄的偏移量等。主文件中用于記錄數(shù)據(jù)相關的Integer和DoubleInteger的字節(jié)序是 little endian(PC 或 Intel),而用于文件管理相關的字節(jié)序則是big endian(Sun or Motorola)[3]。主文件頭長度為100 byte。表1列出文件頭的字節(jié)位置、值、類型和字節(jié)序。
實現(xiàn)清華山維EPS到ArcGIS的轉(zhuǎn)換,幾何對象轉(zhuǎn)換是關鍵,因此在數(shù)據(jù)轉(zhuǎn)換之前首先考慮實體幾何類型的對照問題,然后根據(jù)該問題創(chuàng)建相應的Shape要素類。其幾何類型的對照關系如表2所示。
表2 數(shù)據(jù)對照表
通過ArcEngine的二次開發(fā),對清華山維EPS數(shù)據(jù)文件內(nèi)容全讀取,然后利用ArcEngine調(diào)用相應的接口實現(xiàn)數(shù)據(jù)向目標文件的寫入,并保存成Shape格式的數(shù)據(jù)(如圖1所示)。
圖1 EPS轉(zhuǎn)換Shape格式步驟
程序主要由3個部分組成:新建相應類型的Shape文件、讀入MDB文件、根據(jù)MDB文件相應的表寫入并保存到Shape文件。下面給出部分主要代碼。
1)新建Shape文件,并添加相應字段。具體代碼及注釋如下:
string tname = "EPS區(qū)"; //新建Shape的文件名
string strShapeFieldName = "Shape";
IFeatureWorkspace pFWS;
IWorkspaceFactory pWorkSpaceF= new Shapefi leWo rkspaceFactoryClass();
pFWS=pWorkSpaceF.OpenFromFile(strFolder,0) as IFeatureWorkspace;
IFields pFields= new FieldsClass();
IFieldsEdit pFieldsEdit;
pFields pFieldsEdit = pFields as IFieldsEdit;
IField pField= new FieldClass();
IFieldEdit pFieldEdit;
pFieldEdit = pField as IFieldEdit;
pFieldEdit.Name_2 = strShapeFieldName;
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
IGeometryDef pGeomDef;
IGeometryDefEdit pGeomDefEdit;
pGeomDef = new GeometryDefClass();
pGeomDefEdit = pGeomDef as IGeometryDefEdit;
pGeomDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPolygon;
//新建Shape文件的類型為esriGeometryType.esriGeometryPolygon是POLYGON類型的數(shù)據(jù)、
esriGeometryType.esriGeometryPoint為POINT類型的數(shù)據(jù)、esriGeometryType.esriGeometryPolyLine為POLYLINE類型的數(shù)據(jù)。
pFieldEdit.GeometryDef_2 = pGeomDef;
pFieldsEdit.AddField(pField);
//新建字段ID
pField = new FieldClass();
pFieldEdit = pField as IFieldEdit;
pFieldEdit.Name_2 = "ID";
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeInteger;
pFieldsEdit.AddField(pField);
pFeatureClass = pFWS.CreateFeatureClass(strName,pFields, null, null, esriFeatureType.esriFTSimple,strShapeFieldName, "");
2)讀取MDB數(shù)據(jù)。具體代碼及注釋如下:
讀取mdb數(shù)據(jù)
OleDbConnection objConnection = new OleDbConnection(strcon);
objConnection.Open();
String sqldd = "select id,layername from GeoAreaTB";
OleDbDataAdapter sda = new OleDbDataAdapter(sqldd,objConnection);
sda.Fill(ds, "屬性記錄");
3)根據(jù)mdb寫Shape文件[4]。
for (int i = 0; i < ds.Tables["屬性記錄"].Rows.Count; i++)
//循環(huán)GeoAreaTB區(qū)文件表中的所有區(qū)
{
DataSet ds1 = new DataSet("屬性記錄1") ;
String sqldd1 = "select x,y,id,seqid from CPointTB_a where id=" + ds.Tables["屬 性 記 錄"].Rows[i].ItemArray[0]+ " order by seqid"; //通過SQL語句從CPointTB_a表里查詢出與GeoAreaTB表中當前ID相同的X,Y坐標值,id和seqid值。
OleDbDataAdapter sda1 = new OleDbDataAdapter(sqldd1, objConnection);
sda1.Fill(ds1, "屬性記錄1");
if (ds1.Tables["屬性記錄1"].Rows.Count >= 3) //3個以上的結(jié)點才能構(gòu)成面
{
IPoint p1 = new PointClass(); //新建IPoint對象P1。
p1.PutCoords((double)ds1.Tables["屬性記錄1"].Rows[0].ItemArray[0], (double)ds1.Tables["屬性記錄1"].Rows[0].ItemArray[1]);//數(shù)據(jù)集的第1條記錄的X,Y坐標賦給p1點
INewPolygonFeedback m_PolyFeed = new NewPolygonFeedbackClass();//新建INewPolygonFeedback對象m_PolyFeed
m_PolyFeed.Start(p1) ;//將P1作為該多邊形的第1個結(jié)點
for (int j = 1; j < ds1.Tables["屬性記錄1"].Rows.Count; j++)
{
IPoint p2 = new PointClass();
p2.PutCoords((double)ds1.Tables["屬性記錄1"].Rows[j].ItemArray[0], (double)ds1.Tables["屬性記錄1"].Rows[j].ItemArray[1]);
m_PolyFeed.AddPoint(p2);
}//循環(huán)添加該多邊形的其他結(jié)點
IPolygon m_Polygon = m_PolyFeed.Stop();//生成多邊形
IPointCollection m_PointCollection =(IPointCollection)m_Polygon;
IGeometry m_Geometry = (IGeometry)m_PointCollection;
CreateFeature(m_Geometry, ds.Tables["屬性記錄"].Rows[i].ItemArray[0].ToString());
//調(diào)用CreateFeature函數(shù)將圖形信息保存至Shape文件的Shape字段,并將改多邊形的ID存入Shape文件的ID字段
cmap.Extent = cmap.FullExtent;//顯示所有轉(zhuǎn)換后的圖形
}
4)保存要素至Shape文件[5]。
private void CreateFeature(IGeometry m_Geometry,String t_id) //創(chuàng)建要素并保存
{
string tid = t_id;//接收變量
if (m_Geometry == null) return;
if (m_CurrentLayer == null) return;
IWorkspaceEdit m_WorkspaceEdit = GetWorkspaceEdit();
//新建 IWorkspaceEdit空間
IFeatureLayer m_FeatureLayer = (IFeatureLayer)m_CurrentLayer;
IFeatureClass m_FeatureClass = m_FeatureLayer.FeatureClass;
m_WorkspaceEdit.StartEditOperation();
//使用WorkspaceEdit接口新建要素
IFeature m_Feature = m_FeatureClass.
CreateFeature();
m_Feature.Shape = m_Geometry;
m_Feature.set_Value(2, tid.ToString());
m_Feature.Store();//保存要素
m_WorkspaceEdit.StopEditOperation();//保存Shape文件
}
通過ArcEngine進行二次開發(fā),將現(xiàn)有的清華山維EPS數(shù)據(jù)轉(zhuǎn)換為ArcGIS格式的數(shù)據(jù),并在ArcMap中通過ID字段掛接清華山維MDB中的屬性表,將清華山維的空間、屬性數(shù)據(jù)無損轉(zhuǎn)換為ArcGIS的Shape格式,通過編寫分層表,能方便地將轉(zhuǎn)換后Shape格式數(shù)據(jù)進行分層,提取有用數(shù)據(jù),提高數(shù)據(jù)使用效率,集成不同平臺功能和數(shù)據(jù),為各級部門使用GIS數(shù)據(jù)提供了方便[6]。本程序已經(jīng)過實際的驗證,并應用于黃山市城鎮(zhèn)地籍數(shù)據(jù)庫和數(shù)字黃山地理空間框架等系統(tǒng)建設中。它減少了數(shù)據(jù)轉(zhuǎn)換的工作量,拓展了地理信息數(shù)據(jù)的應用范圍,取得了良好的經(jīng)濟效益與社會效益[7]。
[1]黃杏元,馬勁松,湯勤.地理信息系統(tǒng)概論[M].北京:高等教育出版社,2001
[2]ESRI Press.ESRI ArcGIS Desktop Developer Guide[M].ESRI PR,2004
[3]蘭小機,劉德兒.ArcObjects GIS應用開發(fā)——基于C#.NET[M].江西:江西理工大學出版社,2006
[4]蔣波濤.ArcObjects 開發(fā)基礎與技巧——基于VisualBasic.Net[M].武漢:武漢大學出版社,2006
[5]張鵬.CAD與GIS集成技術(shù)在城市基礎測繪中的應用[J].地理空間信息,2010,8(5):22-24
[6]畢旭東.基于ArcGIS的地籍管理信息系統(tǒng)的設計與實現(xiàn)[D].成都:西南交通大學,2009
[7]CH/Z9001-2007.數(shù)字城市地理空間信息公共平臺技術(shù)規(guī)范[S]