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原創文章,歡迎轉載,但必須注明出處,否則將追究相關法律責任!

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM