天天看點

基于C#的ArcEngine二次開發44: GDB矢量檔案檢查結果導出GDB/SHP的思路分析1 導出GDB檔案2 導出shp檔案(以點要素為例)

在對GDB格式的矢量資料庫進行檢查時,經常需要将檢查結果導出為shp檔案,或者GDB格式檔案;形成了兩個小的處理思路,在這裡總結分享。

1 導出GDB檔案

介紹了兩種方法,主要針對要導出的資料格式為GDB類型的輸出檔案;兩種思路的差異是:

  • 前者将整個GDB以檔案形式拷貝,然後在删除不需要的圖層;
  • 後者建立GDB檔案,然後隻拷貝需要的要素類

1.1 整體拷貝+圖層删除思路

該思路将整個GDB檔案視為一個目錄,直接拷貝到結果目錄中,然後再删除多餘圖層的方法

1.1.1 GDB檔案整體拷貝

之前博文C#程式設計學習13:檔案及檔案夾檢索與拷貝已經對檔案夾拷貝的代碼進行了總結

//需要引用System.IO命名空間,實作代碼如下:
 
private static bool CopyDirectory(string SourcePath, string DestinationPath, bool overwriteexisting)  
{  
   bool ret = false;  
   try  
   {  
       if (Directory.Exists(SourcePath))  
       {  
           //不存在則建立
           if (Directory.Exists(DestinationPath) == false)  
               Directory.CreateDirectory(DestinationPath);  
           
           foreach (string fls in Directory.GetFiles(SourcePath))  
           {  
               FileInfo flinfo = new FileInfo(fls);  
               flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting);  
           }  
           foreach (string drs in Directory.GetDirectories(SourcePath))  
           {  
               DirectoryInfo drinfo = new DirectoryInfo(drs);  
               if (CopyDirectory(drs, DestinationPath + drinfo.Name, overwriteexisting) == false)  
                   ret = false;  
           }  
       }  
       ret = true;  
   }  
   catch (Exception ex)  
   {  
       ret = false;  
   }  
   return ret;  
}
//使用方法:
 
bool copy = CopyDirectory("c:\\src.gdb", "c:\\temp\\dst.gdb", true);
           

1.1.2 删除多餘圖層

之前博文:基于C#的ArcEngine二次開發40:如何删除臨時GDB檔案;對此做過分析

public void DeleteFeatureClass(IWorkspace workspace, string featueClassName)
{
    //根據名稱删除資料庫要素
    IFeatureWorkspaceManage featureWorkspaceMange = (workspace as IFeatureWorkspace) as IFeatureWorkspaceManage;
    IEnumDatasetName enumDatasetName = workspace.get_DatasetNames(esriDatasetType.esriDTFeatureClass);
    IDatasetName datasetName = enumDatasetName.Next();
 
    while (datasetName != null)
    {
        if (datasetName.Name.Equals(featueClassName))
        {
            featureWorkspaceMange.DeleteByName(datasetName);//删除指定要素類
            break;
        }
        datasetName = enumDatasetName.Next();
    }
}
           

1.1.3 拷貝檢查

檢查LRDL的name是否為空的示例

private void checkOutput(string srcGDB, string dstGDB) 
{
    //1. GDB拷貝
    if(!System.IO.Exists(dstGDB))
    {
        CopyDirectory(srcGDB, dstGDB);
    }
    //2. 打開檔案
    IWorkspaceFactory worFact =new FileGDBWorkspaceFactory();
    IWorkspace workspace = worFact.OpenFromFile(dstGDB, 0);
    //3. 假定移除AANP層
    DeleteFeatureClass("AANP");   
    //4. 假設檢查LRDL,需要增加字段進行錯誤資訊記錄
    IFeatureClass poFeaterClass = ofeatureWorkspace.OpenFeatureClass("LRDL");
    int checkFieldIndex = poFeaterClass.FindField("檢查結果記錄");
    if(checkFieldIndex == -1)
    {
        IFields pFields = new FieldClass();
        IFieldEdit pFieldEdit = pFields as IFieldEdit;
        pFieldEdit.Name_2 = "檢查結果記錄";
        pFieldEdit.Type_2 = filedType;    
        pFieldEdit.Length_2 = fieldLength;
        pTable.AddField(pFieldEdit);    
    }
    checkFieldIndex = poFeaterClass.FindField("檢查結果記錄");
    //5. 周遊每個要素進行檢查
    IFeatureCursor pCursor = poFeaterClass.Update(null, false);
    IFeature pFeature = pCursor.NextFeature();
    while(pFeature != null)
    {
        int nameIndex = pFeature.get_Field("RNN");
        string name = pFeature.get_Value(nameIndex).ToString().Trim();
        if(name == "")
        {
            pFeature.get_Value(checkFieldIndex, "名稱為空,錯誤")
            pCursor.UpdateFeature();
        }
        else
        {
            pCursor.DeleteFeature();
        }
        pFeature = pCursor.NextFeature();
    }
    //6. 登出對象
    Marshal.FinalReleaseComObject(pCursor);
    Marshal.FinalReleaseComObject(poFeaterClass);
    Marshal.FinalReleaseComObject(workspace);
    GC.Collect();
}
           

