using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.DataManagementTools; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Geoprocessing; using ESRI.ArcGIS.Geoprocessor; /* * Model:GP工具帮助类 * Description:GP工具帮助类 * Author:高山 * Finished:2017年12月4日 */ namespace Kingo.RuleCheck.CheckHelper { /// /// GP工具帮助类 /// public class GeoprocessorHelper { /// /// 调用GP工具检查要素类图层(pFeatureClass和inFeatureClass任意一个都可以)(自相交,是否闭合,是否有空洞等) /// /// 检查要素类路径 /// 输出路径 public static bool CheckGeometry(string inFeatureClass, string outTableName, string outPutMDBPath) { bool checkSuccess = true; try { ESRI.ArcGIS.Geoprocessor.Geoprocessor geoProcessor = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); geoProcessor.OverwriteOutput = true; ESRI.ArcGIS.DataManagementTools.CheckGeometry checkGeometryTool = new ESRI.ArcGIS.DataManagementTools.CheckGeometry(); if (!string.IsNullOrWhiteSpace(inFeatureClass)) { checkGeometryTool.in_features = inFeatureClass; } else { throw new Exception("请输入要检查的图层!"); } checkGeometryTool.out_table = System.IO.Path.Combine(outPutMDBPath, outTableName); IGeoProcessorResult tGeoResult = (IGeoProcessorResult)geoProcessor.Execute(checkGeometryTool, null); if (tGeoResult == null || tGeoResult.Status != ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded) { throw new Exception("CheckGeometryGP工具发生异常!"); } #region 检查是否可以查询到生成的属性表 Thread.Sleep(5000); //DateTime dtStart = DateTime.Now; //while (!DataCheckHelper.IsExistTable(outTableName, rdbHelper, DBOperator.DatabaseType.MSAccess)) //{ // //超过10秒不再检查,表示可能生成表异常 // if (DateDiff(dtStart, DateTime.Now) > 10) // { // checkSuccess = false; // break; // } //} #endregion return checkSuccess; } catch (Exception ex) { throw new Exception("检查图形自相交发生异常:" + ex.Message.ToString()); } } /// /// 计算时间差,返回单位秒 /// /// /// /// public static decimal DateDiff(DateTime DateTimeStart, DateTime DateTimeEnd) { TimeSpan tsStart = new TimeSpan(DateTimeStart.Ticks); TimeSpan tsEnd = new TimeSpan(DateTimeEnd.Ticks); TimeSpan ts = tsStart.Subtract(tsEnd).Duration(); decimal dateDiff = ts.Days * 86400 + ts.Hours * 3600 + ts.Minutes * 60 + ts.Seconds + decimal.Parse(ts.Milliseconds.ToString()) / 1000; return dateDiff; } /// /// 检查单个图形问题 /// /// /// public static List CheckGeometry(IGeometry pGeometry) { List lstError = new List(); try { IPointCollection polygonVertices = new PolygonClass(); IPointCollection lineVertices = pGeometry as IPointCollection; polygonVertices.AddPointCollection(lineVertices); ITopologicalOperator3 pTopology = polygonVertices as ITopologicalOperator3; esriNonSimpleReasonEnum reason = esriNonSimpleReasonEnum.esriNonSimpleSelfIntersections;//自相交 pTopology.IsKnownSimple_2 = false; if (!pTopology.get_IsSimpleEx(out reason)) { if (reason == esriNonSimpleReasonEnum.esriNonSimpleSelfIntersections) { lstError.Add("图形存在自相交"); } if (reason == esriNonSimpleReasonEnum.esriNonSimpleShortSegments) { lstError.Add("图形存在短线段"); } if (reason == esriNonSimpleReasonEnum.esriNonSimpleUnclosedRing) { lstError.Add("图形存在不闭合的环"); } if (reason == esriNonSimpleReasonEnum.esriNonSimpleEmptyPart) { lstError.Add("图形部分为空"); } } } catch (Exception ex) { throw ex; } return lstError; } /// /// 要素类和要素类相交分析 /// /// 输入要素类 /// 裁剪要素类 /// 输出shp的文件名(不加.shp后缀) public static void IntersectAnalysis(IFeatureClass inputFeatClass, IFeatureClass clipFeatClass, string outShpFileName) { Geoprocessor geoprocessor = null; IGpValueTableObject gpValueTableObject = null; try { geoprocessor = new Geoprocessor(); geoprocessor.OverwriteOutput = true; ESRI.ArcGIS.AnalysisTools.Intersect intersect = new ESRI.ArcGIS.AnalysisTools.Intersect(); gpValueTableObject = new GpValueTableObjectClass();//对两个要素类进行相交运算 gpValueTableObject.SetColumns(2); object o1 = inputFeatClass;//输入IFeatureClass 1 object o2 = clipFeatClass;//输入IFeatureClass 2 gpValueTableObject.AddRow(ref o1); gpValueTableObject.AddRow(ref o2); intersect.in_features = gpValueTableObject; intersect.out_feature_class = outShpFileName; intersect.join_attributes = "ALL";//"NO_FID";//"ONLY_FID" intersect.output_type = "INPUT"; geoprocessor.Execute(intersect, null); //Thread.Sleep(5000); //融合 //ESRI.ArcGIS.Geoprocessor.Geoprocessor geoprocessor = new Geoprocessor(); //ESRI.ArcGIS.DataManagementTools.Dissolve dissolve = new ESRI.ArcGIS.DataManagementTools.Dissolve(); //dissolve.in_features = dltbFeatureClass; //dissolve.out_feature_class = System.IO.Path.Combine(dataset.Workspace.PathName, OutputFeatureClassName); //dissolve.dissolve_field = DissolveAttributesName; ////d.statistics_fields = ""; //dissolve.multi_part = "MULTI_PART"; //geoprocessor.Execute(dissolve, null); } catch (Exception ex) { throw new Exception("相交分析发生异常:" + ex.Message.ToString()); } } /// /// 缓冲区分析(注意,输出图层必须和输入图层在同一要素集下面,否则报错) /// /// 要缓冲的要素类 /// 生成文件路径 /// 缓冲区大小 /// public static void BufferAnalysis(IFeatureClass pFeatureClass, string outputPath, double tolerance, ref IFeatureLayer pFeatureLayer) { try { Geoprocessor gp = new Geoprocessor(); gp.OverwriteOutput = true;//覆盖现有文件 ESRI.ArcGIS.AnalysisTools.Buffer buffer = new ESRI.ArcGIS.AnalysisTools.Buffer(); buffer.in_features = pFeatureClass; buffer.out_feature_class = outputPath; buffer.buffer_distance_or_field = tolerance + " Meters"; buffer.dissolve_option = "NONE";//(NONE|ALL|LIST) 这个要设成ALL,否则相交部分不会融合 //buffer.dissolve_field = "OBJECTID"; buffer.line_side = "FULL";//默认是"FULL",最好不要改否则出错 buffer.line_end_type = "ROUND";//默认是"ROUND",最好不要改否则出错 gp.Execute(buffer, null); IGeoProcessorResult tGeoResult = (IGeoProcessorResult)gp.Execute(buffer, null); if (tGeoResult == null || tGeoResult.Status != ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded) { throw new Exception("缓冲异常"); } //pFeatureLayer = GetOutPutFeatureClass(tGeoResult); } catch (Exception ex) { throw new Exception("缓冲区建立失败:" + ex.Message); } } //删除要素类 public static void DeleteFeatureDataset(IWorkspace ws, string name) { if (ws == null || string.IsNullOrEmpty(name)) { return; } IEnumDatasetName pEnumDatasetName; IFeatureWorkspace pFeaWorkspace; IDatasetName pDatasetName; try { pFeaWorkspace = ws as IFeatureWorkspace; pEnumDatasetName = ws.get_DatasetNames(esriDatasetType.esriDTFeatureClass ^ esriDatasetType.esriDTFeatureDataset); pEnumDatasetName.Reset(); pDatasetName = pEnumDatasetName.Next(); while (pDatasetName != null) { if (pDatasetName.Type == esriDatasetType.esriDTFeatureDataset) { //如果是要素集,则对要素集内的要素类进行查找 IEnumDatasetName pEnumFcName = (pDatasetName as IFeatureDatasetName).FeatureClassNames; IDatasetName pFcName = pEnumFcName.Next(); while (pFcName != null) { if (pFcName.Name.IndexOf(name) >= 0) { DeleteByName(pFeaWorkspace, pFcName); return; } pFcName = pEnumFcName.Next(); } } else { if (pDatasetName.Name.IndexOf(name) >= 0) { DeleteByName(pFeaWorkspace, pDatasetName); return; } } pDatasetName = pEnumDatasetName.Next(); } } catch (Exception ex) { throw ex; } } //删除名称对象 private static void DeleteByName(IFeatureWorkspace pFeaWorkspace, IDatasetName pDatasetName) { IFeatureWorkspaceManage pWorkspaceManager = pFeaWorkspace as IFeatureWorkspaceManage; pWorkspaceManager.DeleteByName(pDatasetName); } private static string ReturnMessages(Geoprocessor gp) { string ms = ""; if (gp.MessageCount > 0) { for (int Count = 0; Count <= gp.MessageCount - 1; Count++) { ms += "$" + gp.GetMessage(Count) + "\n\n"; } } return ms; } /// /// 由于Spatial Join 生成新的图层无ObjectID,所以先增加ObjectIDCopy字段,并将ObjcetID值赋值给ObjectIDCopy /// /// public static int CreateFiled(IFeatureClass pFeatureClass, string fieldName) { try { if (pFeatureClass == null) { return -1; } IClass pClass = pFeatureClass as IClass; if (pFeatureClass.Fields.FindField(fieldName) < 0) { IField field = new ESRI.ArcGIS.Geodatabase.FieldClass(); IFieldEdit2 fieldEdit2 = field as IFieldEdit2; fieldEdit2.Type_2 = esriFieldType.esriFieldTypeString; fieldEdit2.Name_2 = fieldName; pClass.AddField(field); } string updateSQL = string.Format("UPDATE {0} SET {1}=''", (pFeatureClass as FeatureClass).BrowseName, fieldName); pFeatureClass.FeatureDataset.Workspace.ExecuteSQL(updateSQL); return pFeatureClass.FindField(fieldName); } catch (Exception ex) { throw new Exception("创建OBJECTIDCopy字段异常:" + ex.Message); } } /// /// 字段计算器 /// /// public static void CalculateField(CalculateField calc) { try { Geoprocessor gp = new Geoprocessor(); gp.OverwriteOutput = true; //CalculateField calc = new CalculateField(); ////计算选中项时,直接传IFeatureLayer,对应bug10664 //calc.in_table = pFeatureLayer; //calc.field = fieldName; //calc.expression = txtExpression.Text; ////calc.expression = expreesion; //calc.expression_type = "PYTHON"; IGeoProcessorResult tGeoResult = (IGeoProcessorResult)gp.Execute(calc, null); if (tGeoResult == null || tGeoResult.Status != ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded) { throw new Exception("字段计算执行失败!"); } } catch { throw; } } /// /// 删除属性表字段 /// /// 需要添加字段的IFeatureLayer /// 添加的字段的名称 /// public static void DeleteField(IFeatureClass layer, string fieldName) { try { ITable pTable = (ITable)layer; IFields pfields; IField pfield; pfields = pTable.Fields; int fieldIndex = pfields.FindField(fieldName); if (fieldIndex < 0) { return; } pfield = pfields.get_Field(fieldIndex); pTable.DeleteField(pfield); } catch { //throw new Exception("删除" + fieldName + "字段异常:" + ex.Message); } } ///// ///// 获取GP生成的图层 ///// ///// //private static IFeatureLayer GetOutPutFeatureClass(IGeoProcessorResult tGeoResult) //{ // IGPUtilities pGPUtilities = new GPUtilitiesClass(); // IFeatureClass pFeatureClass = null; // IQueryFilter pQueryFilter = null; // try // { // pGPUtilities.DecodeFeatureLayer(tGeoResult.GetOutput(0), out pFeatureClass, out pQueryFilter); // int count = pFeatureClass.FeatureCount(null); //统计Feature对象个数 // IFeatureCursor pCursor = pFeatureClass.Insert(true); //提取FeatureCursor对象 // IFeatureLayer pFeatureLayer = new FeatureLayerClass(); // pFeatureLayer.FeatureClass = pFeatureClass; // pFeatureLayer.Name = pFeatureClass.AliasName; // return pFeatureLayer; // } // catch (Exception ex) // { // throw new Exception("获取生成图层异常:" + ex.Message); // } // finally // { // if (pQueryFilter != null) // { // Marshal.ReleaseComObject(pQueryFilter); // } // } //} /// /// 要素与图层做压盖分析 /// /// /// /// public static List FeatureIntersectFeatureClass(IGeometry pGeometry, List pLayers) { List result = new List(); try { if (pGeometry != null && !pGeometry.IsEmpty && pLayers != null) { foreach (IFeatureLayer item in pLayers) { IIdentify identify = item as IIdentify; if (identify == null) continue; ESRI.ArcGIS.esriSystem.IArray array = identify.Identify(pGeometry); if (array == null) continue; for (int i = 0; i < array.Count; i++) { IRowIdentifyObject row = (IRowIdentifyObject)array.get_Element(i); if (row == null) continue; IFeature f = row.Row as IFeature; result.Add(f); } } } } catch (Exception ex) { throw ex; } return result; } /// /// 融合 /// /// 源要素 /// 输出要素 /// 融合字段 /// public static IFeatureClass Dissolve(IFeatureClass sourceFClass,string out_feature_class, string dissolve_field) { ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); gp.OverwriteOutput = true; //是否覆盖原文件 try { ESRI.ArcGIS.DataManagementTools.Dissolve diss = new ESRI.ArcGIS.DataManagementTools.Dissolve(); diss.in_features = sourceFClass; diss.out_feature_class = out_feature_class;//"F:\\新建文件地理数据库.gdb\\diss_name"; diss.multi_part = "false"; //Boolean只能填写"false"或"true" diss.dissolve_field = dissolve_field;//"MC;DM"; gp.Execute(diss, null); IGeoProcessorResult result = (IGeoProcessorResult)gp.Execute(diss, null); return gp.Open(result.ReturnValue) as IFeatureClass; } catch { throw new Exception("图形融合发生异常:" + ReturnMessages(gp)); } } /// /// 面邻域 /// /// 源要素 /// 输出表 /// 融合字段 /// public static void PolygonNeighbors(IFeatureClass sourceFClass, string out_table, string in_fields) { ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); gp.OverwriteOutput = true; //是否覆盖原文件 try { ESRI.ArcGIS.AnalysisTools.PolygonNeighbors polygonNeighbors = new ESRI.ArcGIS.AnalysisTools.PolygonNeighbors(); polygonNeighbors.in_features = sourceFClass; polygonNeighbors.out_table = out_table; polygonNeighbors.in_fields = in_fields; //"MC;DM"; gp.Execute(polygonNeighbors, null); } catch { throw new Exception("面邻域发生异常:" + ReturnMessages(gp)); } } /// /// 擦除 /// /// /// /// /// public static IFeatureClass Erase(IFeatureClass in_features, IFeatureClass erase_features, string out_feature_class) { ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); gp.OverwriteOutput = true; //是否覆盖原文件 try { ESRI.ArcGIS.AnalysisTools.Erase erase = new ESRI.ArcGIS.AnalysisTools.Erase(); erase.in_features = in_features; erase.erase_features = erase_features; erase.out_feature_class = out_feature_class; gp.Execute(erase, null); IGeoProcessorResult result = (IGeoProcessorResult)gp.Execute(erase, null); return gp.Open(result.ReturnValue) as IFeatureClass; } catch { throw new Exception("擦除发生异常:" + ReturnMessages(gp)); } } /// /// 多部件至单部件 /// /// /// /// public static IFeatureClass MultipartToSinglepart(IFeatureClass sourceFClass, string out_feature_class) { ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); gp.OverwriteOutput = true; //是否覆盖原文件 try { ESRI.ArcGIS.DataManagementTools.MultipartToSinglepart multipartToSinglepart = new MultipartToSinglepart(); multipartToSinglepart.in_features = sourceFClass; multipartToSinglepart.out_feature_class = out_feature_class; gp.Execute(multipartToSinglepart, null); IGeoProcessorResult result = (IGeoProcessorResult)gp.Execute(multipartToSinglepart, null); return gp.Open(result.ReturnValue) as IFeatureClass; } catch { throw new Exception("多部件至单部件发生异常:" + ReturnMessages(gp)); } } /// /// FcToFeatureClass /// /// public static void FeatureClassToFeatureClass(string inputFeatureClass, string outPath, string outName, ref IFeatureClass featureClass, bool getResult = true) { try { //导出要素类 ESRI.ArcGIS.Geoprocessor.Geoprocessor geoprocessor = new Geoprocessor(); geoprocessor.OverwriteOutput = true; ESRI.ArcGIS.ConversionTools.FeatureClassToFeatureClass fcToFc = new ESRI.ArcGIS.ConversionTools.FeatureClassToFeatureClass(); fcToFc.in_features = inputFeatureClass; fcToFc.out_path = outPath; fcToFc.out_name = outName; //fcToFc.where_clause = ; IGeoProcessorResult tGeoResult = null; try { tGeoResult = (IGeoProcessorResult)geoprocessor.Execute(fcToFc, null); } catch { //获取geoprocessor更详细错误信息 object sev = null; throw new Exception(geoprocessor.GetMessages(ref sev)); } if (tGeoResult == null || tGeoResult.Status != ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded) { throw new Exception("导出要素类失败:" + ReturnMessages(geoprocessor)); } if (getResult) { featureClass = GetOutPutFeatureClass(tGeoResult); } } catch (Exception ex) { throw ex; } } /// /// 相交分析 /// /// 输入要素类集合 /// 输出要素类地址(包含图层名称) /// 返回相交的结果图层 /// 是否返回相交后的结果图层 /// 相交后保留那些字段:ALL,NO_FID,ONLY_FID /// "INPUT","LINE","POINT" /// 相交容差 public static void IntersectAnalysis(List listPath, string outPath, ref IFeatureClass featureClass, bool getResult = true, string join_attributes = "ALL", string output_type = "INPUT", string cluster_tolerance = "0.0001") { Geoprocessor geoprocessor = null; IGeoProcessorResult tGeoResult = null; IGpValueTableObject gpValueTableObject = null; try { geoprocessor = new Geoprocessor(); geoprocessor.OverwriteOutput = true; ESRI.ArcGIS.AnalysisTools.Intersect intersect = new ESRI.ArcGIS.AnalysisTools.Intersect(); gpValueTableObject = new GpValueTableObjectClass(); gpValueTableObject.SetColumns(listPath.Count); foreach (var item in listPath) { object o = item; gpValueTableObject.AddRow(ref o); } intersect.in_features = gpValueTableObject; intersect.out_feature_class = outPath; intersect.join_attributes = join_attributes;//"NO_FID";"ONLY_FID" intersect.output_type = output_type;// "INPUT","LINE","POINT"; try { tGeoResult = (IGeoProcessorResult)geoprocessor.Execute(intersect, null); } catch { object sev = null; string message = geoprocessor.GetMessages(ref sev); throw new Exception(message); } if (tGeoResult == null || tGeoResult.Status != ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded) { throw new Exception(ReturnMessages(geoprocessor)); } if (getResult) { featureClass = GetOutPutFeatureClass(tGeoResult); } } catch (Exception ex) { throw new Exception("相交异常:" + ex.Message.ToString()); } finally { if (gpValueTableObject != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(gpValueTableObject); } if (tGeoResult != null) { System.Runtime.InteropServices.Marshal.ReleaseComObject(tGeoResult); } } } /// /// 筛选 /// /// /// /// /// /// public static void SelectAnalysis(string in_features, string out_feature_class, string where_clause, ref IFeatureClass featureClass, bool getResult = true) { ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); gp.OverwriteOutput = true; //是否覆盖原文件 try { ESRI.ArcGIS.AnalysisTools.Select select = new ESRI.ArcGIS.AnalysisTools.Select(); select.in_features = in_features; select.out_feature_class = out_feature_class; select.where_clause = where_clause; IGeoProcessorResult tGeoResult = null; tGeoResult = (IGeoProcessorResult)gp.Execute(select, null); if (getResult) { featureClass = GetOutPutFeatureClass(tGeoResult); } } catch { throw new Exception("筛选发生异常:" + ReturnMessages(gp)); } } /// /// 擦除/相减分析 /// /// public static void EraseAnalysis(string in_features, string erase_features, string out_feature_class, ref IFeatureClass featureClass, bool getResult = true, double tolerance = 0.0001) { try { Geoprocessor geoprocessor = new Geoprocessor(); geoprocessor.OverwriteOutput = true; ESRI.ArcGIS.AnalysisTools.Erase erase = new ESRI.ArcGIS.AnalysisTools.Erase(); erase.in_features = in_features; erase.erase_features = erase_features; erase.out_feature_class = out_feature_class; erase.cluster_tolerance = tolerance; IGeoProcessorResult tGeoResult = null; try { tGeoResult = (IGeoProcessorResult)geoprocessor.Execute(erase, null); } catch (Exception) { object sev = null; throw new Exception(geoprocessor.GetMessages(ref sev)); } if (tGeoResult == null || tGeoResult.Status != ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded) { throw new Exception(ReturnMessages(geoprocessor)); } if (getResult) { featureClass = GetOutPutFeatureClass(tGeoResult); } } catch (Exception ex) { throw ex; } } /// /// 多部件转单部件 /// /// /// public static void MultipartToSinglepart(string in_features, string out_feature_class, ref IFeatureClass featureClass, bool getResult = true) { ESRI.ArcGIS.Geoprocessor.Geoprocessor gp = new ESRI.ArcGIS.Geoprocessor.Geoprocessor(); gp.OverwriteOutput = true; //是否覆盖原文件 try { MultipartToSinglepart multipartToSinglepart = new MultipartToSinglepart(); multipartToSinglepart.in_features = in_features; multipartToSinglepart.out_feature_class = out_feature_class; gp.Execute(multipartToSinglepart, null); IGeoProcessorResult tGeoResult = null; try { tGeoResult = (IGeoProcessorResult)gp.Execute(multipartToSinglepart, null); } catch (Exception) { object sev = null; throw new Exception(gp.GetMessages(ref sev)); } if (tGeoResult == null || tGeoResult.Status != ESRI.ArcGIS.esriSystem.esriJobStatus.esriJobSucceeded) { throw new Exception(ReturnMessages(gp)); } if (getResult) { featureClass = GetOutPutFeatureClass(tGeoResult); } } catch { throw new Exception("多部件转单部件发生异常:" + ReturnMessages(gp)); } } /// /// 获取GP生成的图层 /// /// private static IFeatureClass GetOutPutFeatureClass(IGeoProcessorResult tGeoResult) { IGPUtilities pGPUtilities = new GPUtilitiesClass(); IFeatureClass pFeatureClass = null; IQueryFilter pQueryFilter = null; try { pGPUtilities.DecodeFeatureLayer(tGeoResult.GetOutput(0), out pFeatureClass, out pQueryFilter); return pFeatureClass; } catch (Exception ex) { throw new Exception("获取生成图层异常:" + ex.Message); } } } }