• 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                 do
    241                 {
    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                     else
    304                     {
    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:47
    425                 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原创文章,欢迎转载,但必须注明出处,否则将追究相关法律责任!

     

  • 相关阅读:
    CSS3 3D Transform
    js关闭当前页面(窗口)的几种方式总结
    JavaScript书籍阅读
    使用@media screen解决移动web开发的多分辨率问题
    ie678 兼容问题
    JS动态引入js,CSS——动态创建script/link/style标签
    扁平化设计的流行配色方案
    最简单的jquery轮播图
    ie7 z-index 失效问题
    js正则表达式手机号(邮箱)验证
  • 原文地址:https://www.cnblogs.com/GISQZC/p/5299820.html
Copyright © 2020-2023  润新知