本系统的一个重点功能就是管理空间数据,所以很多空间数据的操作,而且这些操作可能随时都可能用到,所以单独封装为一个独立的空间数据操作类(地图操作类)。封装的函数都是一些最基本的操作功能,具体实现基于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点以后哦!