ArcGIS Engine 地图操作基础——数据加载

数据加载是 ArcGIS Engine 中最基础的操作,AE 支持的数据广泛,包含矢量数据、栅格数据、CAD 数据、Excel数据等等,这些数据的加载有助于我们使用 AE 做进一步的数据处理与分析。

加载地图文档

地图文档可以是一个ArcMap文档(*.mxd)或者ArcMap模版(*.mxt)或ArcReader文件(*.pmf)。

加载地图文档的方式有三种:

    1. 使用 IMapControl 接口的 LoadMxFile 方法加载;
    1. 通过 IMapDocument 接口加载;
    1. 使用 ArcGIS Engine 中封装好的类库资源 ControlsOpenDocCommandClass 加载。

LoadMxFile 方法加载地图文档文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private void BtnLoadMxFile_Click(object sender, EventArgs e)
{
//加载数据前如果有数据则清空
try
{
OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.CheckFileExists = true;
pOpenFileDialog.Title = "打开地图文档";
pOpenFileDialog.Filter = "ArcMap文档(*.mxd)|*.mxd;|ArcMap模板(*.mxt)|*.mxt|发布地图文件(*.pmf)|*.pmf|所有地图格式(*.mxd;*.mxt;*.pmf)|*.mxd;*.mxt;*.pmf";
pOpenFileDialog.Multiselect = false; //不允许多个文件同时选择
pOpenFileDialog.RestoreDirectory = true; //存储打开的文件路径
if (pOpenFileDialog.ShowDialog() == DialogResult.OK)
{
string pFileName = pOpenFileDialog.FileName;
if (pFileName == "")
{
return;
}
if (mainMapControl.CheckMxFile(pFileName)) //检查地图文档有效性
{
ClearAllData();
mainMapControl.LoadMxFile(pFileName);
}
else
{
MessageBox.Show(pFileName + "是无效的地图文档!", "信息提示");
return;
}
}
}
catch (Exception ex)
{
MessageBox.Show("打开地图文档失败" + ex.Message);
}
}
  • 关于 ClearAllData 函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void ClearAllData()
{
if (mainMapControl.Map != null && mainMapControl.Map.LayerCount > 0)
{
//新建mainMapControl中Map
IMap dataMap = new MapClass();
dataMap.Name = "Map";
mainMapControl.DocumentFilename = string.Empty;
mainMapControl.Map = dataMap;

//新建EagleEyeMapControl中Map
IMap eagleEyeMap = new MapClass();
eagleEyeMap.Name = "eagleEyeMap";
EagleEyeMapControl.DocumentFilename = string.Empty;
EagleEyeMapControl.Map = eagleEyeMap;
}
}

IMapDocument 方法加载 Mxd 文档文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private void BtnIMapDocument_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.CheckFileExists = true;
pOpenFileDialog.Title = "打开地图文档";
pOpenFileDialog.Filter = "ArcMap文档(*.mxd)|*.mxd;|ArcMap模板(*.mxt)|*.mxt|发布地图文件(*.pmf)|*.pmf|所有地图格式(*.mxd;*.mxt;*.pmf)|*.mxd;*.mxt;*.pmf";
pOpenFileDialog.Multiselect = false;
pOpenFileDialog.RestoreDirectory = true;
if (pOpenFileDialog.ShowDialog() == DialogResult.OK)
{
string pFileName = pOpenFileDialog.FileName;
if (pFileName == "")
{
return;
}

if (mainMapControl.CheckMxFile(pFileName)) //检查地图文档有效性
{
//将数据载入pMapDocument并与Map控件关联
IMapDocument pMapDocument = new MapDocument();//using ESRI.ArcGIS.Carto;
pMapDocument.Open(pFileName, "");
//获取Map中激活的地图文档
mainMapControl.Map = pMapDocument.ActiveView.FocusMap;
mainMapControl.ActiveView.Refresh();
}
else
{
MessageBox.Show(pFileName + "是无效的地图文档!", "信息提示");
return;
}
}
}
catch (Exception ex)
{
MessageBox.Show("打开地图文档失败" + ex.Message);
}
}

ControlsOpenDocCommandClass 加载地图

1
2
3
4
5
6
private void BtncontrolsOpenDocCommandClass_Click(object sender, EventArgs e)
{
ICommand command = new ControlsOpenDocCommandClass();
command.OnCreate(mainMapControl.Object);
command.OnClick();
}

