ArcEngine-长度量算

在使用ArcGIS的过程中,我们会发现在右上角有个长度量算的工具,对于随意在地图上选择的两点进行量算并给出实际距离。那么到底是怎么实现的呢,本文附上实现的源代码,有错误或者更好地优化的方案请进行纠正,努力才会让目标离我们更近些。

 //长度量算工具代码
        private IHookHelper m_hookHelper;
        private IGraphicsContainer pGraphicContainer;
        private IMap pMap;
        private IActiveView pActiveView;
        private IDisplayFeedback pDisplayFeedback;
        private IScreenDisplay pScreenDisplay = null;
        IPoint pPointStd;
        IPoint pPoint;
        IPoint pPointLast;
        IProximityOperator pProximity;
        public double measureDistance = 0;
        public double DistanceSegment = 0;
        INewLineFeedback pNewLineFeedback = null;
        public DistancePointsTool()
        {
            base.m_category="SpatailAnalyst";
            base.m_caption="长度量算";
            base.m_message="长度量算";
            base.m_toolTip="长度量算";
            base.m_name="长度量算";
        }
        public override void OnCreate(object hook)
        {
            if (m_hookHelper==null)
                m_hookHelper=new HookHelperClass();
            m_hookHelper.Hook=hook;
            pActiveView=m_hookHelper.ActiveView;
            pMap=pActiveView.FocusMap;
            pGraphicContainer=pMap as IGraphicsContainer;
            pDisplayFeedback=null;
            pScreenDisplay=pActiveView.ScreenDisplay;
        }
        //重载鼠标点击事件
        protected override void OnMouseDown(int Button,int shift,int X,int Y)

 {
    //产生一个当前点击的点对象
            if (Button==1)
            {
                //判断该点是否为第一个点
                if (pDisplayFeedback==null)
                {
                    pPointStd=new PointClass();
                    pPointStd.SpatialReference=pMap.SpatialReference;
                    pPointStd=pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);
                    pDisplayFeedback=new NewLineFeedbackClass();
                    pDisplayFeedback.Display=pScreenDisplay;
                    pNewLineFeedback=pDisplayFeedback as INewLineFeedback;
                    pNewLineFeedback.Start(pPointStd);
                    pPointLast=pPointStd;
                    pProximity=pPointStd as IProximityOperator;
                }
                else{
                    pNewLineFeedback=pDisplayFeedback as INewLineFeedback;
                    pNewLineFeedback.AddPoint(pPoint);
                    IProximityOperator pProximity=pPointLast as IProximityOperator;
                    DistanceSegment=pProximity.ReturnDistance(pPoint);
                    measureDistance+=pProximity.ReturnDistance(pPoint);
                    pPointLast =pPoint;
                }
            }
        }
        //重载鼠标移动事件
        public override void OnMouseMove(int Button,int shift,int X,int Y)
{
            pPoint =new PointClass();
            pPoint.SpatialReference=pMap.SpatialReference;
            pPoint=pActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);
            if(pNewLineFeedback!=null)
            {

                    pNewLineFeedback.MoveTo(pPoint);
                }
            }
        //重载鼠标双击事件,距离量测结束
        public override void onDblClick()
        {
            base.onDblClick();
            IGeometry pGeometry=null;
            string LengthUnits=null;
            if (pNewLineFeedback!=null)
            {
                pGeometry=pNewLineFeedback.Stop();
                pNewLineFeedback=null;
                IElement pElement=null;
                ISimpleLineSymbol pSimpleLineSymbol=new SimpleLineSymbolClass();
                pSimpleLineSymbol.Width=2;
                pSimpleLineSymbol.Style=esriSimpleLineStyle.esriSLSSolid;

                ISimpleFillSymbol pSimpleFillSymbol=new SimpleFillSymbolClass();
                pSimpleFillSymbol.Style=esriSimpleFillStyle.esriSFSSolid;
                pSimpleFillSymbol.Outline= pSimpleLineSymbol;
                ILineElement pLineElement=new LineElementClass();
                pLineElement.Symbol=pSimpleLineSymbol;
                pElement=pLineElement as IElement;
                pElement=pLineElement as IElement;
                pElement.Geometry=pGeometry;
                IGraphicsContainer pGraphicsContainer=pActiveView.FocusMap as IGraphicsContainer;
                pGraphicsContainer.AddElement(pElement,0);
                pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics,null,null);
                pGraphicsContainer.DeleteElement(pElement);
                MessageBox.Show("\n线段长度:"+DistanceSegment.ToString()+"\n总长度:"+measureDistance.ToString()+"\n地图单位:"+LengthUnits,"长度量算");
                measureDistance=0;
                DistanceSegment=0;
                pNewLineFeedback=null;
                pDisplayFeedback=null;
            }
        }
客户最近打电话过来,说我们的软件在距离的时候不能平移地图。我们的软件是使用ArcEngine来开发的,在网上输入关键字“arcengine 距离”,可以搜索到一大堆内容基本相似的文章或代码,基本上都是采用INewLineFeedback来实现的,我们的软件也是使用此种方法。方法大致如下:写一个距离工具,继承自BaseTool,在该类中使用INewLineFeedback动态绘制多段折线,最后转化为Element添加到地图上。如果要增加平移功能,我们仿造ArcMap使用鼠标中键平移,在OnMouseDown、OnMouseMove、OnMouseUp事件中增加判断鼠标中键的语句,然后分别使用PanStart、PanMoveTo、PanStop实现地图的平移。 此时,出现了一个新问题,一旦移动地图后,之前使用INewLineFeedback绘制的线完全乱了方寸,有一部分线丢失了。之后又发现一个更可笑的问题,在绘制的过程中,如果使用alt+tab键切换到其它窗口,然后再切换回地图窗口的时候,会多出一条线,INewLineFeedback把切换窗口前的鼠标位置记录了下来。 对于这个问题,我使用ArcMap的测工具检查了一下,发现不存在上述问题。但是INewLineFeedback为什么会产生这个bug,难道是本人的使用方法不对。在网上搜了一下其他类似代码进行测试,都存在这个bug。ArcEngine的SDK文档上也没有特别强调INewLineFeedback的使用细节。 本来打用gdi进行解决,最后发现INewLineFeedback有一个Refresh函数,那么应该在什么地方使用它呢?在ArcMapControl的诸多事件中,尝试了OnAfterDraw、OnAfterScreenDraw、OnViewRefresh等,发现OnAfterScreenDraw是OK的。具体是在OnAfterScreenDraw事件中使用Refresh函数刷新INewLineFeedback,完美解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值