同学做毕设,要求我帮着写个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 }