zoukankan      html  css  js  c++  java
  • ArcGIS Engine开发之地图浏览

    地图的浏览功能包括缩放、移动、量测旋转等。

    1、放大与缩小

    无论是放大还是缩小,都是通过改变MapControl中当前视图的范围Extent属性来实现的,主要用到包络线(Envelope)类。

    包络线是一个矩形区域,它是一个几何形体的最小包络边框,每一个Geometry对象都拥有一个包络线对象。包络线通过它的最大与最小X,Y坐标来定义一个矩形形状,因此包络线对象相对于它的空间参考而言总是直角。IEnvelop接口是Expand方法的用于缩放包络线的范围,进而产生一个新的包络线对象,从而实现放大和缩放。

    实现的思路:

    1)固定比例尺放大是以当前视图的中心点为缩放中心对地图进行放大。在放大的操作中记下MapControl当前的Extent。

    2)把该范围缩小

    3)设置MapControl的extent 属性为缩小后的范围,由于MapControl本身的尺寸没有变化,这样就实现了放大的效果。

    Expend函数的参数说明

    参数 描述
    dx,dy 必须,分别表示x,y轴方向上的增量
    asRatio 表示是否按比例进行改变,当为false时,扩张以加法走形式进行,Xmin=Xmin-dx,Ymin=Ymin-dy,Xmax=Xmax+dx,Ymax=Ymax+dy,当为true时,扩张以乘法形式进行。无论如何中心位置不会改变

    放大代码:

    IEnvelope pEnvelop = mainMapControl.Extent;
                pEnvelop.Expand(0.5,0.5,true );//设置放大的倍数
                mainMapControl.Extent = pEnvelop;
                mainMapControl.ActiveView.Refresh();

    缩小代码:

    IActiveView pActiveView = mainMapControl.ActiveView;
                IPoint centPoint = new PointClass();
                centPoint.PutCoords((pActiveView .Extent.XMin+pActiveView .Extent .XMax )/2,(pActiveView.Extent .YMax+pActiveView .Extent.YMin )/2);
                IEnvelope pEnvelop=pActiveView .Extent ;
                pEnvelop .Expand (1.5,1.5,true);//与放大的区别在于expand的参数不同
                pActiveView .Extent .CenterAt (centPoint );
                pActiveView .Extent=pEnvelop ;
                pActiveView .Refresh ();

    2、拉框放大与缩小、漫游与全图

    拉框放大及时用鼠标拖出来的矩形放大到数据视图额整个范围。

    拉框放大缩小用到的TrackRectangle方法。该方法在MapControl的OnMouseDown事件中触发,会在MapControl上生成一个由用户鼠标轨迹定义的矩形橡皮筋。该方法返回一个IPolygon接口的几何对象。在方法的执行过程中,MapControl的OnMouseDown事件被触发,这时还没有发生MapControl的onMouseUp事件,所以追踪时按下ESC键可以取消TrackRectangle的操作。

    1)拉框放大的思路

    使用Envelope获取鼠标拖出的矩形橡皮筋范围值赋给当前的视图,若矩形的范围为空则返回。

     mainMapControl.CurrentTool = null;
                pMouseOperate = "ZoomIn";
                mainMapControl.MousePointer = esriControlsMousePointer.esriPointerZoomIn;

    2)拉框缩小

     mainMapControl.CurrentTool = null;
                pMouseOperate = "ZoomOut";
                mainMapControl.MousePointer = esriControlsMousePointer.esriPointerZoomOut;

    3)漫游

     mainMapControl.CurrentTool = null;
                pMouseOperate = "Pan";
                mainMapControl.MousePointer = esriControlsMousePointer.esriPointerPan;

    4)调用MapControl MouseDown事件

     private void mainMapControl_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IMapControlEvents2_OnMouseDownEvent e)
            {
                //将屏幕的坐标转换为地图的坐标点
    
                IPoint pPoint = (mainMapControl.Map as IActiveView).ScreenDisplay.DisplayTransformation.ToMapPoint(e.x, e.y);
                if (e.button == 1)
                {//表示鼠标的左键
                    IActiveView pActiveView = mainMapControl.ActiveView;
                    IEnvelope pEnvelop = new EnvelopeClass();
                    switch (pMouseOperate)
                    {
                        #region
                        //拉框放大
                        case "ZoomIn":
                            pEnvelop = mainMapControl.TrackRectangle();
                            //如果拉框的范围为空则返回
                            if (pEnvelop == null || pEnvelop.IsEmpty || pEnvelop.Height == 0 || pEnvelop.Width == 0)
                            {
                                return;
                            }
                            //如果有拉框范围则放大到拉框范围
                            pActiveView.Extent = pEnvelop;
                            pActiveView.Refresh();
                            break;
                        #endregion
                        #region
                        ///拉框缩小
                        case "ZoomOut":
                            pEnvelop = mainMapControl.TrackRectangle();
                            //如果拉框范围为空则退出
                            if (pEnvelop == null || pEnvelop.IsEmpty || pEnvelop.Height == 0 || pEnvelop.Width == 0)
                            {
                                return;
                            }
                            else  //如果有拉框范围、则以拉框范围为中心,缩小倍数为当前视图范围/拉框范围
                            {
                                double dWidth = pActiveView.Extent.Width * pActiveView.Extent.Width / pEnvelop.Width;
                                double dHeight = pActiveView.Extent.Height * pActiveView.Extent.Height / pEnvelop.Height;
                                double dXmin = pActiveView.Extent.MMin - ((pEnvelop.MMin - pActiveView.Extent.MMin) * pActiveView.Extent.Width / pEnvelop.Width);
                                double dYmin = pActiveView.Extent.YMin - ((pEnvelop.YMin - pActiveView.Extent.YMin) * pActiveView.Extent.Height / pEnvelop.Height);
                                double dXmax = dXmin + dWidth;
                                double dYmax = dYmin + dHeight;
                                pEnvelop.PutCoords(dXmin, dYmin, dXmax, dYmax);
                            }
                            pActiveView.Extent = pEnvelop;
                            pActiveView.Refresh();
                            break;
                        #endregion
                        #region      ///漫游
                        case "Pan":
                            mainMapControl.Pan();
                            break;
                        #endregion
                        #region
                        case "Null":
                            mainMapControl.CurrentTool = null;
                            break;
                        #endregion
                    }
                }

    3、历史视图的切换

    历史视图切换就是快速地在前视图和后视图之间快速的切换,上一视图命令可以快速地回退到最后一次地图操作以前的地图范围,下一视图命令和上一视图恰好相反。实现该功能需要用到IExtentStack接口,即堆扩展接口。该接口提供了访问控制范围内堆栈员的方法。主要的接口方法如下:

    方法 描述
    Canredo 是否存在一个能够重做的视图
    CanUndo 是否存在一个能够撤销的视图
    Redo 重做到下一视图范围
    Undo 撤销到上一视图

    实现思路:

    1)新建一个ExtentStack对象来存储历史视图,并赋予视图窗口中的视图堆。

    2)判断是否能回到前一视图或后一视图,如果能,则视图窗口中视图中视图返回到上一视图和下一视图。

    3)返回前一视图命令的实现。

     /// <summary>
            /// 返回前一视图操作
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            /// 定义全局变量
            IExtentStack pExtentStack;
            private void btnUndo_ItemClick(object sender, ItemClickEventArgs e)
            {
                 pExtentStack = mainMapControl.ActiveView.ExtentStack;
                //判断是否可以回到前一视图,第一个视图没有前视图
                if (pExtentStack.CanRedo())
                {
                    pExtentStack.Undo();
                    btnBackView.Enabled = true;//后一视图的按钮可以使用
                    if (!pExtentStack.CanRedo())
                    {
                        btnForWardView.Enabled = false;//前一视图的按钮不可以使用
                    }
                }
                mainMapControl.ActiveView.Refresh();
            }
            /// <summary>
            /// 返回到前一视图的操作
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void btnRedo_ItemClick(object sender, ItemClickEventArgs e)
            {
                 pExtentStack = mainMapControl.ActiveView.ExtentStack;
                //判断是否可以回到后一视图,最后一个视图没有后一视图
                if (pExtentStack.CanRedo())
                {
                    pExtentStack.Redo();
                    btnForWardView.Enabled = true;//前一视图按钮可以使用
    
                    if (!pExtentStack.CanRedo())
                    {
                        btnBackView.Enabled = false;
                    }
                }
                mainMapControl.ActiveView.Refresh();
    
            }
  • 相关阅读:
    导航控制器的出栈
    UIPickView的基本使用
    多控制器
    通过Xib加载控制器的View
    从StoryBoard加载控制器
    模仿UIApplication单例
    LaunchScreen原理
    UIWindow
    指定初始化的运用
    零长度数组在内核中的运用
  • 原文地址:https://www.cnblogs.com/dongteng/p/5883502.html
Copyright © 2011-2022 走看看