• ArcObject 实现FeatureClass 投影转换


    1 使用 Project 与 ProjectEx 实现要素投影转换

    使用 IGeometry5.Project 与 ProjectEx 方法 对要素进行投影转换

    /// <summary>
    /// 要素类从现有投影转换为新的投影
    /// </summary>
    /// <param name="featureClass">要素类</param>
    /// <param name="newSpatialReference">新的坐标参考系</param>
    /// <param name="out_path">输出路径</param>
    /// <param name="out_name">输出要素类名</param>
    /// <param name="out_featureDataset_name">输出路径为Geodatabae时, 要素数据集名</param>
    /// <param name="esriSRGeoTransformationTypeObject">地理基准面转换方式</param>
    /// <returns></returns>
    public IFeatureClass Project(IFeatureClass featureClass,
                                    ISpatialReference newSpatialReference,
                                    string out_path,
                                    string out_name,
                                    string out_featureDataset_name = null,
                                    object esriSRGeoTransformationTypeObject = null)
    {
        var geoDataset = (IGeoDataset)featureClass;
        var spatialReference = geoDataset.SpatialReference;
        IClone comparison = spatialReference as IClone;
        if (comparison.IsEqual((IClone)newSpatialReference))
            return null;
        // 检查地理基准面转换
        int gTransformationType = int.MinValue;
        if (esriSRGeoTransformationTypeObject is esriSRGeoTransformationType)
            gTransformationType = (int)esriSRGeoTransformationTypeObject;
        else if (esriSRGeoTransformationTypeObject is esriSRGeoTransformation2Type)
            gTransformationType = (int)esriSRGeoTransformationTypeObject;
        else if (esriSRGeoTransformationTypeObject is esriSRGeoTransformation3Type)
            gTransformationType = (int)esriSRGeoTransformationTypeObject;
        IGeoTransformation geoTransformation = null;
        if (gTransformationType != int.MinValue)
        {
            ISpatialReferenceFactory2 spatialReferenceFactory2 = new SpatialReferenceEnvironmentClass();
            geoTransformation = (IGeoTransformation)spatialReferenceFactory2.CreateGeoTransformation(gTransformationType);
        }
        // 打开输出路径的工作空间
        Type factoryType = null;
        string extension = System.IO.Path.GetExtension(out_path);
        if (extension == ".gdb")
        {
            factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
        }
        else if (extension == "")
        {
            factoryType = Type.GetTypeFromProgID("esriDataSourcesFile.ShapefileWorkspaceFactory");
            out_featureDataset_name = null;
        }
        else
            return null;
        var out_workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
        var out_workspace = out_workspaceFactory.OpenFromFile(out_path, 0);
        var featureWorkspace = (IFeatureWorkspace)out_workspace;
        // 删掉存在的同名要素类
        IFeatureClass out_featureClass = null;
        var workspace2 = (IWorkspace2)out_workspace;
        if (workspace2.get_NameExists(esriDatasetType.esriDTFeatureClass, out_name))
        {
            out_featureClass = featureWorkspace.OpenFeatureClass(out_name);
            ((IDataset)out_featureClass).Delete();
        }
        // 复制属性字段,添加修改的SHAPE字段
        int shapeFieldIndex = featureClass.FindField(featureClass.ShapeFieldName); // 获得Shape字段索引
        IFields out_fields = new FieldsClass();
        IFieldsEdit fieldsEdit = (IFieldsEdit)out_fields;
        for (int i = 0; i < featureClass.Fields.FieldCount; i++)
        {
            if (i == shapeFieldIndex)
            {
                IGeometryDef geometryDef = new GeometryDefClass();
                IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;
                geometryDefEdit.GeometryType_2 = featureClass.ShapeType;
                geometryDefEdit.SpatialReference_2 = newSpatialReference;
                IField shpField = new FieldClass();
                IFieldEdit pFieldEdit = (IFieldEdit)shpField;
                pFieldEdit.Name_2 = "SHAPE";
                pFieldEdit.AliasName_2 = "SHAPE";
                pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
                pFieldEdit.GeometryDef_2 = geometryDef;
                fieldsEdit.AddField(shpField); 
            }
            else
            {
                fieldsEdit.AddField(featureClass.Fields.Field[i]);
            }
        }
        // 创建要素类
        if (String.IsNullOrWhiteSpace(out_featureDataset_name))
        {   // 在Geodatabase/Shapefile工作空间建立要素类
            out_featureClass = featureWorkspace.CreateFeatureClass(out_name, out_fields,
                                                                    featureClass.CLSID, 
                                                                    featureClass.EXTCLSID,
                                                                    esriFeatureType.esriFTSimple, 
                                                                    "Shape", "");
        }
        else
        {   // 在Geodatabase的FeatureDataset建立要素类
            IFeatureDataset featureDataset = null;
            if (workspace2.get_NameExists(esriDatasetType.esriDTFeatureDataset, 
                                          out_featureDataset_name))
                featureDataset = featureWorkspace.OpenFeatureDataset(out_featureDataset_name);
            else
                featureDataset = featureWorkspace.CreateFeatureDataset(out_featureDataset_name, 
                                                                       spatialReference);
            out_featureClass = featureDataset.CreateFeatureClass(out_name, out_fields,
                                                                    featureClass.CLSID, 
                                                                    featureClass.EXTCLSID,
                                                                    esriFeatureType.esriFTSimple, 
                                                                    "Shape", "");
            Marshal.ReleaseComObject(featureDataset);
        }
        // 生成两个要素类字段的对应表
        Dictionary<int, int> fieldsDictionary = new Dictionary<int, int>();
        for (int i = 0; i < featureClass.Fields.FieldCount; i++)
        {
            if (featureClass.Fields.Field[i].Editable == false)
                continue; // 跳过系统自动生成的不可编辑的字段
            string field_name = featureClass.Fields.Field[i].Name.ToUpper();
            for (int j = 0; j < out_featureClass.Fields.FieldCount; j++)
            {
                string field_name2 = out_featureClass.Fields.Field[j].Name.ToUpper();
                if (field_name == field_name2)
                    fieldsDictionary.Add(i, j);
            }
        }
        // 向输出要素类中添加要素
        var searchFeatureCursor = featureClass.Search(null, false);
        var insertFeatureCursor = out_featureClass.Insert(true);
        IFeatureBuffer insertFeatureBuffer = out_featureClass.CreateFeatureBuffer();
        IFeature feature = searchFeatureCursor.NextFeature();
        int index = 0;
        while (feature != null)
        {
            // 复制要素的属性值
            foreach (KeyValuePair<int, int> keyValue in fieldsDictionary)
            {
                if (keyValue.Key == shapeFieldIndex) // 投影转换
                {
                    IGeometry5 geometry = feature.ShapeCopy as IGeometry5;
                    if (geoTransformation == null)
                        geometry.Project(newSpatialReference);
                    else
                        geometry.ProjectEx(newSpatialReference,
                                           esriTransformDirection.esriTransformForward,
                                           geoTransformation, false, 0, 0);
                    insertFeatureBuffer.Shape = geometry;
                }
                else
                {
                    insertFeatureBuffer.set_Value(keyValue.Value, 
                                                  feature.get_Value(keyValue.Key));
                }
            }
            insertFeatureCursor.InsertFeature(insertFeatureBuffer);
            feature = searchFeatureCursor.NextFeature();
            if (index++ % 1000 == 0) insertFeatureCursor.Flush();
        }
        insertFeatureCursor.Flush();
        Marshal.ReleaseComObject(spatialReference);
        Marshal.ReleaseComObject(out_workspace);
        Marshal.ReleaseComObject(searchFeatureCursor);
        Marshal.ReleaseComObject(insertFeatureCursor);
        Marshal.ReleaseComObject(insertFeatureBuffer);
        return out_featureClass;
    }
    

    2. 利用 ConvertFeatureClass 实现投影转换

    利用 IFeatureDataConverter.ConvertFeatureClass 实现 FeatureClass 的投影转换。

    /// <summary>
    /// 要素类从现有投影转换为新的投影
    /// </summary>
    /// <param name="featureClass">要素类</param>
    /// <param name="newSpatialReference">新的坐标参考系</param>
    /// <param name="out_path">输出路径</param>
    /// <param name="out_name">输出要素类名</param>
    /// <param name="out_featureDataset_name">输出路径为Geodatabae时, 要素数据集名</param>
    public void Project(IFeatureClass featureClass,
                        IQueryFilter queryFilter,
                        ISpatialReference newSpatialReference,
                        string out_path,
                        string out_name,
                        string out_featureDataset_name = null)
    {
        var geoDataset = (IGeoDataset)featureClass;
        var spatialReference = geoDataset.SpatialReference;
        IClone comparison = spatialReference as IClone;
        if (comparison.IsEqual((IClone)newSpatialReference))
            return;
        Type factoryType = null;
        string extension = System.IO.Path.GetExtension(out_path);
        if (extension == ".gdb")
        {
            factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory");
        }
        else if (extension == "")
        {
            factoryType = Type.GetTypeFromProgID("esriDataSourcesFile.ShapefileWorkspaceFactory");
            out_featureDataset_name = null;
        }
        else
            return;
        var out_workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType);
        var out_workspace = out_workspaceFactory.OpenFromFile(out_path, 0);
        // 删除已存在同名要素类
        IWorkspace2 out_workspace2 = (IWorkspace2)out_workspace;
        IFeatureWorkspace out_featureWorkspace = (IFeatureWorkspace)out_workspace2;
        if (out_workspace2.get_NameExists(esriDatasetType.esriDTFeatureClass, out_name))
        {
            var tmp_dataset = (IDataset)out_featureWorkspace.OpenFeatureClass(out_name);
            tmp_dataset.Delete();
        }
        // 输出要素数据集名
        IFeatureDataset out_featureDataset = null;
        IFeatureDatasetName out_featureDatasetName = null;
        if (!String.IsNullOrWhiteSpace(out_featureDataset_name))
        {
            if (out_workspace2.get_NameExists(esriDatasetType.esriDTFeatureDataset, 
                                              out_featureDataset_name))
                out_featureDataset = out_featureWorkspace.OpenFeatureDataset(out_featureDataset_name);
            else
                out_featureDataset = out_featureWorkspace.CreateFeatureDataset(out_featureDataset_name, 
                                                                               spatialReference);                                             
            // 判断要素数据集的空间参考系与新参考系是否相同
            var tmp_geoDataset = (IGeoDataset)out_featureDataset;
            var tmp_comparison = tmp_geoDataset.SpatialReference as IClone;
            if (!tmp_comparison.IsEqual((IClone)newSpatialReference))
                return;
            out_featureDatasetName = (IFeatureDatasetName)out_featureDataset.FullName;
        }
        // 输出工作空间名
        IDataset out_dataset = (IDataset)out_workspace;
        IWorkspaceName out_workspaceName = (IWorkspaceName)out_dataset.FullName;
        // 输出FeatureClass名
        IFeatureClassName out_featureClassName = new FeatureClassNameClass();
        IDatasetName out_datasetName = out_featureClassName as IDatasetName;
        out_datasetName.WorkspaceName = out_workspaceName;
        out_datasetName.Name = out_name;
        // 输入的工作空间
        IDataset in_dataset = featureClass as IDataset;
        IFeatureClassName in_featureClassName = in_dataset.FullName as IFeatureClassName;
        IWorkspace in_workspace = in_dataset.Workspace;
        //检查字段的有效性
        IFieldChecker fieldChecker = new FieldCheckerClass();
        fieldChecker.InputWorkspace = in_workspace;
        fieldChecker.ValidateWorkspace = out_workspace;
        IFields in_fields = featureClass.Fields;
        IEnumFieldError enumFieldError;
        IFields out_fields;
        fieldChecker.Validate(in_fields, out enumFieldError, out out_fields);
        // 获取源要素类的空间参考,可以通过获取源要素类中Shape字段的GeometryDef字段获得
        // 这里应该也可以自定义GeometryDef,实现源要素类的投影变换?
        IGeometryDef geometryDef = new GeometryDefClass();
        IGeometryDefEdit geometryDefEdit = (IGeometryDefEdit)geometryDef;
        geometryDefEdit.GeometryType_2 = featureClass.ShapeType;
        geometryDefEdit.SpatialReference_2 = newSpatialReference;
        // 调用IFeatureDataConverter接口进行数据转换
        IFeatureDataConverter featureDataConverter = new FeatureDataConverterClass();
        featureDataConverter.ConvertFeatureClass(in_featureClassName,
                                                    queryFilter,
                                                    out_featureDatasetName,
                                                    out_featureClassName,
                                                    geometryDef,
                                                    out_fields,
                                                    "", 1000, 0);      
    }
    

    上面的方法实现了ArcToolbox的Project工具

    方案1可以选择理基准面的转换方式,方案2不可以

    在不进行地理基准面转换时,对 478911个点的FeatureClass数据进行投影转换

    ArcMap Toolbox的 Project工具 用时 39.06秒
    IGeometry5.Project 用时 31.50秒
    IFeatureDataConverter.ConvertFeatureClass 用时 24.86秒
    
  • 相关阅读:
    Linux软件安装【JDK安装】
    接口自动化<009>:Python 接口自动化Mock使用
    接口自动化<008>:Python 自定义装饰器
    接口自动化<007>:Python 装饰器 @functools.wraps(func)
    接口自动化<006>:Python 装饰器 @retry
    接口自动化<005>:Python中*args 和 **kwargs的用法详解
    接口自动化<004>:json.dumps()、json.loads()与json.dump()、json.load()
    接口自动化<003>:request部分参数解析
    pycharm常用设置及快捷键说明
    接口自动化<002>:session.request 会话用作前后文管理器
  • 原文地址:https://www.cnblogs.com/lqqgis/p/12642491.html
Copyright © 2020-2023  润新知