【ArcGIS Pro二次开发】(11):面要素的一键拓扑

在工作中,经常需要对要素进行拓扑检查。

在ArcGIS Pro中正常的工作流程是在数据库中【新建要素数据集——新建拓扑——将要素加入拓扑——添加规则——验证】,工作流程不算短,操作起来比较繁琐。

下面以一个例子演示如何在ArcGIS Pro SDK二次开发中实现一键拓扑。


一、要实现的功能

如上图所示,在待检查的面要素上右键,单击自定义的【面要素拓扑】按钮即可,运行结果生成检查结果【TopErr_poly】。查看属性表如下:

这个工具本质上就是让拓扑的几个操作步骤在后动自动运行,所以生成的结果和拓扑结果是一样的,好处在于省时省力。

本例子只针对【单个面要素的重叠检查】,功能是少了点,后期可能会扩展一下,把拓扑功能都加进来。


二、实现流程

1、设置UI,新建自定义按钮,添加到要素图层的右键菜单里,具体可以参看我这个系列的文章。或者查看文章后面放出的工程文件,这里就不展开说了。

2、获取默认数据库、所选的要素图层,并检查是否是面要素。

            // 获取默认数据库
            var gdb = Project.Current.DefaultGeodatabasePath;
            // 获取图层
            FeatureLayer ly = MapView.Active.GetSelectedLayers().FirstOrDefault() as FeatureLayer;
            // 如果选择的不是面要素或是无选择,则返回
            if (ly.ShapeType != esriGeometryType.esriGeometryPolygon || ly == null)
            {
                MessageBox.Show("请选择一个面要素,否则不能执行!");
                return;
            }

3、获取所选图层的坐标系,并通过调用Geoprocessing工具实现在默认数据库中创建要素数据集。【实际上后面的步骤都是通过调用Geoprocessing工具来实现的,真是省时省力】

            // 开启异步
            await QueuedTask.Run(async () =>
            {
                //获取图层的坐标系
                var sr = ly.GetSpatialReference();
                string db_name = "Top2Check";    // 要素数据集名
                string fc_name = "top_fc";        // 要素名
                string top_name = "Topology";       // TOP名
                string db_path = gdb + "\\" + db_name;    // 要素数据集路径
                string fc_path = db_path + "\\" + fc_name;         // 要素路径
                string top_path = db_path + "\\" + top_name;         // TOP路径
                //在数据库中创建要素数据集
                var par_CreatDatabase = Geoprocessing.MakeValueArray(gdb, db_name, sr);
                await Geoprocessing.ExecuteToolAsync("management.CreateFeatureDataset", par_CreatDatabase);
            });

4、将所选要素复制到创建的要素数据集中:

var par_CopyFeature = Geoprocessing.MakeValueArray(ly.Name, fc_path);
await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.CopyFeatures", par_CopyFeature));

5、新建拓扑:

var par_CreatTop = Geoprocessing.MakeValueArray(db_path, top_name);
await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.CreateTopology", par_CreatTop));

6、向拓扑中添加要素:

var par_AddFeatureClass = Geoprocessing.MakeValueArray(top_path, fc_path);
await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.AddFeatureClassToTopology", par_AddFeatureClass));

7、添加拓扑规则【重叠】:

var par_AddRule = Geoprocessing.MakeValueArray(top_path, "Must Not Overlap (Area)", fc_path, null, null, null);
await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.AddRuleToTopology", par_AddRule));

8、验证拓扑:

var par_Validate = Geoprocessing.MakeValueArray(top_path);
await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.ValidateTopology", par_Validate));

9、输出TOP错误:

var par_ExportErrors = Geoprocessing.MakeValueArray(top_path, gdb, "TopErr");
await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.ExportTopologyErrors", par_ExportErrors));

以上就是功能实现的核心代码,整理一下,完整代码如下:

        protected override async void OnClick()
        {
            // 获取默认数据库
            var gdb = Project.Current.DefaultGeodatabasePath;
            // 获取图层
            FeatureLayer ly = MapView.Active.GetSelectedLayers().FirstOrDefault() as FeatureLayer;
            // 如果选择的不是面要素或是无选择,则返回
            if (ly.ShapeType != esriGeometryType.esriGeometryPolygon || ly == null)
            {
                MessageBox.Show("请选择一个面要素,否则不能执行!");
                return;
            }
            // 开启异步
            await QueuedTask.Run(async () =>
            {
                //获取图层的坐标系
                var sr = ly.GetSpatialReference();
                string db_name = "Top2Check";    // 要素数据集名
                string fc_name = "top_fc";        // 要素名
                string top_name = "Topology";       // TOP名
                string db_path = gdb + "\\" + db_name;    // 要素数据集路径
                string fc_path = db_path + "\\" + fc_name;         // 要素路径
                string top_path = db_path + "\\" + top_name;         // TOP路径
                //在数据库中创建要素数据集
                var par_CreatDatabase = Geoprocessing.MakeValueArray(gdb, db_name, sr);
                await Geoprocessing.ExecuteToolAsync("management.CreateFeatureDataset", par_CreatDatabase);
                // 将所选要素复制到创建的要素数据集中
                var par_CopyFeature = Geoprocessing.MakeValueArray(ly.Name, fc_path);
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.CopyFeatures", par_CopyFeature));
                // 新建拓扑
                var par_CreatTop = Geoprocessing.MakeValueArray(db_path, top_name);
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.CreateTopology", par_CreatTop));
                // 向拓扑中添加要素
                var par_AddFeatureClass = Geoprocessing.MakeValueArray(top_path, fc_path);
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.AddFeatureClassToTopology", par_AddFeatureClass));
                // 添加拓扑规则【重叠】
                var par_AddRule = Geoprocessing.MakeValueArray(top_path, "Must Not Overlap (Area)", fc_path, null, null, null);
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.AddRuleToTopology", par_AddRule));
                // 验证拓扑
                var par_Validate = Geoprocessing.MakeValueArray(top_path);
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.ValidateTopology", par_Validate));
                // 输出TOP错误
                var par_ExportErrors = Geoprocessing.MakeValueArray(top_path, gdb, "TopErr");
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.ExportTopologyErrors", par_ExportErrors));
                // 删除中间要素
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.Delete", Geoprocessing.MakeValueArray(db_path)));
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.Delete", Geoprocessing.MakeValueArray(gdb + "\\TopErr_point")));
                await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync("management.Delete", Geoprocessing.MakeValueArray(gdb + "\\TopErr_line")));
                MessageBox.Show("完成拓扑检查【面要素,不能重叠】!");
            });
        }

三、工程文件分享

最后,放上工程文件的链接:

PolygonTopologyhttps://pan.baidu.com/s/1Djt-duOUc2MxsHfUPdhBHA?pwd=1q02

PS:可以直接点击文件夹bin\Debug\net6.0-windows\下的.esriAddinX文件直接安装。