加载 Shapefile 数据

加载 Shapefile 数据的方式有两种:

    1. 通过工作空间加载;
    1. 通过 MapControl 空间的 AddShapefile 方法加载

通过工作空间加载

实例程序实现思路:

  • (1) 创建 ShapefileWorkspaceFactory 实例 pWorkspaceFactory ,使用 IWorkspaceFactory 接口的 OpenFromFile 方法打开 pFeatureWorkspace 中存储的基于 Shapefile 的工作区。
  • (2) 创建 FeatureLayer 的实例 pFeatureLayer ,并定义数据集。
  • (3) 使用 IMap 接口的 AddLayer 方法加载 pFeatureLayer 到当前地图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
private void AddShp_Click(object sender, EventArgs e)
{
//ClearAllData();
try
{
OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.CheckFileExists = true;
pOpenFileDialog.Title = "打开Shape文件";
pOpenFileDialog.Filter = "Shape文件(*.shp)|*.shp";
pOpenFileDialog.ShowDialog();

////获取文件路径,此即为第二种方法
//FileInfo pFileInfo = new FileInfo(pOpenFileDialog.FileName);
//string pPath = pOpenFileDialog.FileName.Substring(0, pOpenFileDialog.FileName.Length - pFileInfo.Name.Length);
//mainMapControl.AddShapeFile(pPath, pFileInfo.Name);

// 获取文件路径
IWorkspaceFactory pWorkspaceFactory;
IFeatureWorkspace pFeatureWorkspace;
IFeatureLayer pFeatureLayer;

string pFullPath = pOpenFileDialog.FileName;
if (pFullPath == "")
return;

int pIndex = pFullPath.LastIndexOf("\\");
//lastIndexOf是从字符串末尾开始检索,检索到子字符,则返回子字符在字符串中的位置,(位置从前向后数,最小位为0,也就是从第0位开始算起)未检测到则返回-1。
string pFilePath = pFullPath.Substring(0, pIndex); //文件路径
string pFileName = pFullPath.Substring(pIndex + 1); //文件名
/*substring(参数)是java中截取字符串的一个方法
有两种传参方式
一种是 public String substring(int beginIndex)
返回一个新的字符串,它是此字符串的一个子字符串。该子字符串从指定索引处的字符开始,直到此字符串末尾。
另一种是 public String substring(int beginIndex, int endIndex)
返回一个新字符串,它是此字符串的一个子字符串。该子字符串从指定的 beginIndex 处开始,直到索引 endIndex - 1 处的字符。因此,该子字符串的长度为 endIndex-beginIndex。 */

//实例化ShapefileWorkspaceFactory工作空间,打开Shape文件
pWorkspaceFactory = new ShapefileWorkspaceFactory();
pFeatureWorkspace = (IFeatureWorkspace)pWorkspaceFactory.OpenFromFile(pFilePath, 0);
//创建并实例化要素集
IFeatureClass pFeatureClass = pFeatureWorkspace.OpenFeatureClass(pFileName);
pFeatureLayer = new FeatureLayer();
pFeatureLayer.FeatureClass = pFeatureClass;
pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;//获取别名

ClearAllData(); //新增删除数据

mainMapControl.Map.AddLayer(pFeatureLayer);//加载图层
mainMapControl.ActiveView.Refresh();
//同步鹰眼.可有可无
SynchronizeEagleEye();
}
catch (Exception ex)
{
MessageBox.Show("图层加载失败!" + ex.Message);
}
}

通过 MapControl 空间的 AddShapefile 方法加载

调用该方法需要传入两个参数,分别是文件路径和不带扩展名的文件名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void AddShp2_Click(object sender, EventArgs e)
{
OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.CheckFileExists = true;
pOpenFileDialog.Title = "打开Shape文件";
pOpenFileDialog.Filter = "Shape文件(*.shp)|*.shp";
pOpenFileDialog.ShowDialog();

//获取文件路径
FileInfo pFileInfo = new FileInfo(pOpenFileDialog.FileName);//FileInfo需要using system.IO
string pPath = pOpenFileDialog.FileName.Substring(0, pOpenFileDialog.FileName.Length - pFileInfo.Name.Length);
mainMapControl.AddShapeFile(pPath, pFileInfo.Name);
// 调用该方法需要传入两个参数,分别是文件路径和不带扩展名的文件名。
}

