【ArcGIS Pro二次开发】(77):ArcGIS Pro中图层的获取与解析

news/2023/12/9 20:06:11 标签: arcgis, c#, arcgis pro二次开发, arcgis pro sdk, 图层

一、最简单的获取图层方式

通常情况下,如果要获取当前地图中的图层,可以用2种方法获取。

以下图为例:

一种是【map.Layers】属性获取,结果如下:

可以看出,这里只获取到了第一层级的图层图层组下面的二级图层被忽略了,显然这不是我们想要的。

另一种是通过map.GetLayersAsFlattenedList()方法获取,结果如下:

这次的结果,不管是第一层级还是第二层级的图层都得到了。

但美中不足的是,图层的结构被打散了,比如说【FW】图层,实际是【新建图层组】下的图层,正确的表达为【新建图层组\FW】。

为什么说这才是正确的表达,如果你用过GP工具就会发现,输入数据是图层的话,只有【新建图层组\FW】这种表达方式才是正确的,如果输入的是【FW】,将是无效的输入。

那边,下一步要做的就是获取图层完整的路径结构。


二、获取图层完整的路径结构

由于SDK没有提供获取图层完整路径结构的接口,那么这个事情就只能自己动手了。

思路其实也不难,就是通过获取图层的父图层,然后把父图层的名字加到结果中就行了,直到父图层是地图为止。

代码如下:

// 获取图层的完整名称
public static List<object> GetLayerFullName(this Object layer, Map map, string lyName)
{
    List<object> result = new List<object>();
    // 如果是图层
    if (layer is Layer)
    {
        // 如果父对象是Map,直接返回图层名
        if (((Layer)layer).Parent is Map)
        {
            result.Add(layer);
            result.Add(lyName);
            return result;
        }
        else
        {
            // 如果父对象是不是Map,则找到父对象图层,并循环查找上一个层级
            Layer paLayer = (Layer)((Layer)layer).Parent;
            List<object> list = paLayer.GetLayerFullName(map, @$"{paLayer}\{lyName}");
            return list;
        }
    }
    // 如果是独立表
    else if (layer is StandaloneTable)
    {
        // 如果父对象是Map,直接返回图层名
        if (((StandaloneTable)layer).Parent is Map)
        {
            result.Add(layer);
            result.Add(lyName);
            return result;
        }
        else
        {
            // 如果父对象是不是Map,则找到父对象图层,并循环查找上一个层级
            Layer paLayer = (Layer)((StandaloneTable)layer).Parent;
            List<object> list = paLayer.GetLayerFullName(map, @$"{paLayer}\{lyName}");
            return list;
        }
    }
    else
    {
        return null;
    }
}

这里先把图层组排除,只考虑一般图层的情况,获取的图层列表如下:

OK,正是想要的结果。

但是,其实这还并不完美,因为这里没有考虑到更复杂的情况,比如说同名图层。稍微调整一下:

再试一下上面的方法,导出结果为:

可以看到,同名图层都被列入列表,但是名称都一样。如果这时候将其作为输入数据,系统就无法认出到底该用哪一个,就只会将第一个作为输入数据,这显然也不是我们想要的。

于是我们要做的是,给这些同名图组作一个标记,作为输入数据的标识。


三、标识同名图层

在我们获取到图层列表后,就可以对列表进行处理。

这里用到的方法是,新建一个字典,用来记录列表中每条记录的出现次数,然后按出现的先后用数字后缀给它标记。

然后再找出只有一个记录,也就是没有同名的图层,把它的【1】的标记去掉就可以了。

代码如下:

// 对重复要素进行数字标记
public static List<string> AddNumbersToDuplicates(this List<string> stringList)
{
    // 使用Dictionary来跟踪每个字符串的出现次数
    Dictionary<string, int> stringCount = new Dictionary<string, int>();
    // 遍历字符串列表
    for (int i = 0; i < stringList.Count; i++)
    {
        string currentString = stringList[i];
        // 检查字符串是否已经在Dictionary中存在
        if (stringCount.ContainsKey(currentString))
        {
            // 获取该字符串的出现次数
            int count = stringCount[currentString];
            // 在当前字符串后添加数字
            stringList[i] = $"{currentString}:{count + 1}";
            // 更新Dictionary中的计数
            stringCount[currentString] = count + 1;
        }
        else
        {
            // 如果字符串在Dictionary中不存在,将其添加,并将计数设置为1
            stringCount.Add(currentString, 1);
            // 在当前字符串后添加数字
            stringList[i] = $"{currentString}:{1}";
        }
    }
    // 去除单个要素的数字标记
    foreach (var item in stringCount)
    {
        if (item.Value == 1)
        {
            for (int i = 0; i < stringList.Count; i++)
            {
                if (stringList[i] == item.Key + ":1")
                {
                    stringList[i] = item.Key;
                }
            }
        }
    }
    // 返回字符串列表
    return stringList;
}

