在上一篇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中合并断开的线要素(根据几何判断)的更多相关文章

  1. ArcEngine环境下合并断开的线要素(根据属性)

    1.遇到的问题: 最近遇到在线要素(矢量数据)中,一条完整的道路.河流等往往是断开的,如下图1所示: 2.思路: 在ArcGIS Desktop中没有相关的工具可以将这些断开的线要素进行自动合并,今天 ...

  2. ArcEngine 创建线要素图层

    在创建要素图层的时候,默认的几何类型是Polygon: Dim objectClassDescription As IObjectClassDescription = New FeatureClass ...

  3. ArcEngine中最短路径的实现

    原文 ArcEngine中最短路径的实现 最短路径分析属于ArcGIS的网络分析范畴.而ArcGIS的网络分析分为两类,分别是基于几何网络和网络数据集的网络分析.它们都可以实现最短路径功能.下面先介绍 ...

  4. ArcEngine中打开各种数据源(WorkSpace)的连接

    (SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源.在开发过程中我们使用了如下几种数据源 1.企业数据库(SDE) 企业 ...

  5. ArcEngine中打开各种数据源(WorkSpace)的连接(转)

    ArcEngine中打开各种数据源(WorkSpace)的连接 (SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源.在开 ...

  6. ArcEngine中打开各种数据源(WorkSpace)的连接http://www.cnblogs.com/feilong3540717/archive/2011/08/07/2129906.html

    ArcEngine中打开各种数据源(WorkSpace)的连接 ArcEngine中打开各种数据源(WorkSpace)的连接 (SDE.personal/File.ShapeFile.CAD数据.影 ...

  7. [转] ArcEngine中打开各种数据源(WorkSpace)的连接

    原文 ArcEngine中打开各种数据源(WorkSpace)的连接(SDE.personal/File.ShapeFile.CAD数据.影像图.影像数据集) ArcEngine 可以接受多种数据源. ...

  8. ArcEngine查询、添加、删除要素的方法

    原文 ArcEngine查询.添加.删除要素的方法 1.查找数据 1).利用FeaturCursor进行空间查询 //空间查询 ISpatialFilter spatialFilter = new S ...

  9. ArcMAp对线要素进行平滑处(打断)

    一:工具简单介绍 -- ArcMAp10.1的高级编辑工具中提供了对线/面要素进行概括/平滑处理的工具. 概括工具.平滑工具分别例如以下:(首先得开启编辑状态 --- 才干够对要素的属性进行更改).选 ...

随机推荐

  1. js单击输入框后弹出提示信息效果

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. Unsafe的应用

    要想把java并发包学好,并明白其底层的设计原理,Unsafe类你不能不去研究一下.下面介绍一下Unsafe类的功能以及它在JDK中的应用. 一.分配内存和释放内存 功能:类中提供的3个本地方法all ...

  3. JAVA 设计模式 适配器模式

    用途 适配器模式 (Adapter) 将一个类的接口转换成客户希望的另外一个接口. Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 适配器模式是一种结构型模式. 结构

  4. C# Socket系列二 简单的创建 socket 通信

    看了系列一 我们开启了对socket tcp的监听状态,那么这一章我们来讲解怎么创建socket的通信代码 我新建一个类 TSocketBase public abstract class TSock ...

  5. 从.net转型,聊聊最近一些面试,薪资和想法

    上一个星期,一篇名为<.net估计要写在你手里了>几乎点燃了整个园子,有人群情激愤了,有人点赞的,有人上去打算喷博主个体无完肤的,总之,这篇博客很成功的引起一些.net 从业者的思考,也包 ...

  6. 【C#】让ReSharper灰色显示未使用的非私有成员的关键

    环境:VS2010+ReSharper8 先说答案: 1.在Inspection Severity中设置Non-private accessibility为Warning.如图: 该页面在ReShar ...

  7. Linq和Lamda表达式的简单处理方式

    一 什么是LINQ? LINQ即Language Integrated Query(语言集成查询),LINQ是集成到C#和Visual Basic.NET这些语言中用于提供查询数据能力的一个新特性. ...

  8. C#的变迁史 - C# 1.0篇

    C#与.NET平台诞生已有10数年了,在每次重大的版本升级中,微软都为这门年轻的语言添加了许多实用的特性,下面我们就来看看每个版本都有些什么.老实说,分清这些并没什么太大的实际意义,但是很多老资格的. ...

  9. 介绍开源的.net通信框架NetworkComms框架 源码分析(七)ProtobufSerializer

    原文网址: http://www.cnblogs.com/csdev Networkcomms 是一款C# 语言编写的TCP/UDP通信框架  作者是英国人  以前是收费的 目前作者已经开源  许可是 ...

  10. 【Java每日一题】20161130

    20161129问题解析请点击今日问题下方的"[Java每日一题]20161130"查看 package Nov2016; public class Ques1130 { publ ...