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();

        }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM