当前位置: 代码迷 >> GIS >> ArcEngine中合龙断开的线要素(根据几何判断)
  详细解决方案

ArcEngine中合龙断开的线要素(根据几何判断)

热度:822   发布时间:2016-05-05 06:02:53.0
ArcEngine中合并断开的线要素(根据几何判断)

       在上一篇ArcEngine环境下合并断开的线要素(根据属性)随笔中介绍了如何通过shp文件属性表中相同的属性字段进行线要素的合并。今天刚把通过几何条件判断的方式连接断开的线要素的ArcGIS 插件完成,在这里把思路和代码和大家分享下:

一,程序思路和实现过程

1.首先读取shp线文件,将各条线要素遍历,存储在List<IFeature>,这里之所以不存在List<IPolyline>和List<IGeometry>中的原因是后两者会丢失要素的属性信息;

2.为了简化合并算法的逻辑和复杂性,采用分治思想。将线要素分为需要进行合并和不需要进行合并(独立的线,ToPoint或FromPoint是“节点”的线和ToPoint,FromPoint均是“节点”线)的两大类,分别存储在两个集合中;

3.现在只需对需要进行合并的的线要素集合进行合并操作。首先从集合中选取一条Polyline,然后在集合剩下的元素中寻找与其ToPoint或FromPoint相同的线要素,然后使用ITopologicalOperator2.Union()方法进行合并,然后寻找和合并后新的Polyline的ToPoint或FromPoint相同的线要素继续合并,没合并一次,就将合并入的Polyline从集合中移除,直到剩下的Polyline不可和当前合并的Polyline合并为止,这样就得到了第一条合并好的Polyline。接着从集合剩下的线要素再找一条Polyline开始新一轮合并操作,直到List<IFeature>为空,整个合并操作结束;

4.得到合并好的List<IFeature> mergeResultLineList后,需要为其添加属性(NAME等字段),通过IFeatureBuffer接口写入shape和Fields,然后Flush到文件中,结束。

二,程序实例和结果

 

                                                              图1  程序执行结果

                                                        图2  合并前的属性表

                                                        图3  合并后的属性表