1.2 建立GDB+ConvertFeatureClass

1.2.1 建立GDB檔案

該内容見系列文章:

  • 基于C#的ArcEngine二次開發39:GP工具的使用--界面、參數及示例代碼
  • 基于C#的ArcEngine二次開發29:GDB檔案操作及異常處理

使用GP工具建立:

//gdbFolder:    設定存放将要建立GDB檔案的目錄
//gdbFileName:    設定GDB檔案的名稱
public void createGDBFile(string gdbFolder, string gdbFileName)
{
    //建立gp工具
    ESRI.ArcGIS.Geoprocessor.Geoprocessor pGeoprocessor = ESRI.ArcGIS.Geoprocessor.Geoprocessor{};
    pGeoprocessor.OverwriteOutput = true;
    pGeoprocessor.AddOutputToMap = false;
 
    //建立GDB檔案
    CreateFileGDB processor = new CreateFileGDB {};
    processor.out_folder_path = gdbFolder;
    processor.out_name = gdbFileName;
 
    pGeoprocessor.Execute(processor, null);
}
           

1.2.2 ConvertFeatureClass

此部分參見之前的文章:基于C#的ArcEngine二次開發29:GDB檔案操作及異常處理

public void CopyLayerFromGDB(string inPath, string gdbLayerName, string ouPath, string ouGdbLayerName)
{
    //1. 指定輸入要素
    IWorkspaceFactory workspaceFactory = new ESRI.ArcGIS.DataSourcesGDB.FileGDBWorkspaceFactoryClass();
    IWorkspace iworkspace = iworkspaceFactory.OpenFromFile(inPath, 0);
    IFeatureWorkspace ifeatureWorkspace = (IFeatureWorkspace)iworkspace;
    IFeatureClass ipFeaterClass = ifeatureWorkspace.OpenFeatureClass(checkLayerName);
    
    //2. 設定輸入圖層名
    IWorkspaceName inWorkspaceName = (inWorkspace as IDataset).FullName as IWorkspaceName ;     
    IFeatureClassName inFeatureClassName = new FeatureClassNameClass();
    IDatasetName inDatasetName = (IDatasetName)inFeatureClassName;
    inDatasetName.WorkspaceName = inWorkspaceName;
    inDatasetName.Name = gdbLayerName;

    //3. 在目标GDB中建立導出圖層
    IWorkspaceFactory oworkspaceFactory = new AccessWorkspaceFactory();
    IWorkspace oworkspace = oworkspaceFactory.OpenFromFile(ouPath, 0);
    IFeatureWorkspace ofeatureWorkspace = (IFeatureWorkspace)workspace;
    IFeatureClass poFeaterClass = ofeatureWorkspace.OpenFeatureClass(mdbLayerName);
    IWorkspace2 oworkspace2 = (IWorkspace2)oworkspace;
    if (oworkspace2.get_NameExists(esriDatasetType.esriDTFeatureClass, checkLayerName))
    {
        IFeatureClass pFC = ofeatureWorkspace.OpenFeatureClass(checkLayerName);
        IDataset pDS = pFC as IDataset;
        pDS.Delete();
     }

    //4. 建立輸出要素類
   IWorkspaceName ouWorkspaceName = (ouWorkspace as IDataset).FullName as IWorkspaceName ;     
   IFeatureClassName ouFeatureClassName = new FeatureClassNameClass();
   IDatasetName ouDatasetName = (IDatasetName)ouFeatureClassName;
   ouDatasetName.WorkspaceName = ouWorkspaceName;
   ouDatasetName.Name = ouGdbLayerName;
    
    //5. 字段指派
    IFieldChecker fieldChecker = new FieldCheckerClass();
    fieldChecker.InputWorkspace = iworkspace;//輸入資料集工作空間
    fieldChecker.ValidateWorkspace = ouWorkpace;//輸出工作空間
 
    IFields outFeatureClassFields;
    IEnumFieldError enumFieldError;            
    fieldChecker.Validate(inFeatureClassFields, out enumFieldError, out outFeatureClassFields);
    //6. 幾何定義
    IField geometryField =  outFeatureClassFields.get_Field(outFeatureClassFields.FindField(inFeatureClass.ShapeFieldName));
    IGeometryDef geometryDef = geometryField.GeometryDef;

    //7. 查詢語句 -- 如果還要進行上述的LRDL層的空值監測,直接寫到sql語句中就可以了
    QueryFilter qf = new QueryFilterClass();
    qf.WhereClause = "";

    //8. 調用轉換函數
    IFeatureDataConverter fctofc = new FeatureDataConverterClass();
IEnumInvalidObject enumErrors = fctofc.ConvertFeatureClass(inFeatureClassName, qf, null, outFeatureClassName, geometryDef, outFeatureClassFields, "", 1000, 0);

}
           

