1需求
在空间规划作业中,编辑要素时,我们需要同时知道编辑要素的面积或长度,以保证工程在预算范围之内,所以,我们需要有一个工具对编辑过程进行实时的检测。
2设计思路
(1)首先需要编辑Map中的所有图层,把符合统计条件的图层找出来,在这里符合条件的是shp数据,如果是shp数据则进行统计;
(2)对符合条件的图层的各个要素(Feature)进行遍历,以求得每个要素(Feature)的长度\面积,求和即得到总长度/面积,对于点要素那当然更简单,直接返回其Count属性即可。
(3)统计的结果在GridView中显示,GridView绑定一个数据表(DataTable),数据表的每一行表示一个图层的面积\长度\个数统计;
(4)换算单位。
3界面设计
(1)主界面,设计的比较简单,仅作为示范:
(2)统计功能的界面设计:
4代码实现
主窗体的代码很简单,加载数据,弹出窗体网上的示例很多,这里主要说说统计功能界面的代码。
按照第二部分的思路,写出各个步骤的代码。
(1)遍历Map中的所有shp图层:
//返回Map中所有的ShapeFile图层
private List<IFeatureLayer> getAllShp(IMap map)
{
IFeatureLayer pFeatureLayer;
List<IFeatureLayer> shpLayreList = new List<IFeatureLayer>();
for(int i = 0; i < map.LayerCount; i++)
{
if (map.Layer[i] is GroupLayer)
{
ICompositeLayer pComLayer = map.Layer[i] as ICompositeLayer;
for (int j = 0; j < pComLayer.Count; j++)
{
pFeatureLayer = pComLayer.Layer[j] as IFeatureLayer;
if (pFeatureLayer.DataSourceType.Contains("Shapefile"))
shpLayreList.Add(pFeatureLayer);
}
}
else if (map.Layer[i] is IFeatureLayer)
{
pFeatureLayer = map.Layer[i] as IFeatureLayer;
if (pFeatureLayer.DataSourceType.Contains("Shapefile"))
shpLayreList.Add(pFeatureLayer);
}
else
continue;
}
return shpLayreList;
}
(2)遍历各个要素,求出各图层的总面积/长度/个数:
//返回要素点的个数
private string getPointCount(IFeatureClass pFeatureClass)
{
return pFeatureClass.FeatureCount(null).ToString();
}
//返回线要素的总长度
private string getLineLength(IFeatureClass pFeatureClass)
{
double Length = 0;
IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false);
IFeature pFeature;
IPolyline pPolyline;
while ((pFeature = pFeatureCursor.NextFeature()) != null)
{
pPolyline = pFeature.Shape as IPolyline;
Length += pPolyline.Length;
}
switch (LengthUnit)
{
case "米":
break;
case "千米":
Length = Length / 1000;
break;
default:
break;
}
return Math.Round(Length, 3).ToString();
}
//返回面要素的总面积
private string getPolygonArea(IFeatureClass pFeatureClass)
{
double Area = 0;
IArea pArea;
IFeature pFeature;
IFeatureCursor pFeatureCursor = pFeatureClass.Search(null, false);
while ((pFeature = pFeatureCursor.NextFeature()) != null)
{
pArea = pFeature.Shape as IArea;
Area += pArea.Area;
}
switch (AreaUnit)
{
case "平方米":
break;
case "平方千米":
Area = Area / 1000000;
break;
case "亩":
Area = Area / 666.6666667;
break;
case "公顷":
Area = Area / 66666.6666667;
break;
default:
break;
}
return Math.Round(Area, 3).ToString();
}
(3)统计结果显示:
//生成每一行数据
private List<string> getRowInfo(IFeatureLayer pFeatureLayer)
{
List<string> s = new List<string>();
IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
switch (pFeatureClass.ShapeType)
{
case esriGeometryType.esriGeometryPoint:
s.Add(pFeatureClass.AliasName);
s.Add("点");
s.Add(getPointCount(pFeatureClass));
s.Add("个");
break;
case esriGeometryType.esriGeometryPolyline:
s.Add(pFeatureClass.AliasName);
s.Add("线");
s.Add(getLineLength(pFeatureClass));
s.Add(LengthUnit);
break;
case esriGeometryType.esriGeometryPolygon:
s.Add(pFeatureClass.AliasName);
s.Add("面");
s.Add(getPolygonArea(pFeatureClass));
s.Add(AreaUnit);
break;
}
return s;
}
//遍历各图层,将数据加载到表中
private void AppendToTable()
{
List<IFeatureLayer> FeatureLayerList = new List<IFeatureLayer>();
List<string> RowInfo = new List<string>();
FeatureLayerList = getAllShp(pMap);
foreach(IFeatureLayer pFeatureLayer in FeatureLayerList)
{
RowInfo = getRowInfo(pFeatureLayer);
DT.Rows.Add(RowInfo[0], RowInfo[1], RowInfo[2], RowInfo[3]);
}
}
其中,AreaUnit、LengthUnit、pMap为三个全局变量,在初始化这个窗体时将主窗体的Map传递到该窗体。
当然,为了简便,这里默认初始的单位为"米"、“平方米”,在实际应用中应该考虑地图的单位。
5代码下载
以上为核心的代码,全部代码和示例数据可以从Github上下载:
https://github.com/ranhongwu/20190803GetAreaAndLength 。