加载栅格数据

实例程序实现思路:

在加载栅格文件时,需引用 ESRI.ArcGIS.DataSourcesRaster 命名空间。

  • (1) 用 IWorkspaceFactory 接口的 OpenFromFile 方法获得栅格文件的工作区;
  • (2) 用 IRasterWorkspace 接口的 OpenRasterDataset 方法获得栅格文件的数据集,实例化栅格文件对象,并对栅格数据集是否具有金字塔进行判断(这里栅格文件如果不具有金字塔则创建金字塔,可以提高大数据量图像的显示效率);
  • (3) 创建 RasterLayer 类的实例 pRasterLayer ,并定义其数据集;
  • (4) 使用 MapControl 控件的 AllLayer 方法将 pRasterLayer 添加至当前地图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private void AddRaster_Click(object sender, EventArgs e)
{
OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.CheckFileExists = true;
pOpenFileDialog.Title = "打开Raster文件";
pOpenFileDialog.Filter = "栅格文件 (*.*)|*.bmp;*.tif;*.jpg;*.img|(*.bmp)|*.bmp|(*.tif)|*.tif|(*.jpg)|*.jpg|(*.img)|*.img";
pOpenFileDialog.ShowDialog();

string pRasterFileName = pOpenFileDialog.FileName;
if (pRasterFileName == "")
{
return;
}

string pPath = System.IO.Path.GetDirectoryName(pRasterFileName);
string pFileName = System.IO.Path.GetFileName(pRasterFileName);

IWorkspaceFactory pWorkspaceFactory = new RasterWorkspaceFactory();
IWorkspace pWorkspace = pWorkspaceFactory.OpenFromFile(pPath, 0);
IRasterWorkspace pRasterWorkspace = pWorkspace as IRasterWorkspace;
IRasterDataset pRasterDataset = pRasterWorkspace.OpenRasterDataset(pFileName);
//影像金字塔判断与创建
IRasterPyramid3 pRasPyrmid;
pRasPyrmid = pRasterDataset as IRasterPyramid3;
if (pRasPyrmid != null)
{
if (!(pRasPyrmid.Present))
{
pRasPyrmid.Create(); //创建金字塔
}
}
IRaster pRaster;
pRaster = pRasterDataset.CreateDefaultRaster();
IRasterLayer pRasterLayer;
pRasterLayer = new RasterLayerClass();
pRasterLayer.CreateFromRaster(pRaster);
mainMapControl.Map.AddLayer(pLayer);//加载shp文件时是这样弄得,经过尝试这样也是可以的,具体有什么区别不可知
//mainMapControl.AddLayer(pLayer, 0);//这是书上的源代码
}

加载 CAD 数据

对于 ArcGIS Engine 来说,有两种不同的方式使用 CAD 数据:① 作为要素图层,以矢量数据来使用;② 作为地图背景,以栅格数据来使用。对于前者, ArcGIS Engine 使用与 FeatureLayer 一样的方法来管理,对于后者则采用 CadLayer 对象来管理。

CAD 文件作为矢量图层加载

分图层加载

实例程序实现思路:

  • (1) CAD 图可以分为点、线、面、标注,它们可以分别被加载到 MapControl 中。与加载其他数据一样,首先定义一个工作空间,用 CadWorkspaceFactoryClass 实例化工作空间,并打开相应的工作空间;
  • (2) 创建 FeatureLayer 的实例,定义数据集,使用 IMap 接口的 AddLayer 方法将要素图层添加至当前地图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
