ArcGIS Engine中的刷新与不同坐标间的相互转换

ArcGIS Engine中的视图(IActiveView)控制着主程序窗口,二维中的常用视图有Map(数据视图)和PageLayout(布局视图)。IActiveView.ScreenDisplay属性即IScreenDisplay接口用来控制屏幕上图形的显示。ScreenDisplay允许用户创建任意数量的缓存,图像不是直接绘制在屏幕上的,而是先绘制在缓存中,然后再将缓存绘制到屏幕上。当程序窗口需要重绘时,不是直接从数据库中获取数据,而是从缓存中获取,从而提高绘制的性能。

通常情况下,Map对象有三个缓存:一是为所有图层生成一个缓存;二是如果Map中存在注记和Graphics的话,为其生成一个缓存;三是如果Map中有要素选择集,也会为其生成一个缓存。不过单个图层也可以创建其专属的缓存,这时Map将为该图层创建一个独立的缓存,而其余的所有图层则放在一个缓存里。接下来就看一下ArcGIS Engine中的刷新方法,以Map为例。

一、ArcGIS Engine中的刷新方法主要有:

1, IActiveView.Refresh

全局刷新,即重绘地图中的所有内容,是效率最低的一种刷新方法。当数据量大时非常耗时。所以除非绝对必要,一般推荐使用IActiveView.PartialRefresh方法。当然如果是涉及全部显示范围的更新就需要使用Refresh,比如平移、缩放、全图等操作。

2, IActiveView.PartialRefresh

部分刷新,可以人为指定重绘地图中的部分内容,该方法效率高,推荐使用。下表说明了部分刷新的参数以及Map或PageLayout中刷新的内容:

ArcGIS Engine中的刷新与不同坐标间的相互转换_第1张图片

刷新所有图层使用:
activeView.PartialRefresh(esriViewGeography, null, null);

刷新单个图层使用:
activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, layer,null);

刷新单个图层中的某个区域使用:
activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, layer, envelope);

刷新图层中的选中要素使用:
activeView.PartialRefresh(esriViewDrawPhase.esriViewGeoSelection, null, null);

Tips: 测试只执行一次刷新即可,而ArcObjects帮助中说需要调用两次,一次在选择前,一次在选择后。

刷新整个Element图层或者label使用:
activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);

刷新一个Element使用:
activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, element, null);

刷新选中的Element使用:
activeView.PartialRefresh(esriViewDrawPhase.esriViewGraphicSelection, null, null);

3, IScreenDisplay.Invalidate

Invalidate方法允许刷新显示中的指定区域,该方法不推荐用户使用,因为需要手动控制绘图缓存,对用户来说该方法不是最优的,推荐使用PartialRefresh。使用方法可以参考ArcObjects帮助:How to add display caching

此外,当地图刷新时会触发IActiveViewEvents.AfterDraw事件,其esriViewDrawPhase参数会返回当前的DrawPhase,其绘图阶段先后依次是esriViewInitializedesriViewBackgroundesriViewGeographyesriViewGraphicsesriViewGeoSelectionesriViewForeground,通过刷新阶段的先后顺序可以实现自定义功能。

ArcGIS Engine中的刷新与不同坐标间的相互转换_第2张图片

二、不同坐标间的相互转换

坐标转换主要使用IDisplayTransformation接口,可以通过IScreenDisplay. DisplayTransformation属性获取。

MapControl下屏幕坐标与地理坐标的相互转换:

1, 屏幕坐标转为地理坐标

public IPoint GetMapCoordinatesFromScreenCoordinates(IPoint screenPoint, IActiveView activeView)
        {
            if (screenPoint == null || screenPoint.IsEmpty || activeView == null)
            {
                return null;
            }
            IScreenDisplay screenDisplay = activeView.ScreenDisplay;
            IDisplayTransformation displayTransformation = screenDisplay.DisplayTransformation;

            return displayTransformation.ToMapPoint((System.Int32)screenPoint.X, (System.Int32)screenPoint.Y);
        }

2, 地理坐标转为屏幕坐标

public IPoint GetScreenCoordinatesFromMapCoorindates(IPoint mapPoint, IActiveView activeView)
        {
            if (mapPoint == null || mapPoint.IsEmpty || activeView == null)
            {
                return null;
            }
            IScreenDisplay screenDisplay = activeView.ScreenDisplay;
            IDisplayTransformation displayTransformation = screenDisplay.DisplayTransformation;
            System.Int32 x;
            System.Int32 y;
            displayTransformation.FromMapPoint(mapPoint, out x, out y);
            IPoint returnPoint = new PointClass();
            returnPoint.PutCoords(x, y);
            return returnPoint;
        }

相较而言,PageLayout中页面坐标与地理坐标的转换就复杂一些,需要获取屏幕坐标作为中间变量:

PageLayoutControl页面坐标与地理坐标的相互转换:

1, 页面坐标到地理坐标的转换分两步:

(1)将IPageLayout转为IActiveView,IActiveView.ScreenDisplay.DisplayTransformation.FromMapPoint(); 将页面坐标转为屏幕坐标;

(2)将FocusMap转为IActiveView,IActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(); 将屏幕坐标转为地理坐标。

2, 地理坐标转换为页面坐标也是分两步:

(1)将FocusMap转为IActiveView,IActiveView.ScreenDisplay.DisplayTransformation.FromMapPoint();将地理坐标转为屏幕坐标;

(2)将IPageLayout转为IActiveView,IActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint();将屏幕坐标转为页面坐标。

此外,其IDisplayTransformation.FromPoints方法可以将point(1/72 inch) distance转为map distance;IDisplayTransformation.ToPoints方法可以将map distance转为point distance。

你可能感兴趣的:(ArcEngine)