运行后结果如下:

可以看到,同名图层的后面加上了数字标记,OK,大功造成。

.......并没有。

虽然标记出来了,但是如果在使用GP工具的时候,输入的是【规划用地:1】这样的字符串,也是无效的。

这时候就要转换一下思路了,GP工具输入的不仅可以是字符串,也可以是图层。因此我们要做的是将上面的字符串还原成图层


四、将图层名字符串还原成图层

首先解释下为什么要这么麻烦,先获取图层名,再还原成图层,进行GP运算,直接将获取的图层作为输入数据不行吗?

这是因为在工具中,经常需要用户手动选择图层,而真正执行的流程是在按下执行键后才进行的,并不在同一个进程中。 

现在的问题是怎么让上面获取到的图层名和它的实际图层一一对应上。

很简单,再来一遍查找图层就行了, 不过这次,我们不仅要获取完整图名,同时也要获取它的原始图层

这里用一个字典来收集。代码如下:

// 获取地图中的所有要素图层【带图层结构】【字典】
public static Dictionary<FeatureLayer, string> AllFeatureLayersDic(this Map map)
{
    Dictionary<FeatureLayer, string> dic = new Dictionary<FeatureLayer, string>();
    List<string> layers = new List<string>();
    List<FeatureLayer> lys = new List<FeatureLayer>();
    // 获取所有要素图层
    List<FeatureLayer> featureLayers = map.GetLayersAsFlattenedList().OfType<FeatureLayer>().ToList();

    foreach (FeatureLayer featureLayer in featureLayers)
    {
        List<object> list = featureLayer.GetLayerFullName(map, featureLayer.Name);

        layers.Add((string)list[1]);
        lys.Add(featureLayer);
    }
    // 标记重复
    layers.AddNumbersToDuplicates();
    // 加入字典
    for (int i = 0; i < lys.Count; i++)
    {
        dic.Add(lys[i], layers[i]);
    }
    // 返回值
    return dic;
}

获取字典后,对着图层名找到图层即可:

// 查找要素图层
foreach (var layer in dicFeatureLayer)
{
    if (layerFullName == layer.Value)
    {
        result.Add(layer.Key);
    }
}

OK,这次是大功告成了,完美闭环。


http://www.niftyadmin.cn/n/5200911.html

相关文章

第十一章 目标检测中的NMS

精度提升 众所周知&#xff0c;非极大值抑制NMS是目标检测常用的后处理算法&#xff0c;用于剔除冗余检测框&#xff0c;本文将对可以提升精度的各种NMS方法及其变体进行阶段性总结。 总体概要&#xff1a; 对NMS进行分类&#xff0c;大致可分为以下六种&#xff0c;这里是依…

【算法设计实验三】动态规划解决01背包问题

请勿原模原样复制&#xff01; 01背包dp具体解释详见链接 ↓ 【算法5.1】背包问题 - 01背包 &#xff08;至多最大价值、至少最小价值&#xff09;_背包问题求最小价值_Roye_ack的博客-CSDN博客 关于如何求出最优物品选择方案&#xff1f; 先在递归求dp公式时&#xff0c;若…

用Auth Analyzer插件批量测试接口越权,安全测试快人一步!

随着信息化技术的不断发展&#xff0c;软件安全成了软件行业的重大挑战&#xff0c;因此安全测试也成为了测试人员必备的技能之一。 沐沐在安全测试过程中较为常见的就是接口越权漏洞&#xff0c;在尝试过多种工具进行越权漏洞测试后&#xff0c;最终找到了个人认为最便捷最有…

8.3 Windows驱动开发:内核遍历文件或目录

在笔者前一篇文章《内核文件读写系列函数》简单的介绍了内核中如何对文件进行基本的读写操作&#xff0c;本章我们将实现内核下遍历文件或目录这一功能&#xff0c;该功能的实现需要依赖于ZwQueryDirectoryFile这个内核API函数来实现&#xff0c;该函数可返回给定文件句柄指定的…

硬件寿命警告!Windows11在特定情况下对【固态硬盘】执行与【机械硬盘】相同的磁盘碎片整理。

首图&#xff0c;无图无真相 据我所知 此bug已持续约3个月。 此bug目前仍可以在Windows Feature Experience Pack 1000.25997.1000.0版本复现&#xff08;截至2023/11/21&#xff0c;最新的Windows预览金丝雀通道&#xff09; 如何复现 1 手动运行系统维护&#xff0c;点…

