基于ArcGIS10.0和Oracle10g的空间数据管理平台六(C#开发)-空间数据操作类

本系统的一个重点功能就是管理空间数据,所以很多空间数据的操作,而且这些操作可能随时都可能用到,所以单独封装为一个独立的空间数据操作类(地图操作类)。封装的函数都是一些最基本的操作功能,具体实现基于ArcGIS平台的空间数据管理还需要很多复杂的功能和逻辑,后面介绍空间数据管理和编辑的时候会详细介绍。

1.首先我们需要介绍的是连接空间数据库的代码函数,具体实现如下:

/// <summary> /// 连接空间数据库并得到一个SDE工作空间的实例 /// </summary> /// <returns></returns> public static IFeatureWorkspace GetFeatrueWorkspace() { //定义一个属性 IPropertySet pPS = new PropertySetClass(); //设置数据库服务器名,服务器所在的IP地址 pPS.SetProperty("SERVER", ConfigurationSettings.AppSettings["SERVER"]); //propset.SetProperty("SERVER", "10.51.6.233"); //设置SDE的端口,这是安装时指定的,默认安装时"port:5151" pPS.SetProperty("INSTANCE", ConfigurationSettings.AppSettings["INSTANCE"]); //SDE的用户名 pPS.SetProperty("USER", ConfigurationSettings.AppSettings["USER"]); //密码 pPS.SetProperty("PASSWORD", ConfigurationSettings.AppSettings["PASSWORD"]); //设置数据库的名字,只有SQL Server Informix 数据库才需要设置 pPS.SetProperty("DATABASE", ConfigurationSettings.AppSettings["DATABASE"]); //SDE的版本,在这为默认版本 pPS.SetProperty("VERSION", ConfigurationSettings.AppSettings["VERSION"]); //定义一个工作空间,并实例化为SDE的工作空间 IWorkspaceFactory pWF = new SdeWorkspaceFactoryClass(); //打开SDE工作空间,并转化为地物工作空间 IFeatureWorkspace pFW = (IFeatureWorkspace)pWF.Open(pPS, 0); return pFW; }

上面这个函数是采用SDE连接方式,也可以采用直接连接的方式,下面一个函数通过一个if分支语句来判断可以采用SDE也可以采用直接连接的方式实现,具体请看代码及详细的注释:

public static IWorkspace FindWsByDefault() { //定义一个属性 IPropertySet Propset = new PropertySetClass(); if (true) // 采用SDE连接 { //设置数据库服务器名,服务器所在的IP地址 Propset.SetProperty("SERVER", "192.168.1.111"); //设置SDE的端口,这是安装时指定的,默认安装时"port:5151" Propset.SetProperty("INSTANCE", "port:5151"); //SDE的用户名 Propset.SetProperty("USER", "sde"); //密码 Propset.SetProperty("PASSWORD", "sde"); //设置数据库的名字,只有SQL Server Informix 数据库才需要设置 //Propset.SetProperty("DATABASE", "sde"); //SDE的版本,在这为默认版本 Propset.SetProperty("VERSION", "SDE.DEFAULT"); } else // 直接连接 { //设置数据库服务器名,如果是本机可以用"sde:sqlserver:." Propset.SetProperty("INSTANCE", "sde:sqlserver:zhpzh"); //SDE的用户名 Propset.SetProperty("USER", "sa"); //密码 Propset.SetProperty("PASSWORD", "sa"); //设置数据库的名字,只有SQL Server Informix 数据库才需要设置 Propset.SetProperty("DATABASE", "sde"); //SDE的版本,在这为默认版本 Propset.SetProperty("VERSION", "SDE.DEFAULT"); } //定义一个工作空间,并实例化为SDE的工作空间 IWorkspaceFactory factory = new SdeWorkspaceFactoryClass(); //打开SDE工作空间,并转化为地物工作空间 IWorkspace workspace = factory.Open(Propset, 0); return workspace; }

代码注释里面提到的工作空间就相当于一个数据库,里面包含了各种可以操作的图层(相当于数据库中的表)。

2.在一个指定的工作空间中查询一个要素类

/// <summary> /// 查找指定要素 /// </summary> /// <param name="ws"></param> /// <param name="className"></param> /// <param name="dsName"></param> /// <returns></returns> public static IFeatureClass FindClassByName(IWorkspace ws, string className, string dsName) { IEnumDataset enumDs; if (dsName != "") { enumDs = ws.get_Datasets(esriDatasetType.esriDTFeatureDataset); IFeatureDataset featureDs = enumDs.Next() as IFeatureDataset; while (featureDs != null) { string strTemp = featureDs.Name.Substring(featureDs.Name.IndexOf('.') + 1); if (strTemp == dsName) { return GetFcFromDataset(featureDs, className); } featureDs = enumDs.Next() as IFeatureDataset; } } else { enumDs = ws.get_Datasets(esriDatasetType.esriDTFeatureClass); return GetFcFromEnumDataset(enumDs,className); } return null; }

然后利用这个函数实现了另外一个函数:通过要素类名和数据集名在指定的工作空间中寻找要素类

/// <summary> /// 通过要素类名和数据集名在指定的工作空间中寻找要素类 /// </summary> /// <param name="className"></param> /// <param name="datasetName"></param> /// <returns></returns> public static IFeatureClass FindClassByName(string className, string datasetName) { IWorkspace ws = FindWsByDefault(); IFeatureClass featClass = FindClassByName(ws, className, datasetName); return featClass; }

3.在数据集中查找要素类,一个数据集可能包含多个要素类,数据集就是把一些具有共同特征(共同的数据结构类型,空间参考相同等)的数据(要素类)划分成一个一个的集合。

/// <summary> /// 在数据集中查找要素类 /// </summary> /// <param name="pFD"></param> /// <param name="className"></param> /// <returns></returns> public static IFeatureClass GetFcFromDataset(IFeatureDataset pFD, string className) { IFeatureClass pFC; IFeatureClassContainer pFCC = pFD as IFeatureClassContainer; for (int i = 0; i < pFCC.ClassCount; i++) { pFC = pFCC.get_Class(i); string strTemp = pFC.AliasName.Substring(pFC.AliasName.IndexOf('.') + 1); if (strTemp == className) { return pFC; } } return null; }

4.将一个要素类从一个工作空间转移到另外一个工作空间:例如文件系统目录(Shape格式文件组成)、mdb或其他格式,文件系统目录下的所有Shape文件(一个等同于表结构的数据文件,内容等同于表里面的数据)构成一个工作空间。

/// <summary> /// 将一个要素类从一个工作空间转移到另外一个工作空间 /// 注意目标工作空间不能有改要素类,必须先清除 /// </summary> /// <param name="sourceWorkspace">源工作空间</param> /// <param name="targetWorkspace">目标工作空间</param> /// <param name="nameOfSourceFeatureClass">源要素类名</param> /// <param name="nameOfTargetFeatureClass">目标要素类名</param> public static void ConvertFeatureClass(IWorkspace sourceWorkspace, IWorkspace targetWorkspace, string nameOfSourceFeatureClass, string nameOfTargetFeatureClass, int sc_id) { //create source workspace name //创建源工作空间名称 IDataset sourceWorkspaceDataset = (IDataset)sourceWorkspace; IWorkspaceName sourceWorkspaceName = (IWorkspaceName)sourceWorkspaceDataset.FullName; //create source dataset name //创建源数据集名称 IFeatureClassName sourceFeatureClassName = new FeatureClassNameClass(); IDatasetName sourceDatasetName = (IDatasetName)sourceFeatureClassName; sourceDatasetName.WorkspaceName = sourceWorkspaceName; sourceDatasetName.Name = nameOfSourceFeatureClass; //create target workspace name //创建目标工作空间名称 IDataset targetWorkspaceDataset = (IDataset)targetWorkspace; IWorkspaceName targetWorkspaceName = (IWorkspaceName)targetWorkspaceDataset.FullName; //create target dataset name //创建目标数据集名称 IFeatureClassName targetFeatureClassName = new FeatureClassNameClass(); IDatasetName targetDatasetName = (IDatasetName)targetFeatureClassName; targetDatasetName.WorkspaceName = targetWorkspaceName; targetDatasetName.Name = nameOfTargetFeatureClass; //Open input Featureclass to get field definitions. //打开输入的要素类以得到字段定义 IName sourceName = (IName)sourceFeatureClassName; //打开源要素类 IFeatureClass sourceFeatureClass = (IFeatureClass)sourceName.Open(); //Validate the field names because you are converting between different workspace types. //验证字段名称,因为你正在不同类型的工作空间之间进行数据转换 IFieldChecker fieldChecker = new FieldCheckerClass(); IFields targetFeatureClassFields; IFields sourceFeatureClassFields = sourceFeatureClass.Fields; IEnumFieldError enumFieldError; // Most importantly set the input and validate workspaces! //最重要的设置输入和验证工作空间 fieldChecker.InputWorkspace = sourceWorkspace; fieldChecker.ValidateWorkspace = targetWorkspace; fieldChecker.Validate(sourceFeatureClassFields, out enumFieldError, out targetFeatureClassFields); // Loop through the output fields to find the geomerty field //遍历所有输出字段找到几何字段 IField geometryField; for (int i = 0; i < targetFeatureClassFields.FieldCount; i++) { if (targetFeatureClassFields.get_Field(i).Type == esriFieldType.esriFieldTypeGeometry) { geometryField = targetFeatureClassFields.get_Field(i); // Get the geometry field's geometry defenition //得到几何字段的几何定义 IGeometryDef geometryDef = geometryField.GeometryDef; //Give the geometry definition a spatial index grid count and grid size //赋予几何定义一个空间索引格网数目和格网大小值 IGeometryDefEdit targetFCGeoDefEdit = (IGeometryDefEdit)geometryDef; targetFCGeoDefEdit.GridCount_2 = 1; targetFCGeoDefEdit.set_GridSize(0, 0); //Allow ArcGIS to determine a valid grid size for the data loaded //允许ArcGIS为数据加载确定一个有效的格网大小 if (sc_id == 0) { targetFCGeoDefEdit.SpatialReference_2 = geometryField.GeometryDef.SpatialReference; } else { ISpatialReferenceFactory2 pSRF2 = new SpatialReferenceEnvironmentClass(); IGeographicCoordinateSystem pGCS = pSRF2.CreateGeographicCoordinateSystem(sc_id); ISpatialReference pSR = (ISpatialReference)pGCS; targetFCGeoDefEdit.SpatialReference_2 = pSR; } //geometryField.GeometryDef.SpatialReference; // we want to convert all of the features //转换要素类中所有的要素 IQueryFilter queryFilter = new QueryFilterClass(); queryFilter.WhereClause = ""; // Load the feature class //加载要素类 IFeatureDataConverter fctofc = new FeatureDataConverterClass(); IEnumInvalidObject enumErrors = fctofc.ConvertFeatureClass(sourceFeatureClassName, queryFilter, null, targetFeatureClassName, geometryDef, targetFeatureClassFields, "", 1000, 0); break; } } }

5.将mdb或Shape文件中要素类转换追加到sde数据库已有的要素类中,追加的mdb和Shape格式必须同SDE(空间数据库插件)数据库中表结构的数据格式相同

/// <summary> /// 将mdb或Shape文件中要素类转换追加到sde数据库已有的要素类中 /// </summary> /// <param name="sourceWorkspace"></param> /// <param name="targetWorkspace"></param> /// <param name="nameOfSourceFeatureClass"></param> /// <param name="nameOfTargetFeatureClass"></param> public static void AddFeatureClassToSDE(IWorkspace sourceWorkspace, IWorkspace targetWorkspace, string nameOfSourceFeatureClass, string nameOfTargetFeatureClass) { IFeatureWorkspace pSourceFW = sourceWorkspace as IFeatureWorkspace; IFeatureClass pSourceFc = pSourceFW.OpenFeatureClass(nameOfSourceFeatureClass); IFeatureWorkspace pTargetFW = targetWorkspace as IFeatureWorkspace; IFeatureClass pTargetFc = pTargetFW.OpenFeatureClass(nameOfTargetFeatureClass); mdb2fc(pSourceFc, pTargetFc); }

函数通过各自的工作空间和要素类名称等到具体需要转换的要素类(包括源要素类:mdb或shape格式中的表结构和目标要素类:SDE中的表结构),然后调用mdb2fc完成具体的转换工作,实现代码如下:

/// <summary> /// 追加要素到SDE的featureclass中 /// </summary> /// <param name="pSourceFc">源要素类</param> /// <param name="pTargetFc">目的要素类</param> private static void mdb2fc(IFeatureClass pSourceFc, IFeatureClass pTargetFc) { IFeatureCursor pFeaCursor = pSourceFc.Search(null, false); IFeature pFeature = pFeaCursor.NextFeature(); IField pField = new FieldClass(); int iIndex = 0; while (pFeature != null) { IFeature tempFeature = pTargetFc.CreateFeature(); tempFeature.Shape = pFeature.Shape; try { //添加字段值 for (int j = 0; j < pSourceFc.Fields.FieldCount; j++) { pField = pSourceFc.Fields.get_Field(j); iIndex = tempFeature.Fields.FindField(pField.Name); if (pField.Editable && iIndex != -1) { tempFeature.set_Value(iIndex, pFeature.get_Value(j)); } } tempFeature.Store(); } catch (System.Exception ex) { MessageBox.Show(ex.Message); return; } pFeature = pFeaCursor.NextFeature(); } }

上面根据源要素类的每一个字段的每一个值依次遍历并且插入SDE的目的要素类(表)中。

6.在图层中搜索要素

/// <summary> /// 在图层中搜索要素 /// </summary> /// <param name="pFeatLyr">需要搜索的图层</param> /// <param name="pGeo">搜索的集合条件</param> /// <returns>包含结果集的游标对象</returns> public static IFeatureCursor SearchFeatures(IFeatureLayer pFeatLyr, IGeometry pGeo) { try { ISpatialFilter spatialFilter = new SpatialFilterClass(); spatialFilter.Geometry = pGeo; spatialFilter.GeometryField = pFeatLyr.FeatureClass.ShapeFieldName; spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; IFeatureCursor featureCursor = pFeatLyr.FeatureClass.Search(spatialFilter, false); return pFeatLyr.FeatureClass.Search(spatialFilter, false); } catch (Exception ex) { MessageBox.Show(ex.Message); return null; } }

7.从选择集中创建要素集

/// <summary> /// 从选择集中创建要素集 /// </summary> /// <param name="pFeatureLayer">来源图层</param> /// <param name="pGeometry">选择范围</param> /// <returns>FeatureClass</returns> public static IFeatureClass CreateSelectionLayer(IFeatureLayer pFL, IGeometry pGeometry) { try { IFeatureLayerDefinition pFLD = pFL as IFeatureLayerDefinition; ISpatialFilter pSF = new SpatialFilterClass(); pSF.Geometry = pGeometry; pSF.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; IQueryFilter pQFilter = pSF; IFeatureSelection pFeatureSel = pFL as IFeatureSelection; pFeatureSel.SelectFeatures(pSF, esriSelectionResultEnum.esriSelectionResultNew, false); IFeatureLayer pSelFL = pFLD.CreateSelectionLayer("Selected Layer", true, null, null); return pSelFL.FeatureClass; } catch (Exception e) { throw (new Exception(e.Message)); } }

8.得到一个要素类和数据集的空间参考系

/// <summary> /// 得到一个要素类的空间参考系 /// </summary> /// <param name="pFeatureClass">要素类</param> /// <returns>空间参考系</returns> public static ISpatialReference getSpatialReference(IFeatureClass pFeatureClass) { IGeoDataset pGeoDataset = pFeatureClass as IGeoDataset; return pGeoDataset.SpatialReference; } /// <summary> /// 得到一个数据集的空间参考系 /// </summary> /// <param name="pFeatureDataset">数据集</param> /// <returns>空间参考系</returns> public static ISpatialReference getSpatialReference(IFeatureDataset pFeatureDataset) { IGeoDataset pGeoDataset = pFeatureDataset as IGeoDataset; return pGeoDataset.SpatialReference; }

9.改变要素类的空间参考

/// <summary> /// 改变要素类的空间参考 /// </summary> /// <param name="pFeatureClass">要素类</param> /// <param name="pGeoType">空间参考类型</param> public static void ChangeFeatureClassRef(IFeatureClass pFeatureClass, int gcsType) { IGeoDataset pGeoDataset = pFeatureClass as IGeoDataset; //QI 到IGeoDatasetSchemaEdit IGeoDatasetSchemaEdit pGeoDatasetSchemaEdit = pGeoDataset as IGeoDatasetSchemaEdit; if (pGeoDatasetSchemaEdit.CanAlterSpatialReference == true) { //创建SpatialReferenceEnvironmentClass对象 ISpatialReferenceFactory2 pSpaRefFactory = new SpatialReferenceEnvironmentClass(); //创建地理坐标系对象 IGeographicCoordinateSystem pNewGeoSys = pSpaRefFactory.CreateGeographicCoordinateSystem(gcsType); pGeoDatasetSchemaEdit.AlterSpatialReference(pNewGeoSys); } }

10.根据各种信息创建要素类

/// <summary> /// 创建一个要素类 /// </summary> /// <param name="workspace">创建要素类的工作空间</param> /// <param name="featureDataset">数据集</param> /// <param name="featureClassName">要素类名称</param> /// <param name="fields">字段集合</param> /// <param name="CLSID"></param> /// <param name="CLSEXT"></param> /// <param name="strConfigKeyword"></param> /// <returns></returns> public static IFeatureClass CreateFeatureClass(IWorkspace2 workspace, IFeatureDataset featureDataset, String featureClassName, IFields fields, UID CLSID, UID CLSEXT, String strConfigKeyword) { // name was not passed in if (featureClassName == "") { return null; } IFeatureClass featureClass; IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace; //feature class with that name already exists if (workspace.get_NameExists(esriDatasetType.esriDTFeatureClass, featureClassName)) { featureClass = featureWorkspace.OpenFeatureClass(featureClassName); return featureClass; } // assign the class id value if not assigned if (CLSID == null) { CLSID = new UIDClass(); CLSID.Value = "esriGeoDatabase.Feature"; } IObjectClassDescription objectClassDescription = new FeatureClassDescriptionClass(); // if a fields collection is not passed in then supply our own if (fields == null) { return null; } System.String strShapeField = ""; // locate the shape field for (int j = 0; j < fields.FieldCount; j++) { if (fields.get_Field(j).Type == esriFieldType.esriFieldTypeGeometry) { strShapeField = fields.get_Field(j).Name; break; } } // Use IFieldChecker to create a validated fields collection. IFieldChecker fieldChecker = new FieldCheckerClass(); IEnumFieldError enumFieldError = null; IFields validatedFields = null; fieldChecker.ValidateWorkspace = (IWorkspace)workspace; fieldChecker.Validate(fields, out enumFieldError, out validatedFields); // The enumFieldError enumerator can be inspected at this point to determine // which fields were modified during validation. // finally create and return the feature class if (featureDataset == null)// if no feature dataset passed in, create at the workspace level { featureClass = featureWorkspace.CreateFeatureClass(featureClassName, validatedFields, CLSID, CLSEXT, esriFeatureType.esriFTSimple, strShapeField, strConfigKeyword); } else { featureClass = featureDataset.CreateFeatureClass(featureClassName, validatedFields, CLSID, CLSEXT, esriFeatureType.esriFTSimple, strShapeField, strConfigKeyword); } return featureClass; }

11.导入一个要素类到目标工作空间中

/// <summary> /// 导入一个要素类到目标工作空间中 /// </summary> /// <param name="pFW">目标工作空间</param> /// <param name="pFD">目标工作空间中的数据集</param> /// <param name="strFCName">导入的目标工作空间的要素类名称</param> /// <param name="pFC">被导入的要素类</param> public static void ImportFeatureClassToSDE(IFeatureWorkspace pFW, IFeatureDataset pFD, string strFCName, IFeatureClass pSourceFC) { if (pSourceFC == null) { MessageBox.Show("被导入的要素类为空了!"); return; } IWorkspace2 pW2 = pFW as IWorkspace2; IFeatureClass pTargetFC = null; pTargetFC = CreateFeatureClass(pW2, pFD, strFCName, pSourceFC.Fields, null, null, ""); if (pTargetFC != null) { mdb2fc(pSourceFC, pTargetFC); } else { MessageBox.Show("打开或创建目标要素类失败!"); } }

12.编辑空间参照和设置IFeatureDataset空间参照

/// <summary> /// 编辑空间参照 /// </summary> /// <param name="inputSpr"></param> /// <returns></returns> public static ISpatialReference EditSpatialReferenceDlg(ISpatialReference inputSpr) { ESRI.ArcGIS.CatalogUI.ISpatialReferenceDialog2 spatialReferenceDialog2 = new ESRI.ArcGIS.CatalogUI.SpatialReferenceDialogClass(); ISpatialReference spf = spatialReferenceDialog2.DoModalEdit(inputSpr, false, false, false, false, false, false, false, 0); return spf; } /// <summary> /// 设置IFeatureDataset空间参照 /// </summary> /// <param name="ds"></param> /// <returns></returns> public static void SetFdsSpatialReference(IFeatureClass ds) { IGeoDataset gds = ds as IGeoDataset; // Cast the geodataset to the IGeoDatasetSchemaEdit interface and set the Spatial Reference. IGeoDatasetSchemaEdit geoDatasetSchemaEdit = (IGeoDatasetSchemaEdit)gds; if (geoDatasetSchemaEdit.CanAlterSpatialReference) { geoDatasetSchemaEdit.AlterSpatialReference(EditSpatialReferenceDlg(gds.SpatialReference)); } }

这里实现所有的函数都是在类MapOperation中,要看懂上面的所有代码必须要有一些ArcObejct编程的基础知识,当然还包括我前一篇博文介绍的有关于ArcGIS的相关知识,为了给大家提供一些ArcObject的编程知识,特别是用C#讲解的,我上传一本电子书,这本书我觉得很不错,讲到了很多关于ArcGIS二次开发的各个方面。电子书的下载地址:

http://download.csdn.net/detail/wanweiaiaqiang/3824454;或在下载页搜索:ArcGIS Engine+C#实例开发教程。

凌晨1:50,睡觉了。昨天晚上我们整个项目组在公司加班到晚上10点以后哦!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值