基于C#的ArcEngine二次开发22:要素拓扑检查

目录

1 拓扑检查

1.1 拓扑检查的基本流程

1.2 拓扑检查代码

1.2.1 checkTopologyError

1.2.2 AddRuleToTopology

1.2.3 ValidateTopology

1.2.4 调用代码及效果

2 拓扑关系枚举

2.1 将文字描述转化为拓扑规则枚举对象

2.2 根据拓扑关系ID获取拓扑描述

X 异常处置

X.1 Error creating topology:-2147220960 Message:应用程序未获得创建或修改此类型数据的方案的许可

X.1.1异常描述

X.1.2 解决方案

X.2 Error creating topology:-2147220960 Message:尝试打开的数据库已被机器....以排他方式打开

X.2.1 异常描述

X.2.2 解决办法

X.3 从其他地方抄来的关于许可的说明

官方参考


先介绍一个ArcGIS拓扑检查的坑:

要素拓扑检查会修改原始数据,比如两条线间距为0.009米,实际不相交;如果容差设为0.1米,经过拓扑检查之后,会将此处融合并导致要素相交,如下图:

面对此种情形,我们应该在ArcCatalog中,新建 --> FeatureClassSet,设置更小的容差:

然后,将要检查的数据拷贝到该要素数据集中,然后在执行拓扑检查即可;注意两者的投影坐标系必须一致。


1 拓扑检查

1.1 拓扑检查的基本流程

1.2 拓扑检查代码

1.2.1 checkTopologyError

        /// <summary>
        /// 检查要素层中存在的拓扑错误
        /// </summary>
        /// <param name="wsPath">工作空间名称</param>
        /// <param name="dsPath">数据集名称</param>
        /// <param name="feaPath">要素类名称</param>
        /// <param name="topologyName">拓扑要素层名,拓扑检查结果记录在该层中</param>
        public void checkTopologyError(string wsPath, string dsPath, string feaPath, string topologyName)
        {
            // Open the workspace and the required datasets.
            Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.AccessWorkspaceFactory");
            //ESRI.ArcGIS.DataSourcesGDB
            IWorkspaceFactory workspaceFactory = new AccessWorkspaceFactory();

            //1. 打开数据集文件
            IWorkspace workspace = workspaceFactory.OpenFromFile(wsPath, 0);
            IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace;

            //2. 打开数据集文件
            IFeatureDataset featureDataset = featureWorkspace.OpenFeatureDataset(dsPath);

            //3. 向拓扑集中添加要素层
            IFeatureClass LRDLlayer = featureWorkspace.OpenFeatureClass(feaPath);
            

            //4. 设置拓扑处理对数据集的独占权限
            ISchemaLock schemaLock = (ISchemaLock)featureDataset;//注意此时不能使用ArcGIS再打开这个数据集
            try
            {
                schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);

                //5. 拓扑处理
                //5.1 创建拓扑容器
                ITopologyContainer2 topologyContainer = featureDataset as ITopologyContainer2;

                //5.2 向拓扑容器中添加拓扑结果层
                //判断当前命名的拓扑是否存在,如果存在,删除
                bool bTopExists = (featureDataset.Workspace as IWorkspace2).get_NameExists(esriDatasetType.esriDTTopology, topologyName);
                if (bTopExists)
                {
                    ITopology topologyTemp = topologyContainer.get_TopologyByName(topologyName);
                    //删除拓扑
                    IDataset pDatasetTemp = (IDataset)topologyTemp;
                    pDatasetTemp.Delete();
                    Marshal.ReleaseComObject(pDatasetTemp);
                }

                ITopology2 topology = topologyContainer.CreateTopology(topologyName,
                    topologyContainer.DefaultClusterTolerance, -1, "") as ITopology2;

               
                //5.3 添加参与拓扑运算的数据层
                topology.AddClass(LRDLlayer, 5, 1, 1, false);

                //5.4 添加拓扑规则
                AddRuleToTopology(topology, esriTopologyRuleType.esriTRTLineNoDangles, "线要素不允许有悬挂点", LRDLlayer);
                AddRuleToTopology(topology, esriTopologyRuleType.esriTRTLineNoPseudos, "线要素不允许有伪节点", LRDLlayer);
                AddRuleToTopology(topology, esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouch, "线要素不能重叠或内部接触", LRDLlayer);
                AddRuleToTopology(topology, esriTopologyRuleType.esriTRTLineNoSelfIntersect, "线要素不能自相交", LRDLlayer);
                //5.5 拓扑验证
                IGeoDataset geoDataset = (IGeoDataset)topology;
                IEnvelope envelope = geoDataset.Extent;
                ValidateTopology(topology, envelope);
            }
            catch (COMException comExc)
            {
                throw new Exception(String.Format("Error creating topology: {0} Message: {1}", comExc.ErrorCode, comExc.Message), comExc);
            }
            finally
            {
               schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
            }
            MessageBox.Show("拓扑检查完毕", "提示信息");
        }