【用unity实现100个游戏之16】Unity程序化生成随机2D地牢游戏2(附项目源码)

文章目录 先看看最终效果前言生成走廊生成房间修复死胡同增加走廊宽度获取走廊位置信息集合方法一方法二 源码完结 先看看最终效果 前言 上期已经实现了房间的生成&#xff0c;本期紧跟着上期内容&#xff0c;生成走廊并结合上期内容生成连通的房间。 生成走廊 修改Procedur…

【算法之路】高精度算法(实现加减乘除)

目录 一、高精度概念 二、高精度算法的实现 1、高精度加法&#xff08;大整数相加&#xff09; 2、高精度减法&#xff08;大整数减法&#xff09; 3、高精度乘法&#xff08;大整数*小整数&#xff09; 4、高精度除法&#xff08;大整数/小整数&#xff09; 一、高精度概…

中国出海主力系列专访之三七互娱:亚马逊云科技助力三七互娱海外“出圈”之路

如果问&#xff0c;在众多的中国出海赛道中哪一条拥有基数最大的粉丝拥趸&#xff1f;以网络游戏、社交媒体、直播、短视频为代表的泛娱乐赛道便成为当仁不让的领跑者。 在东京、新加坡、开罗、伦敦、纽约、慕尼黑等国际都市&#xff0c;当地的年轻人会随时随地的打开“中国造”…

Java实现象棋算法

象棋算法包括搜索算法、评估函数和剪枝算法。以下是一个简单的实现&#xff1a; 搜索算法&#xff1a;使用极大极小值算法&#xff0c;即每个玩家都会做出最好的选择&#xff0c;考虑到对方也会做出最好的选择&#xff0c;所以需要搜索多层。 public int search(int depth, i…

JavaEE初阶--------第七章 HashMsp、HashTable 和 ConcurrentHashMap 之间的区别

系列文章目录 第七章 HashMsp、HashTable 和 ConcurrentHashMap 之间的区别 文章目录 系列文章目录第七章 HashMsp、HashTable 和 ConcurrentHashMap 之间的区别 一、多线程环境使用哈希表1、HashTable2、ConcurrentHashMap 总结 一、多线程环境使用哈希表 HashMap 本身不是线…

Rust语言精讲:数据类型全解析

大家好&#xff01;我是lincyang。 今天&#xff0c;我们将深入探讨Rust语言中的数据类型&#xff0c;这是理解和掌握Rust的基础。 Rust语言数据类型概览 Rust是静态类型语言&#xff0c;所有变量类型在编译时确定。Rust的数据类型分为两类&#xff1a;标量类型和复合类型。…

zabbix告警 邮件告警 钉钉告警

邮件告警添加主机组添加模板添加主机在模板中添加监控项在模板中添加触发器添加动作&#xff0c;远程执行命令给用户绑定告警媒介类型 钉钉告警安装python依赖模块python-requests配置钉钉告警配置脚本zabbix_ding.conf在目录/var/log/zabbix中创建钉钉告警日志文件zabbix_ding…

在springBoot中同时使用mysql和MongoDB

在SpringBoot中非关系向数据库MongoDB和关系型数据库MySQL都可通过引入相关依赖并按照指定配置单独集成; mysql引入依赖: compile "org.springframework.boot:spring-boot-starter-web:1.5.18.RELEASE"compile "org.springframework.boot:spring-boot-start…

Python 检测网络是否连通

1 使用 urlib import urllib.requestdef test_internet_connection():url https://www.baidu.comtry:urllib.request.urlopen(url, timeout5)print("网络连接正常")except urllib.error.URLError as ex:print("网络连接异常&#xff1a;" str(ex))test_…

Django 路由配置(二)

一、路由 就是根据用户请求的URL链接来判断对应的出来程序&#xff0c;并返回处理结果&#xff0c;也是就是URL和django的视图建立映射关系. 二、Django请求页面的步骤 1、首先Django确定要使用的根URLconf模块&#xff0c;通过ROOT_URLCONF来设置&#xff0c;在settings.py配置…

光伏、储能双层优化配置接入配电网研究(附带Matlab代码)

由于能源的日益匮乏&#xff0c;电力需求的不断增长等&#xff0c;配电网中分布式能源渗透率不断提高&#xff0c;且逐渐向主动配电网方向发展。此外&#xff0c;需求响应(demand response&#xff0c;DR)的加入对配电网的规划运行也带来了新的因素。因此&#xff0c;如何综合考…
最新文章