解决有关GIS点选重叠点的问题

        当GIS地图中出现点要素比较集中的情况时,进行点选如果不加以设置调整的话就会出现点选不上要素。目前有如下两种设置方式,都是对选中要素进行范围扩大,但是差别很大,现在以极端方式来验证这两种方式的效果。

        我们先来看一下将要操作的地图底图效果:

        这是一个管网图层+管网附属建筑物图层,在截图中不难看到很多附属建筑物都靠近在一起,而且图层信息比较复杂,若要实现点选,默认的点选方法如下:     

          IdentifyTask IdentifyTask = new IdentifyTask(Config.MapServiceAddr);  //实例化Task对象
            IdentifyTask.ExecuteCompleted += new EventHandler<IdentifyEventArgs>(IdentifyTask_ExecuteCompleted);  //注册Task完成监听事件

            ESRI.ArcGIS.Client.Tasks.IdentifyParameters identyfyParams = new IdentifyParameters();  //实例化Task参数对象
            identyfyParams.Geometry = e.MapPoint;  //待识别的几何图形,常用的有点选,矩形选择,多边形选择等
            identyfyParams.Height = (int)MyMap.ActualHeight;  //当前浏览器的地图高度
            identyfyParams.Width = (int)MyMap.ActualWidth;   //当前浏览器的地图宽度
            identyfyParams.MapExtent = MyMap.Extent;  //当前地图的范围
            identyfyParams.SpatialReference = MyMap.SpatialReference;  //定义输入和输出几何图形,以及mapExtent的空间参考
            identyfyParams.LayerOption = LayerOption.all;  //定义查询图层
            /**
             * 固定查询第一个图层,即高速公路,可以使用下拉框进行选择其它图层(需要遍历所有图层),查询多个图层
             *      identifyParams.layerOption=IdentifyParameters.LAYER_OPTION_VISIBLE;  所有可见图层
             *                                                    LAYER_OPTION_ALL;      所有图层
             *                                                    LAYER_OPTION_TOP;      最上层
             * */
            foreach (int intIndex in lstLayerIndex)
            {
                identyfyParams.LayerIds.Add(intIndex);
            }
            IdentifyTask.ExecuteAsync(identyfyParams);  //为必要属性赋值,发送请求
             IdentifyTask.Failed += new EventHandler<TaskFailedEventArgs>(IdentifyTask_Failed);

        说明:紫色部分看似是重复的对查询图层进行了定义,但当Arcgis10.1运行在Windows2012上的时候,单独使用LayerOptionidentyfyParams.LayerIds.Add都会有失效率,所以这里才把两种方式都添加进来(这只是我遇到的情况,不知道其他大侠是否也有类似的经历)

        这样的方式就很难命中选择的要素。于是我们想到的是扩大点的命中范围,来增强它的命中率。

        方式一:  获取选中点的四角坐标范围,然后将其进行一定程度的范围扩大,然后将Geometry指向扩大后的四角坐标范围。这里的范围值是对真实数据的地理坐标范围进行扩大或缩小。

          //获取点选的点对象
            ESRI.ArcGIS.Client.Geometry.MapPoint clickPoint = e.MapPoint;
          //为了让点选范围扩大,更容易点一些
            ESRI.ArcGIS.Client.Geometry.Envelope test = clickPoint.Extent;
           test.XMax += 50;
           test.XMin -= 50;
           test.YMax += 50;
           test.YMin -= 50;
           MousePoint = clickPoint;

          IdentifyTask IdentifyTask = new IdentifyTask(Config.MapServiceAddr);  //实例化Task对象
            IdentifyTask.ExecuteCompleted += new EventHandler<IdentifyEventArgs>(IdentifyTask_ExecuteCompleted);  //注册Task完成监听事件

            ESRI.ArcGIS.Client.Tasks.IdentifyParameters identyfyParams = new IdentifyParameters();  //实例化Task参数对象
            identyfyParams.Geometry = test;  //待识别的几何图形,常用的有点选,矩形选择,多边形选择等
            identyfyParams.Height = (int)MyMap.ActualHeight;  //当前浏览器的地图高度
            identyfyParams.Width = (int)MyMap.ActualWidth;   //当前浏览器的地图宽度
            identyfyParams.MapExtent = MyMap.Extent;  //当前地图的范围
            identyfyParams.SpatialReference = MyMap.SpatialReference;  //定义输入和输出几何图形,以及mapExtent的空间参考
            identyfyParams.LayerOption = LayerOption.all;  //定义查询图层
            /**
             * 固定查询第一个图层,即高速公路,可以使用下拉框进行选择其它图层(需要遍历所有图层),查询多个图层
             *      identifyParams.layerOption=IdentifyParameters.LAYER_OPTION_VISIBLE;  所有可见图层
             *                                                    LAYER_OPTION_ALL;      所有图层
             *                                                    LAYER_OPTION_TOP;      最上层
             * */
            foreach (int intIndex in lstLayerIndex)
            {
                identyfyParams.LayerIds.Add(intIndex);
            }
            IdentifyTask.ExecuteAsync(identyfyParams);  //为必要属性赋值,发送请求
            IdentifyTask.Failed += new EventHandler<TaskFailedEventArgs>(IdentifyTask_Failed);

        通常而言,这种方式也没有什么不妥,但对于我么截图的图层进行点选就会出现问题。因为是对数据的真实坐标值进行范围的扩大或缩小,那么即使重合比较严重的两个点进行无限放大,该放大也只是比例尺无限放大,变化的是屏幕像素值而不是地理坐标值,这时对其中一个点进行点选,最后还是会将两个点的信息全部显示出来。如下左图:

        方式二:获取选中点,并且设置容差参数值(即以选中要素为中心,设置值为半径的屏幕像素范围内的要素将被视为选中要素)。

          IdentifyTask IdentifyTask = new IdentifyTask(Config.MapServiceAddr);  //实例化Task对象
            IdentifyTask.ExecuteCompleted += new EventHandler<IdentifyEventArgs>(IdentifyTask_ExecuteCompleted);  //注册Task完成监听事件

            ESRI.ArcGIS.Client.Tasks.IdentifyParameters identyfyParams = new IdentifyParameters();  //实例化Task参数对象
            identyfyParams.Tolerance = 10;  //容差半径
            identyfyParams.Geometry = e.MapPoint;  //待识别的几何图形,常用的有点选,矩形选择,多边形选择等
            identyfyParams.Height = (int)MyMap.ActualHeight;  //当前浏览器的地图高度
            identyfyParams.Width = (int)MyMap.ActualWidth;   //当前浏览器的地图宽度
            identyfyParams.MapExtent = MyMap.Extent;  //当前地图的范围
            identyfyParams.SpatialReference = MyMap.SpatialReference;  //定义输入和输出几何图形,以及mapExtent的空间参考
            identyfyParams.LayerOption = LayerOption.all;  //定义查询图层
            /**
             * 固定查询第一个图层,即高速公路,可以使用下拉框进行选择其它图层(需要遍历所有图层),查询多个图层
             *      identifyParams.layerOption=IdentifyParameters.LAYER_OPTION_VISIBLE;  所有可见图层
             *                                                    LAYER_OPTION_ALL;      所有图层
             *                                                    LAYER_OPTION_TOP;      最上层
             * */
            foreach (int intIndex in lstLayerIndex)
            {
                identyfyParams.LayerIds.Add(intIndex);
            }
            IdentifyTask.ExecuteAsync(identyfyParams);  //为必要属性赋值,发送请求
            IdentifyTask.Failed += new EventHandler<TaskFailedEventArgs>(IdentifyTask_Failed);

        这种方式的效果就很明显了,选中的要素是同一个,不需要放大那么大的比例,就可以直接获取都想要的附属建筑物的要素信息了。如下左图:


        通过上述说明,两种方法的精准度一目了然,当然对于要素信息没有如此密集程度时,也可以采用第一种方式。

 

        如果以上两种方式都不可以,也有一种相对粗暴的方式,就是在返回结果中,只选取第一个返回值。

转载自:https://blog.csdn.net/daidailiuhome/article/details/12165091

You may also like...