当前位置: 代码迷 >> GIS >> ArcEngine环境下合龙断开的线要素(根据属性)
  详细解决方案

ArcEngine环境下合龙断开的线要素(根据属性)

热度:817   发布时间:2016-05-05 06:02:50.0
ArcEngine环境下合并断开的线要素(根据属性)

     1.遇到的问题:

 最近遇到在线要素(矢量数据)中,一条完整的道路、河流等往往是断开的,如下图1所示:

 

     2.思路:

      在ArcGIS Desktop中没有相关的工具可以将这些断开的线要素进行自动合并,今天自己写了一个Arcmap上的一个插件,实现当点击插件按钮后,对地图窗口中断开的线要素进行合并。合并的依据是具有相同NAME属性(如长沙-张家界高速)的Polyline要素进行合并,然后存储在另一个线要素图层中。

     3.程序的实现和结果:

      程序运行的结果如下,这样本来属于同一段道路的多个Polyline就合并成一条Polyline:

      

      

     4.程序源代码:

  1 using System;  2 using System.Collections;  3 using System.Collections.Generic;  4 using System.Text;  5 using System.IO;  6 using System.Windows.Forms;  7 using ESRI.ArcGIS.ArcMapUI;  8 using ESRI.ArcGIS.Carto;  9 using ESRI.ArcGIS.Geodatabase; 10 using ESRI.ArcGIS.Geometry; 11  12 namespace MergeDisconnectPolylineAddin 13 { 14     public class MergePolyline : ESRI.ArcGIS.Desktop.AddIns.Button 15     { 16          17         IMap map = null; 18         IActiveView pActiveView = null; 19         //private List<IPolyline> DisconnPolylineList = new List<IPolyline>(); 20  21         public MergePolyline() 22         { 23             IMxDocument mxDoc = ArcMap.Application.Document as IMxDocument; 24             map = mxDoc.FocusMap; 25             pActiveView = mxDoc.ActivatedView; 26         } 27  28         protected override void OnClick() 29         { 30             // 31             //  TODO: Sample code showing how to access button host 32             // 33             ArcMap.Application.CurrentTool = null; 34  35             //计算程序耗时 36             DateTime beforDT = System.DateTime.Now; 37              38             List<string> distinctString = getDistinctNAMEValue(); 39             MergePloyline(distinctString); 40  41             DateTime afterDT = System.DateTime.Now; 42             TimeSpan ts = afterDT.Subtract(beforDT); 43             MessageBox.Show("线要素合并结束,运行程序共耗时约:"+ ts.Minutes+"分钟"); 44         } 45          46         public List<string> getDistinctNAMEValue() 47         { 48             IFeatureLayer featureLayer = map.get_Layer(0) as IFeatureLayer; 49             IFeatureClass featureClass = featureLayer.FeatureClass; 50             IQueryFilter queryFilter = new QueryFilterClass(); 51             queryFilter.WhereClause = ""; 52             IFeatureCursor pFeatCursor = featureClass.Search(queryFilter, false); 53             IFeature pFeature = pFeatCursor.NextFeature(); 54             ArrayList fieldArray = new ArrayList(); 55             List<string> distinctString = new List<string>(); 56             while (pFeature != null) 57             { 58                 if (featureClass.ShapeType == esriGeometryType.esriGeometryPolyline) 59                 { 60                     IFields fields = pFeatCursor.Fields; 61                     int fieldIndex = fields.FindField("NAME"); 62                     string field_NAME = (string)pFeature.get_Value(fieldIndex); 63                     fieldArray.Add(field_NAME); 64                 } 65                 pFeature = pFeatCursor.NextFeature(); 66             } 67             distinctString = removeSameString(fieldArray); 68             return distinctString; 69         } 70  71         public void MergePloyline(List<string> DistinctNameValue) 72         { 73             IFeatureLayer featureLayer = map.get_Layer(0) as IFeatureLayer; 74             IFeatureClass featureClass = featureLayer.FeatureClass; 75  76             //IDataset dataset = featureClass as IDataset; 77             //IWorkspaceEdit workspaceEdit = dataset.Workspace as IWorkspaceEdit; 78             //Type.Missing指的是空类型,因为有些方法你传null给它会出错的,必须要用Type.Missing. 79             object Missing = Type.Missing; 80             //workspaceEdit.StartEditing(true); 81             //workspaceEdit.StartEditOperation(); 82             //string field_NAME = ""; 83  84             for (int i = 0; i < DistinctNameValue.Count; i++) 85             { 86                 IQueryFilter queryFilter = new QueryFilterClass(); 87                 queryFilter.WhereClause = ""; 88                 IFeatureCursor pFeatCursor = featureClass.Search(queryFilter, false); 89                 IFeature pFeature = pFeatCursor.NextFeature(); 90  91                 IFeature pFeatureFirst = pFeature; 92                 //List<IPolyline> toMergePolylineList = new List<IPolyline>(); 93  94                 IGeometryCollection Geometrybag = new GeometryBagClass(); 95                 ITopologicalOperator2 pTopOperatorFirst = null; 96                 IGeometry geometrySecond = null; 97                 IGeometry pGeometryFirst = null; 98                 bool bSwitch = true; 99                 while (pFeature != null)100                 {101                     map.SelectFeature(featureLayer, pFeature);102                     if (featureClass.ShapeType == esriGeometryType.esriGeometryPolyline)103                     {                       104                         //IPolyline polyline = geometry as IPolyline;105                         IFields fields = pFeatCursor.Fields;106                         int fieldIndex = fields.FindField("NAME");107                         string field_NAME = (string)pFeature.get_Value(fieldIndex);108                         109                         if (field_NAME == DistinctNameValue[i])110                         {111                             if (bSwitch)112                             {113                                 //将当前name字段相同的feature中的第一个feature传给pFeatureFirst114                                 pFeatureFirst = pFeature;115                                 pGeometryFirst = pFeature.Shape;116                                 pTopOperatorFirst = (ITopologicalOperator2) pGeometryFirst;117                                 pTopOperatorFirst.IsKnownSimple_2 = false;118                                 pTopOperatorFirst.Simplify();119                                 pGeometryFirst.SnapToSpatialReference();120                                 bSwitch = false;121                                 //break;122                             }123                             else124                             {125                                 //geometrySecond = pFeature.ShapeCopy;126                                 geometrySecond = pFeature.Shape;127                                 Geometrybag.AddGeometry(geometrySecond, ref Missing, ref Missing);128                                 //toMergePolylineList.Add(polyline);129                             }                           130                         }131                         //DisconnPolylineList.Add(polyline);132                     }133                     pFeature = pFeatCursor.NextFeature();134                 }135                 IEnumGeometry tEnumGeometry = (IEnumGeometry)Geometrybag;136                 //IGeometry mergeGeomery = null;137                 pTopOperatorFirst.ConstructUnion(tEnumGeometry);138 139                 pTopOperatorFirst.IsKnownSimple_2 = false;140                 pTopOperatorFirst.Simplify();141                 pFeatureFirst.Shape = pGeometryFirst;142                 //pFeatureFirst.Store();143                 IFeatureLayer featureLayer2 = map.get_Layer(1) as IFeatureLayer;144                 IFeatureClass featureClass2 = featureLayer2.FeatureClass;145                 AddPolyline(featureClass2, pGeometryFirst);146             }147             //workspaceEdit.StopEditOperation();148             //workspaceEdit.StopEditing(true);           149         }150         private void AddPolyline(IFeatureClass pFeatureClass, IGeometry polyline)151         {152             IFeatureBuffer featureBuffer = pFeatureClass.CreateFeatureBuffer();153             IFeatureCursor featureCursor;154             featureCursor = pFeatureClass.Insert(true);155             featureBuffer.Shape = polyline;156             featureCursor.InsertFeature(featureBuffer);157             featureCursor.Flush();158             System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);159         }160         public List<string> removeSameString(ArrayList stringArray)161         {162             //List用于存储从数组里取出来的不相同的元素163             List<string> distinctString = new List<string>();164             foreach (string eachString in stringArray)165             {166                 if (!distinctString.Contains(eachString))167                     distinctString.Add(eachString);168             }169             return distinctString;170         }171 172         protected override void OnUpdate()173         {174             Enabled = ArcMap.Application != null;175         }176     }177 178 }

    5.总结

      这个插件还有一些不足的地方,如不是从线要素首尾点相邻的角度寻找相邻点(这种方法存在判断三条线要素交叉而形成的节点的判断和是否进行合并的问题和难点),在下一篇随笔里面会介绍从纯几何学的角度实现线要素的连接的实现。

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

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

 

4楼我也是个傻瓜
01.用GIS编程的思维来解决实际生产中遇到的问题,非常不错!向您学习;,02.其实您有这句话还有些不采“在ArcGIS Desktop中没有相关的工具可以将这些断开的线要素进行自动合并”;实际上,arcmap在很早之前就有这个功能了,即融合工具(Dissolve)
Re: GISQZC
@我也是个傻瓜,您好,感谢您帮我指出文中的错误。ArcGIS工具箱中的Dissolve工具的确可以将具有相同属性的的不同要素(相连或不相连)进行合并。但是这个工具不能满足我导师提的需求(我们拿到的数据主要是要进行道路线要素化简,在道路都是分段断开的条件下,化简的效果不好,所以需要先进行合并,再进行抽烯)。Dissolve工具是完全根据属性判断的,在节点(有3条或3条以上的线相交的点)处可能仍然是相连的。后面为了解决这个问题,就重新换了一个思路写,不通过属性,直接通过几何条件判断进行合并操作,在我后面的两篇随笔中http://www.cnblogs.com/GISQZC/p/5299820.html 。我还是在校生,有什么写的不对的地方还请您批评指正,谢谢!
3楼ProgrammingNobody
总结括号里的话表达不清
Re: GISQZC
@ProgrammingNobody,你好,这句话的意思是,我这样通过属性判断,Name属性相同的线要素都进行了合并。但是后来我导师要求如果有3条或者3条以上的polyline向接于同一点(称之为“节点”),就不能进行合并,只合并两条开始点或者结束点相同的两条线。这样通过同值属性的方式就不符合需求了。所以我重新写了一个通过几何上的相接关系合并的新的算法,在我今天发的日志里,你可以看一下。
2楼ProgrammingNobody
谢谢兄台!
1楼GISQZC
不客气,一起进步!