private void AddCADByLayer_Click(object sender, EventArgs e)
{
IWorkspaceFactory pWorkspaceFactory;
IFeatureWorkspace pFeatureWorkspace;
IFeatureLayer pFeatureLayer;
IFeatureClass pFeatureClass;

OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.Filter = "CAD(*.dwg)|*.dwg";
pOpenFileDialog.Title = "打开CAD数据文件";
pOpenFileDialog.ShowDialog();

string pFullPath = pOpenFileDialog.FileName;
if (pFullPath == "")
{
return;
}
//获取文件名和文件路径
int pIndex = pFullPath.LastIndexOf("\\");
string pFilePath = pFullPath.Substring(0, pIndex);
string pFileName = pFullPath.Substring(pIndex + 1);

pWorkspaceFactory = new CadWorkspaceFactory();
pFeatureWorkspace = (IFeatureWorkspace)pWorkspaceFactory.OpenFromFile(pFilePath, 0);
//加载CAD文件中的线文件
pFeatureClass = pFeatureWorkspace.OpenFeatureClass(pFileName + ":polyline");
//pFeatureClass = pFeatureWorkspace.OpenFeatureClass(pFileName + ":polygon");//打开多边形
//pFeatureClass = pFeatureWorkspace.OpenFeatureClass(pFileName + ":point");//打开点
//pFeatureClass = pFeatureWorkspace.OpenFeatureClass(pFileName + ":multipatch");//打开多面体
//pFeatureClass = pFeatureWorkspace.OpenFeatureClass(pFileName + ":annotation");//打开标注是这样吗?自己尝试失败,打开的是点,什么鬼?搞不懂。。。
pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.Name = pFileName;
pFeatureLayer.FeatureClass = pFeatureClass;

ClearAllData(); //新增删除数据

mainMapControl.Map.AddLayer(pFeatureLayer);
mainMapControl.ActiveView.Refresh();
//同步鹰眼,可有可无
SynchronizeEagleEye();
}

整幅图加载

实例程序实现思路:

  • 将 CAD 作为整幅图加载时,在得到相应的工作空间之后对 CAD 文件中的要素进行遍历,并判断是否为注记图层,如果是注记则需要使用 CadAnnotationLayer 对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
private void AddWholeCAD_Click(object sender, EventArgs e)
{
IWorkspaceFactory pWorkspaceFactory;
IFeatureWorkspace pFeatureWorkspace;
IFeatureLayer pFeatureLayer;
IFeatureDataset pFeatureDataset;

OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.Filter = "CAD(*.dwg)|*.dwg";
pOpenFileDialog.Title = "打开CAD数据文件";
pOpenFileDialog.ShowDialog();

string pFullPath = pOpenFileDialog.FileName;
if (pFullPath == "")
{
return;
}
//获取文件名和文件路径
int pIndex = pFullPath.LastIndexOf("\\");
string pFilePath = pFullPath.Substring(0, pIndex);
string pFileName = pFullPath.Substring(pIndex + 1);
//打开CAD数据集
pWorkspaceFactory = new CadWorkspaceFactoryClass(); //using ESRI.ArcGIS.DataSourcesFile;
pFeatureWorkspace = (IFeatureWorkspace)pWorkspaceFactory.OpenFromFile(pFilePath, 0);
//打开一个要素集
pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(pFileName);
//IFeatureClassContainer可以管理IFeatureDataset中的每个要素类
IFeatureClassContainer pFeatClassContainer = (IFeatureClassContainer)pFeatureDataset;

ClearAllData(); //新增删除数据

//对CAD文件中的要素进行遍历处理
for (int i = 0; i < pFeatClassContainer.ClassCount; i++)
{
IFeatureClass pFeatClass = pFeatClassContainer.get_Class(i);
//如果是注记,则添加注记层
if (pFeatClass.FeatureType == esriFeatureType.esriFTCoverageAnnotation)
{
pFeatureLayer = new CadAnnotationLayerClass();
pFeatureLayer.Name = pFeatClass.AliasName;
pFeatureLayer.FeatureClass = pFeatClass;
mainMapControl.Map.AddLayer(pFeatureLayer);
}
else //如果是点、线、面则添加要素层
{
pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.Name = pFeatClass.AliasName;
pFeatureLayer.FeatureClass = pFeatClass;
mainMapControl.Map.AddLayer(pFeatureLayer);
}
mainMapControl.ActiveView.Refresh();
}
//同步鹰眼,可有可无
SynchronizeEagleEye();
}

CAD 文件作为栅格图层加载

