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 合并后的属性表
三,程序详细代码
public class MergeDisconnectLine : ESRI.ArcGIS.Desktop.AddIns.Button
{ public int CountPercent { get; set; }
IMap map = null;
private List<IFeature> DisconnPolylineList = new List<IFeature>();
private List<IFeature> firstRowFeatureList = new List<IFeature>(); public MergeDisconnectLine()
{
IMxDocument mxDoc = ArcMap.Application.Document as IMxDocument;
map = mxDoc.FocusMap;
}
protected override void OnClick()
{
//
// TODO: Sample code showing how to access button host
//
ArcMap.Application.CurrentTool = null; //计算程序耗时
DateTime beforDT = System.DateTime.Now;
//Application.EnableVisualStyles();
//Application.SetCompatibleTextRenderingDefault(false);
////ProgressBar pBar = new ProgressBar();
//Application.Run(new ProgressBar());
List<IFeature> allPolylineList = getAllPolyline();
List<IFeature> noNeedUnionLineList = getWithoutNeedUnionLineList(allPolylineList);
List<IFeature> toUnionLineList = GetToUnionLineList(allPolylineList, noNeedUnionLineList);
List<IFeature> unionLineList = MergeLineListOperate(toUnionLineList);
AddField();
WriteNoNeedUnionLineToFile(noNeedUnionLineList);
WriteUnionLineToFile(unionLineList, firstRowFeatureList);
DateTime afterDT = System.DateTime.Now;
TimeSpan ts = afterDT.Subtract(beforDT);
int minutes = ts.Minutes;
int seconds = ts.Seconds%;
//pBar.Hide();
MessageBox.Show("线要素合并结束,运行程序共耗时约:" + minutes + "分"+ seconds + "秒");
}
//获取shp文件中所有的Polyline(IFeature)对象
public List<IFeature> getAllPolyline()
{
IFeatureLayer featureLayer = map.get_Layer() as IFeatureLayer;
IFeatureClass featureClass = featureLayer.FeatureClass;
IQueryFilter queryFilter = new QueryFilter();
queryFilter.WhereClause = "";
IFeatureCursor pFeatCursor = featureClass.Search(queryFilter, false);
IFeature pFeature = pFeatCursor.NextFeature(); while (pFeature != null)
{
if (featureClass.ShapeType == esriGeometryType.esriGeometryPolyline)
{
DisconnPolylineList.Add(pFeature);
}
pFeature = pFeatCursor.NextFeature();
}
return DisconnPolylineList;
} //获取需要进行合并的线(是noNeedUnionLineList的补集)
public List<IFeature> GetToUnionLineList(List<IFeature> allPolylineList, List<IFeature> noNeedUnionLineList)
{
List<IFeature> toUnionLineList = allPolylineList;
foreach (IFeature featureLine in noNeedUnionLineList)
{
toUnionLineList.Remove(featureLine);
}
return toUnionLineList;
} //获取不需要进行合并的线(独立线,一端是节点的线,和两端都是节点的线)
public List<IFeature> getWithoutNeedUnionLineList(List<IFeature> allPolylineList)
{
List<IFeature> noNeedUnionLineList = new List<IFeature>();
foreach (IFeature featureLine in allPolylineList)
{
int count = featureLine.Fields.FieldCount;
List<IFeature> allPolylineListCopy = allPolylineList;
IGeometry geoLine = featureLine.Shape;
IPolyline lineFirst = geoLine as IPolyline;
IPoint startPt1 = lineFirst.FromPoint;
IPoint endPt1 = lineFirst.ToPoint;
int fromFlag = ;
int toFlag = ;
for (int i = ; i < allPolylineListCopy.Count; i++)
{
IFeature line2 = allPolylineListCopy[i];
IGeometry geoLine2 = line2.Shape;
IPolyline lineSecond = geoLine2 as IPolyline;
IPoint startPt2 = lineSecond.FromPoint;
IPoint endPt2 = lineSecond.ToPoint;
//FromPoint相同的点
if ((startPt1.X == startPt2.X && startPt1.Y == startPt2.Y) ||
(startPt1.X == endPt2.X && startPt1.Y == endPt2.Y))
{
fromFlag++;
}
//ToPoint相同的点
if ((endPt1.X == endPt2.X && endPt1.Y == endPt2.Y) ||
(endPt1.X == startPt2.X && endPt1.Y == startPt2.Y))
{
toFlag++;
}
}
if (fromFlag > || toFlag > || (fromFlag == && toFlag == ))
{
noNeedUnionLineList.Add(featureLine);
//noNeedUnionLineFileds.Add(featureLine.Fields);
}
}
return noNeedUnionLineList;
} //将需要进行合并的线要素(没有节点)集合进行合并,结果为多条线
public List<IFeature> MergeLineListOperate(List<IFeature> toUnionLineList)
{
List<IFeature> mergeResultLineList = new List<IFeature>();
int CountPercent = ;
while (toUnionLineList.Count > )
{
CountPercent++;
//初始化当前合并的线要素
IFeature unionCurrentLine = toUnionLineList[];
//将第一个要素的属性字段值作为最终合并线要素的值
firstRowFeatureList.Add(unionCurrentLine);
List<IFeature> currentMergeLineList = new List<IFeature>();
int count2 = ;
do
{
count2++;
IFeature featureFirst = unionCurrentLine;
IGeometry geoLineFirst = featureFirst.Shape;
IPolyline lineFirst = geoLineFirst as IPolyline;
IPoint startPt1 = lineFirst.FromPoint;
IPoint endPt1 = lineFirst.ToPoint;
toUnionLineList.Remove(featureFirst);
currentMergeLineList.Clear();
currentMergeLineList.Add(featureFirst); List<IFeature> allPolylineListTemp1 = new List<IFeature>();
List<IFeature> allPolylineListTemp2 = new List<IFeature>();
int bStart1 = ;
int bStart2 = ;
for (int j = ; j < toUnionLineList.Count; j++)
{
IFeature featureSecond = toUnionLineList[j];
IGeometry geoLineSecond = featureSecond.Shape;
IPolyline lineSecond = geoLineSecond as IPolyline;
IPoint startPt2 = lineSecond.FromPoint;
IPoint endPt2 = lineSecond.ToPoint; if ((startPt1.X == startPt2.X && startPt1.Y == startPt2.Y) ||
(startPt1.X == endPt2.X && startPt1.Y == endPt2.Y))
{
bStart1++;
if (bStart1 > )
{
allPolylineListTemp1.Add(featureSecond);
currentMergeLineList.AddRange(allPolylineListTemp1);
toUnionLineList.Remove(featureSecond);
}
}
if ((endPt1.X == endPt2.X && endPt1.Y == endPt2.Y) ||
(endPt1.X == startPt2.X && endPt1.Y == startPt2.Y))
{
bStart2++;
if (bStart2 > )
{
allPolylineListTemp2.Add(featureSecond);
currentMergeLineList.AddRange(allPolylineListTemp2);
toUnionLineList.Remove(featureSecond);
} } }
if (currentMergeLineList.Count > )
{
unionCurrentLine = UnionCurrentLineList(currentMergeLineList);
}
else
{
int ii = ;
}
} while (currentMergeLineList.Count > ); mergeResultLineList.Add(unionCurrentLine);
}
return mergeResultLineList;
} //为待写入图层添加Name和GB字段
public void AddField()
{
IFeatureLayer featureLayer2 = map.get_Layer() as IFeatureLayer;
IFeatureClass featureClass2 = featureLayer2.FeatureClass;
IClass pClass = featureClass2 as IClass;
IField fld1 = new Field();
IField fld2 = new Field();
IFieldEdit2 fld_NAME = fld1 as IFieldEdit2;
IFieldEdit2 fld_GB = fld2 as IFieldEdit2;
fld_NAME.Type_2 = esriFieldType.esriFieldTypeString;
fld_NAME.Name_2 = "NAME";
fld_GB.Type_2 = esriFieldType.esriFieldTypeString;
fld_GB.Name_2 = "GB";
pClass.AddField(fld_GB);
pClass.AddField(fld_NAME); } public void WriteNoNeedUnionLineToFile(List<IFeature> pLineList)
{
foreach (IFeature featureLine in pLineList)
{
IFeatureLayer featureLayer2 = map.get_Layer() as IFeatureLayer;
IFeatureClass featureClass2 = featureLayer2.FeatureClass;
IFeatureBuffer featureBuffer = featureClass2.CreateFeatureBuffer();
IFeatureCursor featureCursor;
featureCursor = featureClass2.Insert(true);
IGeometry pGeometry = featureLine.Shape;
featureBuffer.Shape = pGeometry;
int NAME_Index = featureLine.Fields.FindField("NAME");
int GB_Index = featureLine.Fields.FindField("GB");
string name = featureLine.get_Value(NAME_Index).ToString();
string gb = featureLine.get_Value(GB_Index).ToString();
int fieldindex1 = featureBuffer.Fields.FindField("NAME");
int fieldindex2 = featureBuffer.Fields.FindField("GB");
if (fieldindex1 >= )
{
featureBuffer.set_Value(fieldindex1, name);
}
if (fieldindex2 >= )
{
featureBuffer.set_Value(fieldindex2, gb);
}
featureCursor.InsertFeature(featureBuffer);
featureCursor.Flush();
System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
}
}
public void WriteUnionLineToFile(List<IFeature> mergeResultLineList, List<IFeature> firstFeatureList)
{
int index = ;
foreach (IFeature featureLine in mergeResultLineList)
{
IFeatureLayer featureLayer2 = map.get_Layer() as IFeatureLayer;
IFeatureClass featureClass2 = featureLayer2.FeatureClass;
IFeatureBuffer featureBuffer = featureClass2.CreateFeatureBuffer();
IFeatureCursor featureCursor;
featureCursor = featureClass2.Insert(true);
IGeometry pGeometry = featureLine.Shape;
featureBuffer.Shape = pGeometry;
int NAME_Index = firstFeatureList[index].Fields.FindField("NAME");
int GB_Index = firstFeatureList[index].Fields.FindField("GB");
string name = firstFeatureList[index].get_Value(NAME_Index).ToString();
string gb = firstFeatureList[index].get_Value(GB_Index).ToString();
int fieldindex1 = featureBuffer.Fields.FindField("NAME");
int fieldindex2 = featureBuffer.Fields.FindField("GB");
if (fieldindex1 >= )
{
featureBuffer.set_Value(fieldindex1, name);
}
if (fieldindex2 >= )
{
featureBuffer.set_Value(fieldindex2, gb);
} featureCursor.InsertFeature(featureBuffer);
featureCursor.Flush();
System.Runtime.InteropServices.Marshal.ReleaseComObject(featureCursor);
index++;
}
} //将传入的List<IPolylne>中的多条线要素进行合并为一条线要素
public IFeature UnionCurrentLineList(List<IFeature> currentMergeLineList)
{
IFeatureLayer featureLayer = map.get_Layer() as IFeatureLayer;
IFeatureClass featureClass = featureLayer.FeatureClass; ITopologicalOperator2 pTopologicalOperator;
IFeature pFeatureTemp = currentMergeLineList[];
IGeometry pGeometry = pFeatureTemp.Shape;
int i = ;
while (i < currentMergeLineList.Count)
{
pTopologicalOperator = pGeometry as ITopologicalOperator2;
//ITopologicalOperator的操作是bug很多的,先强制的检查下面三个步骤,再进行操作
//modifiy in 2016/03/20 12:47
pTopologicalOperator.IsKnownSimple_2 = false;
pTopologicalOperator.Simplify();
pGeometry.SnapToSpatialReference(); pGeometry = currentMergeLineList[i].Shape;
pGeometry = pTopologicalOperator.Union(pGeometry);
i++;
}
IFeature unionLine = featureClass.CreateFeature();
unionLine.Shape = pGeometry;
IDataset pDataset = featureClass as IDataset;
pDataset.Workspace.ExecuteSQL("delete from " + featureClass.AliasName + " where SHAPE_Length = 0" );
return unionLine;
} protected override void OnUpdate()
{
Enabled = ArcMap.Application != null;
}
}
-------------------------------------------------------------------------------------------------------------------------
本文系作者GISQZC原创文章,欢迎转载,但必须注明出处,否则将追究相关法律责任!
ArcEngine中合并断开的线要素(根据几何判断)的更多相关文章
- ArcEngine环境下合并断开的线要素(根据属性)
1.遇到的问题: 最近遇到在线要素(矢量数据)中,一条完整的道路.河流等往往是断开的,如下图1所示: 2.思路: 在ArcGIS Desktop中没有相关的工具可以将这些断开的线要素进行自动合并,今天 ...
- ArcEngine 创建线要素图层
在创建要素图层的时候,默认的几何类型是Polygon: Dim objectClassDescription As IObjectClassDescription = New FeatureClass ...
- ArcEngine中最短路径的实现
原文 ArcEngine中最短路径的实现 最短路径分析属于ArcGIS的网络分析范畴.而ArcGIS的网络分析分为两类,分别是基于几何网络和网络数据集的网络分析.它们都可以实现最短路径功能.下面先介绍 ...
- ArcEngine中打开各种数据源(WorkSpace)的连接
(SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源.在开发过程中我们使用了如下几种数据源 1.企业数据库(SDE) 企业 ...
- ArcEngine中打开各种数据源(WorkSpace)的连接(转)
ArcEngine中打开各种数据源(WorkSpace)的连接 (SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源.在开 ...
- ArcEngine中打开各种数据源(WorkSpace)的连接http://www.cnblogs.com/feilong3540717/archive/2011/08/07/2129906.html
ArcEngine中打开各种数据源(WorkSpace)的连接 ArcEngine中打开各种数据源(WorkSpace)的连接 (SDE.personal/File.ShapeFile.CAD数据.影 ...
- [转] ArcEngine中打开各种数据源(WorkSpace)的连接
原文 ArcEngine中打开各种数据源(WorkSpace)的连接(SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源. ...
- ArcEngine查询、添加、删除要素的方法
原文 ArcEngine查询.添加.删除要素的方法 1.查找数据 1).利用FeaturCursor进行空间查询 //空间查询 ISpatialFilter spatialFilter = new S ...
- ArcMAp对线要素进行平滑处(打断)
一:工具简单介绍 -- ArcMAp10.1的高级编辑工具中提供了对线/面要素进行概括/平滑处理的工具. 概括工具.平滑工具分别例如以下:(首先得开启编辑状态 --- 才干够对要素的属性进行更改).选 ...
随机推荐
- [Node.js] 使用node-forge保障Javascript应用的传输安全
原文地址:http://www.moye.me/2015/12/19/protect_jsapp_tsl_by_using_node-forge/ 引子 半年前的最后一次更新(惭愧 ),提到了对称与 ...
- ArcGIS Earth数据小析
ArcGIS Earth,一款轻量级的三维地球应用.因为工作关系下载试用了半天,正好借这个机会简单研究一下ArcGIS Earth的大概思路,特别是地形数据的组成和影像数据的加载,在这总结整理一下.下 ...
- golang中的race检测
golang中的race检测 由于golang中的go是非常方便的,加上函数又非常容易隐藏go. 所以很多时候,当我们写出一个程序的时候,我们并不知道这个程序在并发情况下会不会出现什么问题. 所以在本 ...
- elasticsearch 文档
elasticsearch 文档 文档格式 索引中最基本的单元叫做文档 document. 在es中文档的示例如下: { "_index": "questions&quo ...
- HT for Web 中Painter的介绍及用法
鉴于许多同学对Painter不熟悉,所以撰写此文介绍下.Painter的中文意思是画家.漆工,那放到HT里是什么意思呢?很简单,这是HT特有的一种接口,允许开发者在拓扑及其它通用组件上使用Canvas ...
- JavaScript星形评分
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...
- jQuery的Ajax请求数据时type无法使用GET
写一个ASP.NET MVC例子,它是使用jQuery的$.Ajax来呼叫控制器的数据. 创建一个视图: 运行结果: 一切正常,但是本例子我们只是获取数据,并没有做任何数据POST上传至控制器,我们尝 ...
- iOS 阶段学习第11天笔记(OC基础知识)
iOS学习(OC语言)知识点整理 一.OC基础知识 1)#import 用于导入头文件,预处理阶段加载引用,只加载一次. 2)OC 依赖于Foundation框架下的头文件Foundation.h, ...
- 暴风冯鑫:去美国香港的99%都亏,互联网公司打死都要回A股
“上市之后,我回答得最多的两句话:一句是运气好:另一句是有好运气要好好地使用它.” 5月18日,暴风科技上市55天后,首享科技大厦办公室里,暴风科技CEO冯鑫这样对我说. 在经历了36个涨停之 ...
- [范例] Firemonkey TForm 实现 OnMouseLeave 事件 (適用 Win & OS X)
在 Firemonkey 的 TForm 并没有提供 OnMouseLeave 的事件,不过可以透过 OnMouseMove 来达到相同效果,请见代码: uses FMX.Consts; proced ...