1.2.2 AddRuleToTopology

        /// <summary>
        /// 增加拓扑规则
        /// </summary>
        /// <param name="topology">拓扑集</param>
        /// <param name="ruleType">拓扑规则</param>
        /// <param name="ruleName">规则名称</param>
        /// <param name="featureClass">要素类</param>
        public void AddRuleToTopology(ITopology topology, esriTopologyRuleType ruleType,
            String ruleName, IFeatureClass featureClass)
        {
            // Create a topology rule.
            ITopologyRule topologyRule = new TopologyRuleClass();
            topologyRule.TopologyRuleType = ruleType;
            topologyRule.Name = ruleName;
            topologyRule.OriginClassID = featureClass.FeatureClassID;
            topologyRule.AllOriginSubtypes = true;

            // Cast the topology to the ITopologyRuleContainer interface and add the rule.
            ITopologyRuleContainer topologyRuleContainer = (ITopologyRuleContainer)topology;
            if (topologyRuleContainer.get_CanAddRule(topologyRule))
            {
                topologyRuleContainer.AddRule(topologyRule);
            }
            else
            {
                throw new ArgumentException("Could not add specified rule to the topology.");
            }
        }

1.2.3 ValidateTopology

        //拓扑有效性检查
        public void ValidateTopology(ITopology topology, IEnvelope envelope)
        {
            // Get the dirty area within the provided envelope.
            IPolygon locationPolygon = new PolygonClass();
            ISegmentCollection segmentCollection = (ISegmentCollection)locationPolygon;
            segmentCollection.SetRectangle(envelope);
            IPolygon polygon = topology.get_DirtyArea(locationPolygon);
            // If a dirty area exists, validate the topology.    if (!polygon.IsEmpty)
            {        // Define the area to validate and validate the topology.
                IEnvelope areaToValidate = polygon.Envelope;
                IEnvelope areaValidated = topology.ValidateTopology(areaToValidate);
            }
        }

1.2.4 调用代码及效果

        private void buttonExecute_Click(object sender, EventArgs e)
        {
            try
            {                
                //---------------------------检查拓扑错误-------------------------------------
                string inPath = textBoxInput.Text;
                string ouPath = textBoxOutput.Text;
                if (System.IO.File.Exists(inPath))
                {
                    checkTopologyError(inPath, "Topology", "LRDL", "TopologyCheck1");
                }
                //------------------------------------------------------------------------------
            }
            catch (Exception ex)
            {
                MessageBox.Show("触发异常操作:" + ex.ToString(), "执行失败");
            }
        }
拓扑检查结果

2 拓扑关系枚举