調用與第一種類似,打開拷貝出的GDB檔案的興趣圖層,然後直接進行處理就行了

2 導出shp檔案(以點要素為例)

這個函數是針對對資料進行處理後,結果以資料點的形式存儲在shp中,自定義屬性字段并輸出要素

/// <summary>
        /// 将點集導出為shp檔案
        /// </summary>
        /// <param name="inPath">輸入資料集</param>
        /// <param name="liPts">要導出的點集</param>
        /// <param name="checkLayerName">點集的來源圖層</param>
        /// <param name="ouPath">導出的shape檔案的結果儲存路徑</param>
        public void ExportPtsToShapefile(string inPath, List<IPoint> liPts, string checkLayerName, string ouPath)
         {
             //1. 打開工作空間
             string strShapeFolder = System.IO.Path.GetDirectoryName(ouPath);
             const string strShapeFieldName = "shape";
             IWorkspaceFactory pWSF = new ShapefileWorkspaceFactoryClass();
             IFeatureWorkspace pWS = (IFeatureWorkspace)pWSF.OpenFromFile(strShapeFolder,0);
             //2. 設定字段集
             IFields pFields = new FieldsClass();
             IFieldsEdit pFieldsEdit = (IFieldsEdit)pFields;
 
             //3. 設定字段
             IField pField = new FieldClass();
             IFieldEdit pFieldEdit = (IFieldEdit)pField;
             //4. 建立類型為幾何類型的字段
             pFieldEdit.Name_2 = strShapeFieldName;
             pFieldEdit.Type_2 = esriFieldType.esriFieldTypeGeometry;
             //為esriFieldTypeGeometry類型的字段建立幾何定義,包括類型和空間參照
             IGeometryDef pGeoDef = new GeometryDefClass(); //The geometry definition for the field if IsGeometry is TRUE.
             IGeometryDefEdit pGeoDefEdit = (IGeometryDefEdit)pGeoDef;
 
             //4.1 将原始資料的投影資訊指派給新的檢查結果圖層
             IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();
             IWorkspace workspace = workspaceFactory.OpenFromFile(inPath, 0);
             IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;
             IFeatureClass pFeaterClass = featureWorkspace.OpenFeatureClass(checkLayerName);//這個地方可以繼續研究如何更簡便的擷取工作空間的坐标系統
             IGeoDataset geoDatabase = pFeaterClass as IGeoDataset;
             //設定坐标系統
             IProjectedCoordinateSystem tProjectedCoordinateSystem = geoDatabase.SpatialReference as IProjectedCoordinateSystem;
             pGeoDefEdit.SpatialReference_2 = tProjectedCoordinateSystem;   
             pGeoDefEdit.GeometryType_2 = esriGeometryType.esriGeometryPoint;          
             pFieldEdit.GeometryDef_2 = pGeoDef;
             pFieldsEdit.AddField(pField);
 
             //添加其他的字段
             pField = new FieldClass();
             pFieldEdit = (IFieldEdit)pField;
             pFieldEdit.Name_2 = "X";
             pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
             //pFieldEdit.Precision_2 = 7;//數值精度
             //pFieldEdit.Scale_2 = 6;//小數點位數
             pFieldsEdit.AddField(pField);
 
             pField = new FieldClass();
             pFieldEdit = (IFieldEdit)pField;
             pFieldEdit.Name_2 = "Y";
             pFieldEdit.Type_2 = esriFieldType.esriFieldTypeDouble;
             //pFieldEdit.Precision_2 = 7;//數值精度
             //pFieldEdit.Scale_2 = 6;//小數點位數
             pFieldsEdit.AddField(pField);
 
             //建立shapefile
             string strShapeName = System.IO.Path.GetFileName(ouPath);           
             IFeatureClass shpFeatureClass = pWS.CreateFeatureClass(strShapeName, pFields, null, null, esriFeatureType.esriFTSimple, strShapeFieldName, "");
 
             //5. 向shape中添加要素
             IPoint pPoint = new PointClass();
             foreach (IPoint pt in liPts)
             {
                 IFeature pFeature = shpFeatureClass.CreateFeature();
                 //5.1 将點坐标設定到屬性表中
 
                 //擷取字段,并對字段值進行屬性指派
                 IFields fields = pFeature.Fields;//擷取該對象的字段
                 int xIdx = fields.FindFieldByAliasName("X");
                 pFeature.set_Value(xIdx, pt.X);
                 int yIdx = fields.FindFieldByAliasName("Y");
                 pFeature.set_Value(yIdx, pt.Y);
 
                 //5.2 将點設定為shp檔案的圖形要素
                 pFeature.Shape = pt;//這一句十分重要,不然點顯示不出來
                 //如果導出的其他類型的元素(IPolygon,IPolyline)
                 pFeature.Store();
             }                               
         }
           

支援作者,歡迎關注個人公衆賬号:

基于C#的ArcEngine二次開發44: GDB矢量檔案檢查結果導出GDB/SHP的思路分析1 導出GDB檔案2 導出shp檔案(以點要素為例)

繼續閱讀