实例程序实现思路:

  • (1) 用 IWorkspaceFactory 接口的 OpenFromFile 方法获得 CAD 文件的工作区;
  • (2) 用 ICadDrawingWorkspace 接口的 OpenCadDrawingDataset 方法获得 CAD 文件的数据集,并将其赋值给 CadLayerClass 类的实例对象 pCadLayer 的 CadDrawingDataset 属性;
  • (3) 使用 IMap 接口的 AddLayer 方法将 pCadLayer 添加至当前地图。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private void AddRasterByCAD_Click(object sender, EventArgs e)
{
IWorkspaceFactory pCadWorkspaceFactory;
IWorkspace pWorkspace;
ICadDrawingWorkspace pCadDrawingWorkspace;
ICadDrawingDataset pCadDrawingDataset;
ICadLayer pCadLayer;

OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.Filter = "CAD(*.dwg)|*.dwg";
pOpenFileDialog.Title = "打开CAD数据文件";
pOpenFileDialog.ShowDialog();

string pFullPath = pOpenFileDialog.FileName;
if (pFullPath == "")
{
return;
}
//获取文件名和文件路径
int pIndex = pFullPath.LastIndexOf("\\");
string pFilePath = pFullPath.Substring(0, pIndex);
string pFileName = pFullPath.Substring(pIndex + 1);
pCadWorkspaceFactory = new CadWorkspaceFactoryClass();

pWorkspace = pCadWorkspaceFactory.OpenFromFile(pFilePath, 0);
pCadDrawingWorkspace = (ICadDrawingWorkspace)pWorkspace;
//获得CAD文件的数据集
pCadDrawingDataset = pCadDrawingWorkspace.OpenCadDrawingDataset(pFileName);
pCadLayer = new CadLayerClass();
pCadLayer.CadDrawingDataset = pCadDrawingDataset;
pCadLayer.Name = pFileName;//书中代码没有这一句,打开的结果是TOC面板里面没有文件的名字,故而自己添上了这一句

mainMapControl.Map.AddLayer(pCadLayer);
mainMapControl.ActiveView.Refresh();
}

加载个人地理数据库

个人地理数据库(Personal Geodatabase)使用 Micorosoft Access 文件(*.mdb)进行空间数据的存储与管理,它将不同的数据同一纳入 Access 文件中,便于数据的管理与迁移,容量限制为2GB。个人地理数据库支持单用户编辑,不支持版本管理。
实例程序实现思路:

  • (1) 创建 AccessWorkspaceFactory 类的实例;
  • (2) 用 IWorkspaceFactory 接口的 OpenFromFile 方法打开 *.mdb 数据集的工作空间,对工作空间里面的数据进行加载。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private void AddPersonGDB_Click(object sender, EventArgs e)
{
IWorkspaceFactory pAccessWorkspaceFactory;

OpenFileDialog pOpenFileDialog = new OpenFileDialog();
pOpenFileDialog.Filter = "Personal Geodatabase(*.mdb)|*.mdb";
pOpenFileDialog.Title = "打开PersonGeodatabase文件";
pOpenFileDialog.ShowDialog();

string pFullPath = pOpenFileDialog.FileName;
if (pFullPath == "")
{
return;
}
pAccessWorkspaceFactory = new AccessWorkspaceFactory(); //using ESRI.ArcGIS.DataSourcesGDB;
//获取工作空间
IWorkspace pWorkspace = pAccessWorkspaceFactory.OpenFromFile(pFullPath, 0);

ClearAllData(); //新增删除数据

//加载工作空间里的数据
AddAllDataset(pWorkspace, mainMapControl);
}
  • 这里对加载工作空间中数据的方法进行了封装,自定义了 AddAllDataset 函数,以便对其他空间数据库(文件地理数据库、ArcSDE 空间数据库)加载时可直接调用。
  • 以上代码主要介绍矢量和栅格数据的加载(其实不止这两种数据格式,加载其他类型的数据也是采用相同的方法,只是采用不同的工作空间而已)。
  • 自定义函数 AddAllDataset 核心代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