2.1 将文字描述转化为拓扑规则枚举对象

        /// <summary>
        /// 根据错误的中文描述转换成esri拓扑枚举
        /// </summary>
        /// <param name="IN_TopoRuleType">拓扑类型</param>
        /// <returns>ESRI.ArcGIS.Geodatabase下的拓扑规则枚举类</returns>
        private esriTopologyRuleType PRV_ConvertTopologyRuleType(TopoErroType IN_TopoRuleType)
        {
            esriTopologyRuleType Temp_TopoRuleType;
            switch (IN_TopoRuleType)
            {
                case TopoErroType.面要素之间无空隙:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoGaps;
                    break;
                case TopoErroType.任何规则:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAny;
                    break;
                case TopoErroType.要素大于最小容差:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTFeatureLargerThanClusterTolerance;
                    break;
                case TopoErroType.面要素间无重叠:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoOverlap;
                    break;
                case TopoErroType.第二个图层面要素必须被第一个图层任一面要素覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaCoveredByAreaClass;
                    break;
                case TopoErroType.面要素必须只包含一个点要素:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaContainOnePoint;
                    break;
                case TopoErroType.两图层面要素必须互相覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaAreaCoverEachOther;
                    break;
                case TopoErroType.第一个图层面要素必须被第一个图层任一面要素包含:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaCoveredByArea;
                    break;
                case TopoErroType.图层间面要素不能相互覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaNoOverlapArea;
                    break;
                case TopoErroType.线要素必须跟面图层边界的一部分或全部重叠:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineCoveredByAreaBoundary;
                    break;
                case TopoErroType.点要素必须落在面要素边界上:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByAreaBoundary;
                    break;
                case TopoErroType.点要素必须落在面要素内:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointProperlyInsideArea;
                    break;
                case TopoErroType.线要素间不能有相互重叠部分:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoOverlap;
                    break;
                case TopoErroType.线要素之间不能相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersection;
                    break;
                case TopoErroType.线要素不允许有悬挂点:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoDangles;
                    break;
                case TopoErroType.线要素不允许有假节点:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoPseudos;
                    break;
                case TopoErroType.第一个图层线要素应被第二个线图层线要素覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineCoveredByLineClass;
                    break;
                case TopoErroType.第一个图层线要素不被第二个线图层线要素覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoOverlapLine;
                    break;
                case TopoErroType.点要素应被线要素覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByLine;
                    break;
                case TopoErroType.点要素应在线要素的端点上:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointCoveredByLineEndpoint;
                    break;
                case TopoErroType.面要素边界必须被线要素覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaBoundaryCoveredByLine;
                    break;
                case TopoErroType.面要素的边界必须被另一面要素边界覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaBoundaryCoveredByAreaBoundary;
                    break;
                case TopoErroType.线要素不能自重叠:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoSelfOverlap;
                    break;
                case TopoErroType.线要素不能自相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoSelfIntersect;
                    break;
                case TopoErroType.线要素间不能重叠和相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouch;
                    break;
                case TopoErroType.线要素端点必须被点要素覆盖:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineEndpointCoveredByPoint;
                    break;
                case TopoErroType.面要素内必须包含至少一个点要素:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAreaContainPoint;
                    break;
                case TopoErroType.线不能是多段:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoMultipart;
                    break;
                case TopoErroType.点要素之间不相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTPointDisjoint;
                    break;
                case TopoErroType.线要素必须不相交:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectLine;
                    break;
                case TopoErroType.线必须不相交或内部接触:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTLineNoIntersectOrInteriorTouchLine;
                    break;
                default:
                    Temp_TopoRuleType = esriTopologyRuleType.esriTRTAny;//将此规则赋予拓扑会直接报错  
                    break;
            }
            return Temp_TopoRuleType;
        }