三,程序详细代码

 

  1 public class MergeDisconnectLine : ESRI.ArcGIS.Desktop.AddIns.Button  2     {  3   4         public int CountPercent { get; set; }  5         IMap map = null;  6         private List<IFeature> DisconnPolylineList = new List<IFeature>(); 10         private List<IFeature> firstRowFeatureList = new List<IFeature>(); 11  12         public MergeDisconnectLine() 13         { 14             IMxDocument mxDoc = ArcMap.Application.Document as IMxDocument; 15             map = mxDoc.FocusMap; 16         } 17         protected override void OnClick() 18         { 19             // 20             //  TODO: Sample code showing how to access button host 21             // 22             ArcMap.Application.CurrentTool = null; 23  24             //计算程序耗时 25             DateTime beforDT = System.DateTime.Now; 27             //Application.EnableVisualStyles(); 28             //Application.SetCompatibleTextRenderingDefault(false); 29             ////ProgressBar pBar = new ProgressBar(); 30             //Application.Run(new ProgressBar());            32             List<IFeature> allPolylineList = getAllPolyline(); 33             List<IFeature> noNeedUnionLineList = getWithoutNeedUnionLineList(allPolylineList); 34             List<IFeature> toUnionLineList = GetToUnionLineList(allPolylineList, noNeedUnionLineList); 35             List<IFeature> unionLineList = MergeLineListOperate(toUnionLineList); 36             AddField(); 37             WriteNoNeedUnionLineToFile(noNeedUnionLineList); 38             WriteUnionLineToFile(unionLineList, firstRowFeatureList); 39             DateTime afterDT = System.DateTime.Now; 40             TimeSpan ts = afterDT.Subtract(beforDT); 41             int minutes = ts.Minutes; 42             int seconds = ts.Seconds%60; 43             //pBar.Hide(); 44             MessageBox.Show("线要素合并结束,运行程序共耗时约:" + minutes + ""+ seconds + ""); 45         } 48         //获取shp文件中所有的Polyline(IFeature)对象 49         public List<IFeature> getAllPolyline() 50         { 51             IFeatureLayer featureLayer = map.get_Layer(1) as IFeatureLayer; 52             IFeatureClass featureClass = featureLayer.FeatureClass; 53             IQueryFilter queryFilter = new QueryFilter(); 54             queryFilter.WhereClause = ""; 55             IFeatureCursor pFeatCursor = featureClass.Search(queryFilter, false); 56             IFeature pFeature = pFeatCursor.NextFeature(); 57  58             while (pFeature != null) 59             { 60                 if (featureClass.ShapeType == esriGeometryType.esriGeometryPolyline) 61                 { 62                     DisconnPolylineList.Add(pFeature); 63                 } 64                 pFeature = pFeatCursor.NextFeature();                  66             } 67             return DisconnPolylineList; 68         }170 171         //获取需要进行合并的线(是noNeedUnionLineList的补集)172         public List<IFeature> GetToUnionLineList(List<IFeature> allPolylineList, List<IFeature> noNeedUnionLineList)173         {174             List<IFeature> toUnionLineList = allPolylineList;175             foreach (IFeature featureLine in noNeedUnionLineList)176             {177                 toUnionLineList.Remove(featureLine);178             }179             return toUnionLineList;180         }181 182         //获取不需要进行合并的线(独立线,一端是节点的线,和两端都是节点的线)       183         public List<IFeature> getWithoutNeedUnionLineList(List<IFeature> allPolylineList)184         {185             List<IFeature> noNeedUnionLineList = new List<IFeature>();186             foreach (IFeature featureLine in allPolylineList)187             {188                 int count = featureLine.Fields.FieldCount;189                 List<IFeature> allPolylineListCopy = allPolylineList;190                 IGeometry geoLine = featureLine.Shape;191                 IPolyline lineFirst = geoLine as IPolyline;192                 IPoint startPt1 = lineFirst.FromPoint;193                 IPoint endPt1 = lineFirst.ToPoint;194                 int fromFlag = 0;195                 int toFlag = 0;196                 for (int i = 0; i < allPolylineListCopy.Count; i++)197                 {198                     IFeature line2 = allPolylineListCopy[i];199                     IGeometry geoLine2 = line2.Shape;200                     IPolyline lineSecond = geoLine2 as IPolyline;201                     IPoint startPt2 = lineSecond.FromPoint;202                     IPoint endPt2 = lineSecond.ToPoint;203                     //FromPoint相同的点204                     if ((startPt1.X == startPt2.X && startPt1.Y == startPt2.Y) ||205                         (startPt1.X == endPt2.X && startPt1.Y == endPt2.Y))206                     {207                         fromFlag++;208                     }209                     //ToPoint相同的点210                     if ((endPt1.X == endPt2.X && endPt1.Y == endPt2.Y) ||211                     (endPt1.X == startPt2.X && endPt1.Y == startPt2.Y))212                     {213                         toFlag++;214                     }215                 }216                 if (fromFlag > 2 || toFlag > 2 || (fromFlag == 1 && toFlag == 1))217                 {218                     noNeedUnionLineList.Add(featureLine);219                     //noNeedUnionLineFileds.Add(featureLine.Fields);220                 }221             }222             return noNeedUnionLineList;223         }224 225         //将需要进行合并的线要素(没有节点)集合进行合并,结果为多条线       227         public List<IFeature> MergeLineListOperate(List<IFeature> toUnionLineList)228         {229             List<IFeature> mergeResultLineList = new List<IFeature>();230             int CountPercent = 0;231             while (toUnionLineList.Count > 0)232             {233                 CountPercent++;234                 //初始化当前合并的线要素235                 IFeature unionCurrentLine = toUnionLineList[0];236                 //将第一个要素的属性字段值作为最终合并线要素的值237                 firstRowFeatureList.Add(unionCurrentLine);238                 List<IFeature> currentMergeLineList = new List<IFeature>();239                 int count2 = 0;240                 do241                 {242                     count2++;243                     IFeature featureFirst = unionCurrentLine;244                     IGeometry geoLineFirst = featureFirst.Shape;245                     IPolyline lineFirst = geoLineFirst as IPolyline;246                     IPoint startPt1 = lineFirst.FromPoint;247                     IPoint endPt1 = lineFirst.ToPoint;248                     toUnionLineList.Remove(featureFirst);251                     currentMergeLineList.Clear();252                     currentMergeLineList.Add(featureFirst); 253 254                     List<IFeature> allPolylineListTemp1 = new List<IFeature>();255                     List<IFeature> allPolylineListTemp2 = new List<IFeature>();256                     int bStart1 = 0;257                     int bStart2 = 0;260                     for (int j = 0; j < toUnionLineList.Count; j++)261                     {264                         IFeature featureSecond = toUnionLineList[j];265                         IGeometry geoLineSecond = featureSecond.Shape;266                         IPolyline lineSecond = geoLineSecond as IPolyline;267                         IPoint startPt2 = lineSecond.FromPoint;268                         IPoint endPt2 = lineSecond.ToPoint;269 270                         if ((startPt1.X == startPt2.X && startPt1.Y == startPt2.Y) ||271                             (startPt1.X == endPt2.X && startPt1.Y == endPt2.Y))272                         {273                             bStart1++;274                             if (bStart1 > 0)275                             {276                                 allPolylineListTemp1.Add(featureSecond);277                                 currentMergeLineList.AddRange(allPolylineListTemp1);279                                 toUnionLineList.Remove(featureSecond);280                             }281                         }282                         if ((endPt1.X == endPt2.X && endPt1.Y == endPt2.Y) ||283                             (endPt1.X == startPt2.X && endPt1.Y == startPt2.Y))284                         {285                             bStart2++;286                             if (bStart2 > 0)287                             {288                                 allPolylineListTemp2.Add(featureSecond);289                                 currentMergeLineList.AddRange(allPolylineListTemp2);290                                 toUnionLineList.Remove(featureSecond);291                             }292 293                         }296                        297                     }298                     if (currentMergeLineList.Count > 1)299                     {301                         unionCurrentLine = UnionCurrentLineList(currentMergeLineList);302                     }303                     else304                     {306                         int ii = 0;307                     }308                 } while (currentMergeLineList.Count > 1);309 310                 mergeResultLineList.Add(unionCurrentLine);312             }313             return mergeResultLineList;314         }315 316         //为待写入图层添加Name和GB字段317         public void AddField()318         {319             IFeatureLayer featureLayer2 = map.get_Layer(0) as IFeatureLayer;320             IFeatureClass featureClass2 = featureLayer2.FeatureClass;322             IClass pClass = featureClass2 as IClass;324             IField fld1 = new Field();325             IField fld2 = new Field();326             IFieldEdit2 fld_NAME = fld1 as IFieldEdit2;327             IFieldEdit2 fld_GB = fld2 as IFieldEdit2;328             fld_NAME.Type_2 = esriFieldType.esriFieldTypeString;329             fld_NAME.Name_2 = "NAME";330             fld_GB.Type_2 = esriFieldType.esriFieldTypeString;331             fld_GB.Name_2 = "GB";332             pClass.AddField(fld_GB);333             pClass.AddField(fld_NAME);334             335         }336 337         public void WriteNoNeedUnionLineToFile(List<IFeature> pLineList)338         {           340             foreach (IFeature featureLine in pLineList)341             {342                 IFeatureLayer featureLayer2 = map.get_Layer(0) as IFeatureLayer;343                 IFeatureClass featureClass2 = featureLayer2.FeatureClass;          345                 IFeatureBuffer featureBuffer = featureClass2.CreateFeatureBuffer();346                 IFeatureCursor featureCursor;347                 featureCursor = featureClass2.Insert(true);               348                 IGeometry pGeometry = featureLine.Shape;349                 featureBuffer.Shape = pGeometry;350                 int NAME_Index = featureLine.Fields.FindField("NAME");351                 int GB_Index = featureLine.Fields.FindField("GB");352                 string name = featureLine.get_Value(NAME_Index).ToString();353                 string gb = featureLine.get_Value(GB_Index).ToString();355                 int fieldindex1 = featureBuffer.Fields.FindField("NAME");356                 int fieldindex2 = featureBuffer.Fields.FindField("GB");357                 if (fieldindex1 >= 0)358                 {359                     featureBuffer.set_Value(fieldindex1, name);360                 }361                 if (fieldindex2 >= 0)362                 {363                     featureBuffer.set_Value(fieldindex2, gb);364                 }368                 featureCursor.InsertFeature(featureBuffer);369                 featureCursor.Flush();370                 System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);               371             }           372         }373         public void WriteUnionLineToFile(List<IFeature> mergeResultLineList, List<IFeature> firstFeatureList)374         {375             int index = 0;376             foreach (IFeature featureLine in mergeResultLineList)377             {378                 IFeatureLayer featureLayer2 = map.get_Layer(0) as IFeatureLayer;379                 IFeatureClass featureClass2 = featureLayer2.FeatureClass;380                 IFeatureBuffer featureBuffer = featureClass2.CreateFeatureBuffer();381                 IFeatureCursor featureCursor;382                 featureCursor = featureClass2.Insert(true);383                 IGeometry pGeometry = featureLine.Shape;384                 featureBuffer.Shape = pGeometry;385                 int NAME_Index = firstFeatureList[index].Fields.FindField("NAME");386                 int GB_Index = firstFeatureList[index].Fields.FindField("GB");387                 string name = firstFeatureList[index].get_Value(NAME_Index).ToString();388                 string gb = firstFeatureList[index].get_Value(GB_Index).ToString();390                 int fieldindex1 = featureBuffer.Fields.FindField("NAME");391                 int fieldindex2 = featureBuffer.Fields.FindField("GB");392                 if (fieldindex1 >= 0)393                 {394                     featureBuffer.set_Value(fieldindex1, name);395                 }396                 if (fieldindex2 >= 0)397                 {398                     featureBuffer.set_Value(fieldindex2, gb);399                 }400    401                 featureCursor.InsertFeature(featureBuffer);402                 featureCursor.Flush();403                 System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);404                 index++;405             }406         }407 408         //将传入的List<IPolylne>中的多条线要素进行合并为一条线要素409         public IFeature UnionCurrentLineList(List<IFeature> currentMergeLineList)410         {411             IFeatureLayer featureLayer = map.get_Layer(1) as IFeatureLayer;412             IFeatureClass featureClass = featureLayer.FeatureClass;413            414             ITopologicalOperator2 pTopologicalOperator;415             IFeature pFeatureTemp = currentMergeLineList[0];416             IGeometry pGeometry = pFeatureTemp.Shape;419             int i = 1;420             while (i < currentMergeLineList.Count)421             {422                 pTopologicalOperator = pGeometry as ITopologicalOperator2;423                 //ITopologicalOperator的操作是bug很多的,先强制的检查下面三个步骤,再进行操作424                 //modifiy in 2016/03/20 12:47425                 pTopologicalOperator.IsKnownSimple_2 = false;426                 pTopologicalOperator.Simplify();427                 pGeometry.SnapToSpatialReference();428 429                 pGeometry = currentMergeLineList[i].Shape;430                 pGeometry = pTopologicalOperator.Union(pGeometry);431                 i++;432             }433             IFeature unionLine = featureClass.CreateFeature();434             unionLine.Shape = pGeometry;436             IDataset pDataset = featureClass as IDataset;438             pDataset.Workspace.ExecuteSQL("delete from " + featureClass.AliasName + " where SHAPE_Length = 0" );439             return unionLine;440         }441               442         protected override void OnUpdate()443         {444             Enabled = ArcMap.Application != null;445         }446     }

-------------------------------------------------------------------------------------------------------------------------

 本文系作者GISQZC原创文章,欢迎转载,但必须注明出处,否则将追究相关法律责任!

 

 

 

1楼ProgrammingNobody
兄台,文章里有错别字,看着很不舒服,Union写成Unon
Re: GISQZC
@ProgrammingNobody,已改正,谢谢!