基于C#的ArcEngine二次开发34:使用ConstructUnion方法进行多要素合并(下)

简介: 基于C#的ArcEngine二次开发34:使用ConstructUnion方法进行多要素合并(下)

3 根据几何合并

通过几何条件判断的方式连接断开的线要素的ArcGIS 插件完成,在这里把思路和代码和大家分享下:

3.1 程序思路和实现过程

1.首先读取shp线文件,将各条线要素遍历,存储在List,这里之所以不存在List和List中的原因是后两者会丢失要素的属性信息;


2.为了简化合并算法的逻辑和复杂性,采用分治思想。将线要素分为需要进行合并和不需要进行合并(独立的线,ToPoint或FromPoint是“节点”的线和ToPoint,FromPoint均是“节点”线)的两大类,分别存储在两个集合中;


3.现在只需对需要进行合并的的线要素集合进行合并操作。首先从集合中选取一条Polyline,然后在集合剩下的元素中寻找与其ToPoint或FromPoint相同的线要素,然后使用ITopologicalOperator2.Union()方法进行合并,然后寻找和合并后新的Polyline的ToPoint或FromPoint相同的线要素继续合并,没合并一次,就将合并入的Polyline从集合中移除,直到剩下的Polyline不可和当前合并的Polyline合并为止,这样就得到了第一条合并好的Polyline。接着从集合剩下的线要素再找一条Polyline开始新一轮合并操作,直到List为空,整个合并操作结束;


4.得到合并好的List mergeResultLineList后,需要为其添加属性(NAME等字段),通过IFeatureBuffer接口写入shape和Fields,然后Flush到文件中,结束。

3.2 程序实例和结果

prk5jtgggn43i_166e073e4e4441ab84214568d5f3d5c1.png

prk5jtgggn43i_0fbce72c450d4f7bb108ea751e49b48e.png

prk5jtgggn43i_da3c535dc3a0488ba1830751ca8bda0f.png

3.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%60;
            //pBar.Hide();
            MessageBox.Show("线要素合并结束,运行程序共耗时约:" + minutes + "分"+ seconds + "秒");
        }
        //获取shp文件中所有的Polyline(IFeature)对象
        public List<IFeature> getAllPolyline()
        {
            IFeatureLayer featureLayer = map.get_Layer(1) 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 = 0;
                int toFlag = 0;
                for (int i = 0; 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 > 2 || toFlag > 2 || (fromFlag == 1 && toFlag == 1))
                {
                    noNeedUnionLineList.Add(featureLine);
                    //noNeedUnionLineFileds.Add(featureLine.Fields);
                }
            }
            return noNeedUnionLineList;
        }
        //将需要进行合并的线要素(没有节点)集合进行合并,结果为多条线       
        public List<IFeature> MergeLineListOperate(List<IFeature> toUnionLineList)
        {
            List<IFeature> mergeResultLineList = new List<IFeature>();
            int CountPercent = 0;
            while (toUnionLineList.Count > 0)
            {
                CountPercent++;
                //初始化当前合并的线要素
                IFeature unionCurrentLine = toUnionLineList[0];
                //将第一个要素的属性字段值作为最终合并线要素的值
                firstRowFeatureList.Add(unionCurrentLine);
                List<IFeature> currentMergeLineList = new List<IFeature>();
                int count2 = 0;
                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 = 0;
                    int bStart2 = 0;
                    for (int j = 0; 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 > 0)
                            {
                                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 > 0)
                            {
                                allPolylineListTemp2.Add(featureSecond);
                                currentMergeLineList.AddRange(allPolylineListTemp2);
                                toUnionLineList.Remove(featureSecond);
                            }
                        }
                    }
                    if (currentMergeLineList.Count > 1)
                    {
                        unionCurrentLine = UnionCurrentLineList(currentMergeLineList);
                    }
                    else
                    {
                        int ii = 0;
                    }
                } while (currentMergeLineList.Count > 1);
                mergeResultLineList.Add(unionCurrentLine);
            }
            return mergeResultLineList;
        }
        //为待写入图层添加Name和GB字段
        public void AddField()
        {
            IFeatureLayer featureLayer2 = map.get_Layer(0) 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(0) 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 >= 0)
                {
                    featureBuffer.set_Value(fieldindex1, name);
                }
                if (fieldindex2 >= 0)
                {
                    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 = 0;
            foreach (IFeature featureLine in mergeResultLineList)
            {
                IFeatureLayer featureLayer2 = map.get_Layer(0) 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 >= 0)
                {
                    featureBuffer.set_Value(fieldindex1, name);
                }
                if (fieldindex2 >= 0)
                {
                    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(1) as IFeatureLayer;
            IFeatureClass featureClass = featureLayer.FeatureClass;
            ITopologicalOperator2 pTopologicalOperator;
            IFeature pFeatureTemp = currentMergeLineList[0];
            IGeometry pGeometry = pFeatureTemp.Shape;
            int i = 1;
            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;
        }
    }
相关文章
|
1月前
|
开发框架 .NET 程序员
C# 去掉字符串最后一个字符的 4 种方法
在实际业务中,我们经常会遇到在循环中拼接字符串的场景,循环结束之后拼接得到的字符串的最后一个字符往往需要去掉,看看 C# 提供了哪4种方法可以高效去掉字符串的最后一个字符
164 0
|
16天前
|
编译器 C#
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
C#多态概述:通过继承实现的不同对象调用相同的方法,表现出不同的行为
111 65
|
14天前
|
存储 C#
【C#】大批量判断文件是否存在的两种方法效率对比
【C#】大批量判断文件是否存在的两种方法效率对比
23 1
|
15天前
|
C#
C#的方法的参数传递
C#的方法的参数传递
9 0
|
15天前
|
数据可视化 程序员 C#
C#中windows应用窗体程序的输入输出方法实例
C#中windows应用窗体程序的输入输出方法实例
11 0
|
1月前
|
C#
C#一分钟浅谈:Lambda 表达式和匿名方法
本文详细介绍了C#编程中的Lambda表达式与匿名方法,两者均可用于定义无名函数,使代码更简洁易维护。文章通过基础概念讲解和示例对比,展示了各自语法特点,如Lambda表达式的`(parameters) =&gt; expression`形式及匿名方法的`delegate(parameters)`结构。并通过实例演示了两者的应用差异,强调了在使用Lambda时应注意闭包问题及其解决策略,推荐优先使用Lambda表达式以增强代码可读性。
35 8
|
2月前
|
图形学 C# 开发者
全面掌握Unity游戏开发核心技术:C#脚本编程从入门到精通——详解生命周期方法、事件处理与面向对象设计,助你打造高效稳定的互动娱乐体验
【8月更文挑战第31天】Unity 是一款强大的游戏开发平台,支持多种编程语言,其中 C# 最为常用。本文介绍 C# 在 Unity 中的应用,涵盖脚本生命周期、常用函数、事件处理及面向对象编程等核心概念。通过具体示例,展示如何编写有效的 C# 脚本,包括 Start、Update 和 LateUpdate 等生命周期方法,以及碰撞检测和类继承等高级技巧,帮助开发者掌握 Unity 脚本编程基础,提升游戏开发效率。
60 0
|
5月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
178 3
|
5月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
189 3
|
9天前
|
安全 C# 数据安全/隐私保护
实现C#编程文件夹加锁保护
【10月更文挑战第16天】本文介绍了两种用 C# 实现文件夹保护的方法:一是通过设置文件系统权限,阻止普通用户访问;二是使用加密技术,对文件夹中的文件进行加密,防止未授权访问。提供了示例代码和使用方法,适用于不同安全需求的场景。