2.2 根据拓扑关系ID获取拓扑描述

         //根据错误ID获取对应描述  
        public enum TopoErroType
        {
            任何规则 = -1,
            要素大于最小容差 = 0,
            面要素之间无空隙 = 1,
            面要素间无重叠 = 3,
            第二个图层面要素必须被第一个图层任一面要素覆盖 = 4,
            两图层面要素必须互相覆盖 = 5,
            第一个图层面要素必须被第一个图层任一面要素包含 = 7,
            图层间面要素不能相互覆盖 = 8,
            线要素必须跟面图层边界的一部分或全部重叠 = 10,
            线要素必须在面内 = 11,
            点要素必须落在面要素边界上 = 13,
            点要素必须落在面要素内 = 15,
            面要素必须只包含一个点要素 = 16,
            线要素间不能有相互重叠部分 = 19,
            线要素之间不能相交 = 20,
            线要素不允许有悬挂点 = 21,
            线要素不允许有假节点 = 22,
            第一个图层线要素应被第二个线图层线要素覆盖 = 26,
            第一个图层线要素不被第二个线图层线要素覆盖 = 28,
            点要素应被线要素覆盖 = 29,
            点要素应在线要素的端点上 = 31,
            点要素之间不相交 = 34,
            点要素重合点要素 = 35,
            面要素边界必须被线要素覆盖 = 37,
            面要素的边界必须被另一面要素边界覆盖 = 38,
            线要素不能自重叠 = 39,
            线要素不能自相交 = 40,
            线要素间不能重叠和相交 = 41,
            线要素端点必须被点要素覆盖 = 42,
            面要素内必须包含至少一个点要素 = 43,
            线不能是多段 = 44,
            线要素必须不相交 = 45,
            线必须不相交或内部接触 = 46
        };

        /// <summary>
        /// 根据ID获取错误类型
        /// </summary>
        /// <param name="IN_TopoType">l类型ID</param>
        /// <returns>类型字符串</returns>
        private string PRV_RecorverTopologyRuleType(int IN_TopoType)
        {
            //根据枚举值获取枚举名  
            string Temp_ErrorDiscripe = Enum.GetName(typeof(TopoErroType), IN_TopoType);
            if (Temp_ErrorDiscripe == null)
                return (IN_TopoType.ToString());//若规则不在列表内则直接返回规则号  
            else
                return Temp_ErrorDiscripe;
        }

X 异常处置

X.1 Error creating topology:-2147220960 Message:应用程序未获得创建或修改此类型数据的方案的许可

X.1.1异常描述

原因:缺乏Advanced许可

X.1.2 解决方案

只勾选Advanced,其他的不要勾选。

X.2 Error creating topology:-2147220960 Message:尝试打开的数据库已被机器....以排他方式打开

X.2.1 异常描述

这个异常是因为你的数据库文件被其他软件,如ArcGIS打开了,需要关闭

如果要素层同时被ArcGIS打开,会报如下异常:意思是要素已被排他的方式占用

X.2.2 解决办法

关闭数据库文件

X.3 从其他地方抄来的关于许可的说明

原文链接:ArcGIS Engine中的License设置

AE开发中的License有两种方法进行设置,一种是通过LicenseControl控件,另一种是通过IAoInitialize接口设置。整个应用程序中只能有一种方式存在,如果进行了两种License设置,就可能产生错误。当然,对于一个健壮的程序而言,我们还需要在初始化之前先判断将被初始化的许可是否可用,应先使用IsProductCodeAvailable方法进行判断,需要初始化扩展模块的许可,可使用CheckOutExtension方法。下面为许可的检测代码

一些重要原则

  1. 初始化许可的一条重要原则就是一个程序只能初始化许可一次,已经初始化许可的程序一旦运行就无法再修改其初始化的许可,即程序运行期间无法修改其使用的许可。
  2. LicenseControl中多选许可是没有意义的,第一个被勾选的许可生效。理论上License中可以勾选多项许可,但运行程序时其作用的是第一个被勾选的许可。如下图只有ArcGIS Engine许可被初始化了。
  3. 什么情况下需要GDB Update许可:当需要对SDE里数据进行编辑时,以及需要在SDE和Personal Geodatabase中创建复杂ArcGIS对象时,需要使用GDB Update许可。对SDE里的数据编辑,很好理解,大致就是进行数据插入,删除,更新;对表添加、删除和修改,表结构的变化(添加、删除列)等,因为这些动作都会造成后台数据库的写操作。
  4. 对 于Personal Geodatabase,进行简单数据对象和编辑,包括创建、删除和修改普通表都是不需要GDB Update许可的,但对于复杂的Geodatabse对象的创建、删除和修改,则需要GDB Update许可,其中复杂的Geodatabse对象包括几何网络,网络分析模型,拓扑,关系类。这也是为什么往往有写好了一个创建几何网络或拓扑的程 序后,执行起来会被报“需要Geodatabase Update许可”的错。
  5. 当需要获取GDB Update许可时,只需勾选ArcGIS Engine Enterprise Geodatabase就可以了

