zoukankan      html  css  js  c++  java
  • 一起学习ArcEngine(8)鹰眼

    ae的官方类库没有提供该控件,需要自己实现,不过也比较简单,原理或实现的思路是,另外增加一个axMapControl控件,把他的视图设为地图的全图范围,把当前地图的范围,在这个地图控件上用红色框画出来即可。

    首先新建一个用户控件,名称设为MapEagle,在控件上拖拽一个axmapcontrol控件,名称设为axMapEagle ,用来显示地图。

    接下来,增加一个自定义属性,用来和地图主窗口关联,使得axMapEagle 能获得当前地图的范围

       1:  private AxMapControl pMap;
       2:          
       3:          /// <summary>
       4:          /// 关联的地图控件
       5:          /// </summary>
       6:          public AxMapControl MapControl
       7:          {
       8:              set
       9:              {
      10:                  if (value != pMap) pMap = value;
      11:                  //this.axMapEagle.Extent = pMap.FullExtent;
      12:                  pMap.OnMapReplaced += new IMapControlEvents2_Ax_OnMapReplacedEventHandler(pMap_OnMapReplaced);
      13:                  pMap.OnExtentUpdated += new IMapControlEvents2_Ax_OnExtentUpdatedEventHandler(pMap_OnExtentUpdated);
      14:              }
      15:   
      16:          }

    主地图控件的OnMapReplaced事件,使得当主地图窗口重新加载时,刷新axMapEagle 的视图范围,实现代码如下

       1:    void pMap_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e)
       2:          {
       3:   
       4:              for (int i = 0; i <= pMap.LayerCount; i++)
       5:              {
       6:                  axMapEagle.AddLayer(pMap.get_Layer(i));
       7:              }
       8:              this.axMapEagle.Extent = pMap.FullExtent;
       9:   
      10:              IGraphicsContainer pGraphicsContainer = this.axMapEagle.Map as IGraphicsContainer;
      11:              IActiveView pActiveView = pGraphicsContainer as IActiveView;
      12:              pGraphicsContainer.DeleteAllElements();
      13:   
      14:              IElement pEle = Envelope2Element(pMap.Extent);
      15:              pGraphicsContainer.AddElement(pEle, 0);
      16:              pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
      17:          }

    该事件中,首先将主地图的图层都加载到axMapEagle 控件中,然后将试图设为全图,接下来删除窗口中的所有Element,再往后就是把主地图的视图范围,在axMapEagle 的视图上画出来,采用创建element的方法实现,方法Envelope2Element 实现将视图范围IEnvelope转化为一个element,把axMapEagle的地图设为图形容器,把创建好的element加进去,然后刷新视图即可。

    方法Envelope2Element 的实现过程,如下所示

       1:   private IElement Envelope2Element(IEnvelope env)
       2:          {
       3:              IRectangleElement pRectangleEle = new RectangleElementClass();
       4:              IElement pEle = pRectangleEle as IElement;
       5:              pEle.Geometry = env;
       6:   
       7:              IRgbColor pColor = new RgbColorClass();
       8:              pColor.RGB = 255;
       9:              pColor.Transparency = 255;
      10:   
      11:              ILineSymbol pOutline = new SimpleLineSymbolClass();
      12:              pOutline.Width = 1.5;
      13:              pOutline.Color = pColor;
      14:   
      15:              pColor = new RgbColorClass();
      16:              pColor.RGB = 255;
      17:              pColor.Transparency = 0;
      18:   
      19:              IFillSymbol pFillSymbol = new SimpleFillSymbolClass();
      20:              pFillSymbol.Color = pColor;
      21:              pFillSymbol.Outline = pOutline;
      22:   
      23:              IFillShapeElement pFillshapeEle = pEle as IFillShapeElement;
      24:              pFillshapeEle.Symbol = pFillSymbol;
      25:              return  pFillshapeEle as IElement;
      26:          }

    到这里已经实现一半了,剩下当主地图视图放大或缩小后,鹰眼地图上的范围标示随之变化没有实现了。也就是主地图的OnExtentUpdated方法,它的官方说明是这样 “Fires after the extent (visible bounds) of the MapControl is changed.”当地图控件的可视范围变化后触发,正是我们想要的。它的实现和加载时一样,同样将变化后的视图范围在地图上绘制就可以了,不用重新加载地图,具体代码如下

       1:          void pMap_OnExtentUpdated(object sender, IMapControlEvents2_OnExtentUpdatedEvent e)
       2:          {
                       //删除已添加的Element
       3:              IGraphicsContainer pGraphicsContainer = this.axMapEagle.Map as IGraphicsContainer;
       4:              IActiveView pActiveView = pGraphicsContainer as IActiveView;
       5:              pGraphicsContainer.DeleteAllElements();
       6:   
       7:              IElement pEle = Envelope2Element(e.newEnvelope as IEnvelope );
       8:              pGraphicsContainer.AddElement(pEle, 0);
       9:              pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
      10:          }
    工作已经完成90%了,呵呵,axMapEagle 控件都会适应主地图视图的变化,还缺的就是主地图视图要适应axMapEagle的视图变化。
    即,当在鹰眼视图上点击时,主地图也要能够移动到点击的位置,这样才是真正的方便。要实现这样的功能,就要用到地图控件
    的OnMouseDown事件,代码如下
       1:  private void axMapEagle_OnMouseDown(object sender, IMapControlEvents2_OnMouseDownEvent e)
       2:          {
       3:              IRubberBand pBand = new RubberEnvelopeClass();
       4:              IGeometry pGeometry = pBand.TrackNew(axMapEagle.ActiveView.ScreenDisplay, null);
       5:            
       6:              if (pGeometry.IsEmpty)
       7:              {
       8:                  IPoint pPt = new PointClass();
       9:                  pPt.PutCoords(e.mapX, e.mapY);
      10:                  //改变主控件的视图范围
      11:                  pMap.CenterAt(pPt);
      12:              }
      13:              else
      14:              {
      15:                  pMap.Extent = pGeometry.Envelope;
      16:                  pMap.ActiveView.Refresh();
      17:              }
      18:          }

    IRubberBand 接口的官方解释是”Provides access to members that control simple rubberbanding.”rubberbanding 翻译过来是‘橡皮带式生成线’;直译是提供控制简单橡皮带式生成线的权限,(英语水平太凹了,只能查字典直译了!)就是能够控制按下鼠标左键拉框时的框范围。该接口的TrackNew方法就是将拉框转换成一个地理要素,然后可以根据这个要素对地图范围进行设定。

    大功告成,主地图和鹰眼实现双向互动了!

  • 相关阅读:
    第一次参赛经历:ecfinal总结
    滑雪(dp或记忆化搜索)
    dp入门题(数塔)
    SQL语句:子查询
    【原创】SQL语句原理解析
    gitignore规则探究
    路径分隔符:正斜线/、反斜线、双反斜线\的区别
    高并发系统设计方法
    js变量作用域,变量提升和函数传参
    数据库设计:三范式
  • 原文地址:https://www.cnblogs.com/liuyh208/p/1576011.html
Copyright © 2011-2022 走看看