/// <summary>
/// 加载工作空间里面的要素和栅格数据
/// </summary>
/// <param name="pWorkspace"></param>
private void AddAllDataset(IWorkspace pWorkspace, AxMapControl mapControl)
{
IEnumDataset pEnumDataset = pWorkspace.get_Datasets(ESRI.ArcGIS.Geodatabase.esriDatasetType.esriDTAny);
pEnumDataset.Reset();
//将Enum数据集中的数据一个个读到DataSet中
IDataset pDataset = pEnumDataset.Next();
//判断数据集是否有数据
while (pDataset != null)
{
if (pDataset is IFeatureDataset) //要素数据集
{
IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pWorkspace;
IFeatureDataset pFeatureDataset = pFeatureWorkspace.OpenFeatureDataset(pDataset.Name);
IEnumDataset pEnumDataset1 = pFeatureDataset.Subsets;
pEnumDataset1.Reset();
IGroupLayer pGroupLayer = new GroupLayerClass();
pGroupLayer.Name = pFeatureDataset.Name;
IDataset pDataset1 = pEnumDataset1.Next();
while (pDataset1 != null)
{
if (pDataset1 is IFeatureClass) //要素类
{
IFeatureLayer pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.FeatureClass = pFeatureWorkspace.OpenFeatureClass(pDataset1.Name);
if (pFeatureLayer.FeatureClass != null)
{
pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;
pGroupLayer.Add(pFeatureLayer);
mapControl.Map.AddLayer(pFeatureLayer);
}
}
pDataset1 = pEnumDataset1.Next();
}
}
else if (pDataset is IFeatureClass) //要素类
{
IFeatureWorkspace pFeatureWorkspace = (IFeatureWorkspace)pWorkspace;
IFeatureLayer pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.FeatureClass = pFeatureWorkspace.OpenFeatureClass(pDataset.Name);

pFeatureLayer.Name = pFeatureLayer.FeatureClass.AliasName;
mapControl.Map.AddLayer(pFeatureLayer);
}
else if (pDataset is IRasterDataset) //栅格数据集
{
IRasterWorkspaceEx pRasterWorkspace = (IRasterWorkspaceEx)pWorkspace;
IRasterDataset pRasterDataset = pRasterWorkspace.OpenRasterDataset(pDataset.Name);
//影像金字塔判断与创建
IRasterPyramid3 pRasPyrmid;
pRasPyrmid = pRasterDataset as IRasterPyramid3;
if (pRasPyrmid != null)
{
if (!(pRasPyrmid.Present))
{
pRasPyrmid.Create(); //创建金字塔
}
}
IRasterLayer pRasterLayer = new RasterLayerClass();
pRasterLayer.CreateFromDataset(pRasterDataset);
ILayer pLayer = pRasterLayer as ILayer;
mapControl.AddLayer(pLayer, 0);
}
pDataset = pEnumDataset.Next();
}

mapControl.ActiveView.Refresh();
//同步鹰眼
SynchronizeEagleEye();
}

加载文件地理数据库数据

文件地理数据库(File Geodatabase)是以文件夹形式存储各种类型的 GIS 数据集,可以存储、查询和管理空间数据和非空间数据,支持的地理数据库的大小最大为 1 TB。文件地理数据库支持单用户编辑,不支持版本管理。
实例程序实现思路:

  • (1) 由于文件地理数据库是以文件夹的形式存在的,因此可以使用 FolderBrowserDialog 选择文件夹进行加载。首先创建 FileGDBWorkspaceFactoryClass 类的实例;
  • (2) 用 IWorkspaceFactory 接口的 OpenFromFile 方法打开文件地理数据库的工作空间,对工作空间里面的数据进行加载。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#region 加载文件地理数据库数据
private void AddFileDatabase_Click(object sender, EventArgs e)
{
IWorkspaceFactory pFileGDBWorkspaceFactory;

FolderBrowserDialog dlg = new FolderBrowserDialog();
if (dlg.ShowDialog() != DialogResult.OK) return;
string pFullPath = dlg.SelectedPath;

if (pFullPath == "")
{
return;
}
pFileGDBWorkspaceFactory = new FileGDBWorkspaceFactoryClass(); //using ESRI.ArcGIS.DataSourcesGDB;

ClearAllData(); //新增删除数据

//获取工作空间
IWorkspace pWorkspace = pFileGDBWorkspaceFactory.OpenFromFile(pFullPath, 0);
AddAllDataset(pWorkspace, mainMapControl);
}
#endregion

加载 ArcSDE 空间数据库数据

ArcSDE(Spatial Database Engine,空间搜索引擎)是在现有的关系型数据库上进行的空间扩展,它使空间数据能保存在关系数据库中(如 Oracle、SQLServer等)。ArcSDE 空间数据库的一个重要特点是支持多用户并发操作,并且可以通过版本来表现空间数据编辑的状态。