官方参考

  1. Checking for topology error features in a geodatabase topology
  2. ArcEngine 拓扑检查 总结
  3. ArcEngine的拓扑检查类
  4. ArcEngine创建拓扑并验证拓扑

  5. ArcEngine实现拓扑检查


喜欢我的分享,可以关注以下两个公众号:

  • 9
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
### 回答1: 基于C#ArcEngine二次开发是一种利用ArcGIS Engine开发工具和C#编程语言来实现GIS应用程序的方法。ArcEngine是一种基于组件的GIS开发平台,它提供了一系列的API和工具,可以帮助开发人员快速构建高效、灵活、可定制的GIS应用程序。C#是一种面向对象的编程语言,它具有简单易学、语法清晰、可读性强等特,非常适合用于GIS应用程序的开发。基于C#ArcEngine二次开发可以实现各种功能,如地图显示、数据查询、空间分析、地图制图等,可以广泛应用于各种领域,如城市规划、土地利用、环境保护、资源管理等。 ### 回答2: ++的编程语言,它有什么优? C++ 是一种功能强大的编程语言,它几乎拥有 C 语言所有的优,还可以在面向对象编程方面提供更高效和灵活的方式。下面是 C++ 的几个主要优: 1. 高效性:C++ 是一种高效的编程语言。与其他编程语言相比,C++ 的执行速度更快,它使用了更少的内存和 CPU 周期,因此可以为需要高性能的应用程序提供更好的支持。 2. 跨平台性:C++ 的编译器可以运行在许多平台上,包括 Windows、MacOS、Linux、Android 和 iOS 等。这使得 C++ 成为一种支持跨平台开发的编程语言,具有极高的灵活性和可扩展性。 3. 面向对象编程:C++ 的面向对象编程能力非常强大。它支持多态、继承和封装等特性,使得面向对象编程更加容易和灵活。 4. 库管理:C++ 提供了许多强大的库,使得开发人员可以轻松地访问各种常用功能,例如文件 I/O、字符串处理、图形界面等。这些库可以大大提高开发人员的效率,减少重复劳动。 5. 可扩展性:C++ 还具有很高的可扩展性。开发人员可以使用 C++ 来编写模块、插件和扩展程序,以满足特定的需求。此外,C++ 还提供了丰富的 API,使得开发人员可以在其程序中使用其他编程语言和技术。 总的来说,C++ 是一种功能强大、高效、跨平台、面向对象、可扩展的编程语言。它在许多行业和领域中都有广泛的应用,例如游戏开发、嵌入式系统、图形界面等。对于需要高性能和高可靠性的应用程序开发来说,C++ 是一种不错的选择。 ### 回答3: 语言的网络编程的特是什么? C语言作为一种高效、简洁、可移植的编程语言,在网络编程中也有一定的应用。C语言基于网络编程的特主要有以下几个方面: 1.底层控制:C语言网络编程的一个重要特是可以对网络协议的底层进行直接控制,比如可以进行原始套接字编程。这种方式可以对网络数据包进行非常细致的处理和控制,使网络程序能够更好地适应各种各样的网络环境。 2.高效性:C语言是一种高效的编程语言,它可以为网络应用程序提供高效的性能。C语言可以通过优化算法和数据结构,降低网络应用程序的延迟和响应时间,提高网络应用程序的吞吐量,保证网络的快速响应。 3.可移植性:C语言是一种可移植的编程语言,可以在多种平台上进行开发和编译。因此,使用C语言开发网络应用程序能够保证程序在不同的操作系统和硬件平台上都能够正常运行。 4.丰富的库函数:C语言提供了丰富的库函数,可以在网络编程中提供各种功能的支持。比如可以通过各种库函数实现TCP/UDP套接字编程、服务器端编程、客户端编程、线程编程等各种网络编程功能。 总之,C语言在网络编程中具有非常重要的地位。C语言网络编程的特主要包括底层控制、高效性、可移植性和丰富的库函数。这些特使得C语言成为网络编程开发者的首选语言之一。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小薛引路

喜欢的读者,可以打赏鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值