同學做畢設,要求我幫着寫個ArcGIS插件,實現功能為:遍歷所有圖斑,提取相鄰圖斑的公共邊長及其他屬性(包括相鄰圖斑的ID),鏈接到屬性表中。搞定后在這里做個記錄。本文分兩大部分:
- ArcGIS插件開發流程
- 實際案例分享
一、ArcGIS插件開發流程
該部分不涉及具體業務,力求以最快速度了解ArcGIS Add-in插件從開發到使用的具體流程。
1.新建項目
2.編寫業務代碼
3.編譯
4.安裝插件
5.使用插件
二、實際案例分享
上面已經說了,案例來源於實際的需求,此處想必沒有比直接上代碼更實用更有feel了。實現功能為:遍歷所有圖斑,提取相鄰圖斑的公共邊長及其他屬性(包括相鄰圖斑的ID),並保存到文本文件中。注釋已經寫的很詳細了,所以具體過程也不多說,有啥問題直接留言,我會看到的~
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.IO; 5 using ESRI.ArcGIS.Framework; 6 using ESRI.ArcGIS.Carto; 7 using ESRI.ArcGIS.ArcMapUI; 8 using System.Windows.Forms; 9 using ESRI.ArcGIS.Geometry; 10 using ESRI.ArcGIS.Geodatabase; 11 using System.Runtime.InteropServices; 12 using ESRI.ArcGIS.ADF.CATIDs; 13 14 namespace SharedSide 15 { 16 public class SharedSide : ESRI.ArcGIS.Desktop.AddIns.Button 17 { 18 private IApplication m_application; 19 private static IMap map; 20 21 public SharedSide() 22 { 23 24 } 25 26 protected override void OnClick() 27 { 28 m_application = ArcMap.Application; 29 map = (m_application.Document as IMxDocument).FocusMap; 30 31 FormSelect formSelect = new FormSelect(); 32 IEnumLayer layers = map.get_Layers(null, false); 33 layers.Reset(); 34 ILayer layer = layers.Next(); 35 while (layer != null) 36 { 37 formSelect.cmbLayers.Items.Add(layer.Name); 38 layer = layers.Next(); 39 } 40 formSelect.ShowDialog(); 41 42 if (formSelect.IsOK) 43 { 44 ILayer selectedLayer = GetLayerByName(formSelect.cmbLayers.Text); 45 IFeatureLayer pFeatureLayer = selectedLayer as IFeatureLayer; 46 int featureCount = pFeatureLayer.FeatureClass.FeatureCount(null); 47 IFeatureCursor featureCursor = pFeatureLayer.Search(null, false); 48 IFeature pFeature = null; 49 50 // 最大相鄰圖斑數 51 int maxNumAdajacency = 0; 52 // 具有相鄰圖斑的要素 53 List<IFeature> featuresHasAdjacency = new List<IFeature>(); 54 // 對應featureHasAdjacency的相鄰圖斑 55 List<List<IFeature>> adjacentFeatures = new List<List<IFeature>>(); 56 // 對應adjacentFeatures的公共邊長度 57 List<List<double>> adjacentLengths = new List<List<double>>(); 58 59 // 提取邊相鄰的相鄰圖斑並計算公共邊長度 60 while ((pFeature = featureCursor.NextFeature()) != null) 61 { 62 // 與pFeature相鄰的圖斑 63 List<IFeature> adjacentFeature = AdjacentPolygons(pFeature, pFeatureLayer); 64 // pFeature與adjacentFeature的公共邊長度 65 List<double> adjacentLength = new List<double>(); 66 67 // 計算公共邊長度並去掉只有公共點相鄰的圖斑 68 if (adjacentFeature.Count > 0) 69 { 70 for (int i = 0; i < adjacentFeature.Count; i++) 71 { 72 double length = LengthOfSide((pFeature.Shape as IPolygon), (adjacentFeature[i].Shape as IPolygon)); 73 if (length == 0) 74 {// 如果只有公共點相鄰,則移除 75 adjacentFeature.Remove(adjacentFeature[i]); 76 } 77 } 78 79 for (int i = 0; i < adjacentFeature.Count; i++) 80 { 81 double length = LengthOfSide((pFeature.Shape as IPolygon), (adjacentFeature[i].Shape as IPolygon)); 82 adjacentLength.Add(length); 83 } 84 } 85 86 if (adjacentFeature.Count > 0) 87 {// 如果去掉只有公共點相鄰的情況pFeature仍有圖斑與之相鄰 88 featuresHasAdjacency.Add(pFeature); 89 adjacentFeatures.Add(adjacentFeature); 90 adjacentLengths.Add(adjacentLength); 91 } 92 93 // 3.查找最多相鄰圖斑數 94 if (adjacentFeature.Count > maxNumAdajacency) 95 { 96 maxNumAdajacency = adjacentFeature.Count; 97 } 98 } 99 System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor); 100 101 // 將相鄰圖斑的公共邊長度及DLBM屬性寫入文本文件保存 102 string text = "OBJECTID"; 103 for (int i = 0; i < maxNumAdajacency; i++) 104 { 105 string str = (",相鄰" + (i + 1) + "-OBJECTID") + (",相鄰" + (i + 1) + "-公共邊長") + (",相鄰" + (i + 1) + "-DLBM"); 106 text += str; 107 } 108 109 WriteData(formSelect.txtPath.Text, text); 110 111 int n = featuresHasAdjacency.Count; 112 for (int i = 0; i < n; i++) 113 { 114 int nIndex = featuresHasAdjacency[i].Table.FindField("OBJECTID"); 115 string str = featuresHasAdjacency[i].get_Value(nIndex).ToString(); 116 int m = adjacentFeatures[i].Count; 117 for (int j = 0; j < m; j++) 118 { 119 str += "," + adjacentFeatures[i][j].get_Value(adjacentFeatures[i][j].Table.FindField("OBJECTID")).ToString(); 120 str += "," + adjacentLengths[i][j].ToString(); 121 str += "," + adjacentFeatures[i][j].get_Value(adjacentFeatures[i][j].Table.FindField("DLBM")).ToString(); 122 } 123 WriteData(formSelect.txtPath.Text, str); 124 } 125 MessageBox.Show("計算完成!"); 126 } 127 } 128 129 protected override void OnUpdate() 130 { 131 Enabled = ArcMap.Application != null; 132 } 133 134 // 通過圖層名稱查找指定圖層 135 public static ILayer GetLayerByName(string lyrName) 136 { 137 ILayer findLayer = null; 138 IEnumLayer pEnumLayer = map.get_Layers(); 139 pEnumLayer.Reset(); 140 ILayer pLayer = pEnumLayer.Next(); 141 while (pLayer != null) 142 { 143 if (pLayer.Name == lyrName) 144 { 145 findLayer = pLayer; 146 } 147 pLayer = pEnumLayer.Next(); 148 } 149 return findLayer; 150 } 151 152 // 判斷線是否為面的邊界 153 public static bool isBoundary(IPolyline iPolyline, IPolygon iPolygon) 154 { 155 bool isBoundary; 156 ITopologicalOperator topoOper = iPolygon as ITopologicalOperator; 157 IPolyline boundLine = topoOper.Boundary as IPolyline; 158 IRelationalOperator reltOper = iPolyline as IRelationalOperator; 159 isBoundary = reltOper.Overlaps(boundLine); 160 return isBoundary; 161 } 162 163 // 查找當前圖層中與某圖斑相鄰的其他圖斑(包括有公共邊的和公共點的) 164 public static List<IFeature> AdjacentPolygons(IFeature iFeature, IFeatureLayer featureLayer) 165 { 166 List<IFeature> listFeature = new List<IFeature>(); 167 IRelationalOperator reltOperator = iFeature.Shape as IRelationalOperator; 168 int featureCount = featureLayer.FeatureClass.FeatureCount(null); 169 IFeatureCursor featureCursor = featureLayer.Search(null, false); 170 IFeature feature = null; 171 while ((feature = featureCursor.NextFeature()) != null) 172 { 173 if (feature.OID == iFeature.OID) 174 { 175 continue; 176 } 177 bool isAdjacent = reltOperator.Touches(feature.Shape); 178 if (isAdjacent) 179 { 180 listFeature.Add(feature); 181 } 182 } 183 return listFeature; 184 } 185 186 // 計算兩個圖斑公共邊的長度 187 public static double LengthOfSide(IPolygon iPolygon1, IPolygon iPolygon2) 188 { 189 IPolyline polyline; 190 ITopologicalOperator topoOper = iPolygon1 as ITopologicalOperator; 191 polyline = topoOper.Intersect(iPolygon2, esriGeometryDimension.esriGeometry1Dimension) as IPolyline; 192 return polyline.Length; 193 } 194 195 // 寫入數據到文件 196 private static void WriteData(string filePath, string text) 197 { 198 FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write); 199 StreamWriter sw = new StreamWriter(fs); 200 sw.WriteLine(text); 201 sw.Close(); 202 fs.Close(); 203 } 204 } 205 }