ArcSDE 的组成:

  1. ArcSDE 服务器管理进程负责维护 ArcSDE 和监听来自客户端的连接请求。ArcSDE 启动就是启动 ArcSDE 服务器管理进程,利用管理员账户管理 ArcSDE 与 RDBMS 的连接,处理客户端的连接请求。
  2. 专用服务器进程由 ArcSDE 服务器管理进程穿件,用于每一个特定的客户端应用程序与数据库的连接。
  3. ArcSDE 客户端通过 ArcSDE 服务器管理进程和专用服务器进程建立和 RDBMS 的连接,实现对数据库的操作。

ArcSDE 提供了应用服务器连接和直接连接两种连接方式。当服务器性能较好时可采用应用服务器连接,否则采用直接连接。为了减轻服务器的压力,建议采用直接连接的方式进行连接。

两种连接方式的异同:直接连接就是通过 ArcSDE 访问数据表,并在本地完成对数据的各种操作(如空间分析、编辑等);而应用服务器连接就是通过 ArcSDE 访问数据表后,在服务器端完成对数据的各种操作,再把操作结果返回客户端。

实例程序实现思路:

  • (1) 创建 SDEWorksapceFactoryClass 类的实例;
  • (2) 通过 SDE 连接的连接属性打开 SDE 数据库的工作空间,对工作空间里面的数据进行加载。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# 这里以基于 Oracle 11g 的 ArcSDE 10.0 连接为例对两种连接方式进行说明。
#region 加载 ArcSDE 数据库
/// <summary>
/// 服务器连接
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddSDEByService_Click(object sender, EventArgs e)
{
IWorkspace pWorkspace;
pWorkspace = arcSDEWorkspaceOpen("192.168.70.110", "esri_sde", "sde", "sde", "", "SDE.DEFAULT");

//如果工作空间不为空则进行加载
if (pWorkspace != null)
{
AddAllDataset(pWorkspace, mainMapControl);
}
}

/// <summary>
/// 直连
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void AddSDEByDirect_Click(object sender, EventArgs e)
{
IWorkspace pWorkspace;

//如果工作空间不为空则进行加载
if (pWorkspace != null)
{
AddAllDataset(pWorkspace, mainMapControl);
}
}

/// <summary>
/// 通过SDE连接打开SDE数据库
/// </summary>
/// <param name="server">服务器IP</param>
/// <param name="instance">数据库实例,应用服务器连接为:5151或esri_sde,直连为sde:oracle11g:orcl(orcl为服务名)</param>
/// <param name="user">SDE用户名</param>
/// <param name="password">用户密码</param>
/// <param name="database">数据库</param>
/// <param name="version">SDE版本,缺省为"SDE.DEFAULT"</param>
/// <returns></returns>
private IWorkspace arcSDEWorkspaceOpen(string server, string instance, string user, string password, string database, string version)
{
IWorkspace pWorkSpace = null;
//创建和实例化数据集
IPropertySet pPropertySet = new PropertySetClass();
pPropertySet.SetProperty("SERVER", server);
pPropertySet.SetProperty("INSTANCE", instance);
pPropertySet.SetProperty("USER", user);
pPropertySet.SetProperty("PASSWORD", password);
pPropertySet.SetProperty("DATABASE", database);
pPropertySet.SetProperty("VERSION", version);
IWorkspaceFactory2 pWorkspaceFactory = new SdeWorkspaceFactoryClass();

try
{
pWorkSpace = pWorkspaceFactory.Open(pPropertySet, 0);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return pWorkSpace;
}
#endregion

加载文本文件数据

野外测量的数据通常为含有 X、Y 坐标的 Excel 文件或者文本文件。
实例程序实现思路:

  • (1) 根据 Excel 或者 *.txt 文件等获取点的坐标信息;
  • (2) 根据点的坐标创建 Shapefile 图层;
  • (3) 加载该 Shapefile 图层。

坐标信息的提取

  • (1) 创建一个点结构,进行点信息的存储。
1
2
3
4
5
6
struct CPoint
{
public string Name;
public double X;
public double Y;
}
  • (2) 创建并实例化一个 CPoint 类型的数组,将所有的点信息进行存储。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
List<string> pColumns = new List<string>();
private List<CPoint> GetPoints(string surveyDataFullName)
{
try
{
List<CPoint> pList = new List<CPoint>();
char[] charArray = new char[] { ',', ' ', '\t' }; //常用的分隔符为逗号、空格、制表符
//文本信息读取
FileStream fs = new FileStream(surveyDataFullName, FileMode.Open);
StreamReader sr = new StreamReader(fs, Encoding.Default);
string strLine = sr.ReadLine();
if (strLine != null)
{
string[] strArray = strLine.Split(charArray);
if (strArray.Length > 0)
{
for (int i = 0; i < strArray.Length; i++)
{
pColumns.Add(strArray[i]);
}
}

while ((strLine= sr.ReadLine())!=null)
{
//点信息的读取
strArray = strLine.Split(charArray);
CPoint pCPoint = new CPoint();
pCPoint.Name = strArray[0].Trim();
pCPoint.X = Convert.ToDouble(strArray[1]);
pCPoint.Y = Convert.ToDouble(strArray[2]);

pList.Add(pCPoint);
}
}
else
{
return null;
}
sr.Close();
return pList;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return null;
}
}

根据点坐标创建 Shapefile 图层

  • (1) 创建表的工作空间,通过 IFields、IFieldsEdit、IField 等接口创建属性字段,添加到要素集中。
  • (2) 根据获得的点坐标信息为属性字段赋值,进而得到图层的要素集。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
private IFeatureLayer CreateShpFromPoints(List<CPoint> cPointList, string filePath)
{
int index = filePath.LastIndexOf('\\');
string folder = filePath.Substring(0, index);//路径切分得到文件夹名
string shapeName = filePath.Substring(index + 1); //路径切分得到文件名
IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass();
IFeatureWorkspace pFWS = (IFeatureWorkspace)pWSF.OpenFromFile(folder, 0);

IFields pFields = new FieldsClass();
IFieldsEdit pFieldsEdit;
pFieldsEdit = (IFieldsEdit)pFields;

IField pField = new FieldClass();
IFieldEdit pFieldEdit = (IFieldEdit)pField;
pFieldEdit.Name_2 = "Shape";
pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
IGeometryDef pGeometryDef = new GeometryDefClass();
IGeometryDefEdit pGDefEdit = (IGeometryDefEdit)pGeometryDef;
pGDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;
//定义坐标系
ISpatialReferenceFactory pSRF = new SpatialReferenceEnvironmentClass();
ISpatialReference pSpatialReference = pSRF.CreateGeographicCoordinateSystem((int)esriSRGeoCSType.esriSRGeoCS_Beijing1954);
pGDefEdit.SpatialReference_2 = pSpatialReference;

pFieldEdit.GeometryDef_2 = pGeometryDef;
pFieldsEdit.AddField(pField);

IFeatureClass pFeatureClass;
pFeatureClass = pFWS.CreateFeatureClass(shapeName, pFields, null, null, esriFeatureType.esriFTSimple, "Shape", "");

IPoint pPoint = new PointClass();
for (int j = 0; j < cPointList.Count; j++)
{
pPoint.X = cPointList[j].X;
pPoint.Y = cPointList[j].Y;

IFeature pFeature = pFeatureClass.CreateFeature();
pFeature.Shape = pPoint;
pFeature.Store();
}

IFeatureLayer pFeatureLayer = new FeatureLayerClass();
pFeatureLayer.Name = shapeName;
pFeatureLayer.FeatureClass = pFeatureClass;
return pFeatureLayer;
}

Shapefile 图层的加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void btnCreate_Click(object sender, EventArgs e)
{
if (ValidateTxtbox())
{
List<CPoint> pCPointList = GetPoints(txtSource.Text);
if (pCPointList == null)
{
MessageBox.Show("所选文件为空,请重新选择!");
}
else
{
IFeatureLayer pFeatureLayer = CreateShpFromPoints(pCPointList, txtSave.Text);
buddyMap.Map.AddLayer(pFeatureLayer);
this.Close();
}
}
}

总结

根据上述 ArcGIS Engine 加载几种常用的数据源的方法,可以看出 ArcGIS Engine 加载空间数据一般具有以下五个步骤:

  1. 创建数据对应的工作空间工厂(WorkspaceFactory);
  2. 使用 WorkspaceFactory 创建要加载数据的工作空间(Workspace);
  3. 使用 Workspace 打开并得到图层的数据集 DataSet ;
  4. 将 DataSet 赋值给新建图层的数据源;
  5. 添加图层到 MapControl。