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