zoukankan      html  css  js  c++  java
  • c#+ArcEngine93实现实时显示测距结果功能

    利用ArcEngine实现距离量测,面积量测的功能已很简单,相信众多的ArcGIS爱好者都能写. 但单纯的实现功能总觉得欠什么.本人喜欢改代码,喜欢优化代码,在原有的功能基础上总喜欢"润色",使之更好看.前一整子在玩skyline时看到 skyline 的测距功能能实时显示量测的距离,于是联想到之前自己用C#+ArcEngine 写的测距功能.何不也优化一下自己代码? 想到就做到.最近手有点痒,算练练手.
    废话少说,先附上效果图:


    说明:
    1.本功能的特点在于在量测的过称当中实时显示量测距离,并将结果实时显示在测距上方.在显示窗体上也显示量测的总距离.

    要点:
    1. INewLineFeedback 负责画线;
    2. 在OnMouseDown事件中计算量测距离,并向GraphicsContainer添加线和节点的Element;
    3.在OnMouseUp事件中实时计算距离随鼠标移动后产生的新距离.
    4. 将节点,量测值,线的element都分别存入到节点组和轨迹线组(IGroupElement),即用IGroupElement同一管理这些element; 最后将这些groupelement又添加到一个总的groupelement.这样做的目的在于好控制这些element,特别是启动新的量测或取消量测功能时可以控制这些element,而不必去用IGraphicsContainer.DeleteAllElements来清除这些element,使用IGraphicsContainer.DeleteAllElements会将所有的element删除.
    5. 量测值element 为ITextElement, 由于他停靠在轨迹线的上方,因此需要对量测值element进行一定角度的旋转,旋转角度由轨迹线的方向角决定.
    6. 绘制element之后的刷新问题也是比较重要的. 刷新范围一定要控制好,太小了,添加的element显示不出来,太大了,浪费. (实在不好控制就刷新整个extent吧,呵呵)

    核心代码如下:
    1. TrackLine类

    TrackLine

    //=================================功能测距==========================
    //描述:实时显示测量距离,节点位置,总长度
    //编程: Jin               开发时间:2009.8.10-2009.8.11
    //特点:实时计算量测距离.
    //缺点: 由于采用element做为显示内容,地图进行放大缩小操作后并不能很好
    //      控制量测值element和轨迹线element之间的距离间隔.
    //===================================================================

    using System;
    using System.Drawing;
    using System.Runtime.InteropServices;
    using ESRI.ArcGIS.ADF.BaseClasses;
    using ESRI.ArcGIS.ADF.CATIDs;
    using ESRI.ArcGIS.Controls;
    using ESRI.ArcGIS.Carto;
    using ESRI.ArcGIS.Geodatabase;
    using ESRI.ArcGIS.Display;
    using ESRI.ArcGIS.Geometry;
    using System.Windows.Forms;

    namespace MhGis.GisTool.Pb_Toolbar
    {
        class TrackLine : BaseTool
        {
            private IHookHelper m_hookHelper = null;
            private INewLineFeedback m_NewLineFeedback = null;
            private IPointCollection m_ptColl; //记录节点

            private MeasureMsgInfo _MsgInfo = null;
            private IPolyline m_TraceLine = null; //完整的轨迹线
            //
            private IGroupElement m_Elements = null; //用于保存包含此功能产生的所有Element
            private IGroupElement m_TraceElement = null; //测距轨迹线
            private IGroupElement m_VertexElement = null; //结点
            private IGroupElement m_LabelElement = null; // 距离标记

            public TrackLine()
            {
                //
                // TODO: Define values for the public properties
                //
                base.m_category = ""; //localizable text
                base.m_caption = "";  //localizable text
                base.m_message = "This should work in ArcMap/MapControl/PageLayoutControl";  //localizable text
                base.m_toolTip = "";  //localizable text
                base.m_name = "";   //unique id, non-localizable (e.g. "MyCategory_MyTool")
                try
                {
                    //
                    // TODO: change resource name if necessary
                    //
                    string bitmapResourceName = GetType().Name + ".bmp";
                    base.m_bitmap = new Bitmap(GetType(), bitmapResourceName);
                    base.m_cursor = new System.Windows.Forms.Cursor(GetType(), GetType().Name + ".cur");
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap");
                }
            }

            public MeasureMsgInfo MsgInfo
            {
                set
                {
                    _MsgInfo = value;
                    _MsgInfo.FormClosing += new FormClosingEventHandler(msgInfo_FromClosing);
                }
            }

            #region Overriden Class Methods

            /// <summary>
            /// Occurs when this tool is created
            /// </summary>
            /// <param name="hook">Instance of the application</param>
            public override void OnCreate(object hook)
            {
                try
                {
                    m_hookHelper = new HookHelperClass();
                    m_hookHelper.Hook = hook;
                    if (m_hookHelper.ActiveView == null)
                    {
                        m_hookHelper = null;
                    }
                }
                catch
                {
                    m_hookHelper = null;
                }

                if (m_hookHelper == null)
                    base.m_enabled = false;
                else
                    base.m_enabled = true;


                // TODO:  Add other initialization code
            }
            void Init()
            {
                //初始化
                m_Elements = new GroupElementClass();
                m_TraceElement = new GroupElementClass();
                m_VertexElement = new GroupElementClass();
                m_LabelElement = new GroupElementClass();

                //初始化,并添加到GraphicsContainer
                IGraphicsContainer g = m_hookHelper.ActiveView as IGraphicsContainer;
                g.AddElement(m_Elements as IElement, 0);
                g.AddElement(m_TraceElement as IElement, 0);
                g.AddElement(m_VertexElement as IElement, 0);
                g.AddElement(m_LabelElement as IElement, 0);

                //添加到m_Elements中
                g.MoveElementToGroup(m_VertexElement as IElement, m_Elements);
                g.MoveElementToGroup(m_LabelElement as IElement, m_Elements);
                g.MoveElementToGroup(m_TraceElement as IElement, m_Elements);
            }
            /// <summary>
            /// Occurs when this tool is clicked
            /// </summary>
            public override void OnClick()
            {
                Init();
            }

            void msgInfo_FromClosing(object sender, FormClosingEventArgs e)
            {
                DeleteAllElements();
                _MsgInfo = null;

                //throw new Exception("The method or operation is not implemented.");
            }
            public override void OnMouseDown(int Button, int Shift, int X, int Y)
            {
                if (Button == 2)
                    return;
                IPoint pt = m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y);
                IGraphicsContainer g = m_hookHelper.ActiveView.GraphicsContainer;
                IEnvelope pEnvBounds = null;

                //获取上一次轨迹线的范围,以便确定刷新范围
                try
                {
                    if (m_TraceLine != null)
                    {
                        m_TraceLine.QueryEnvelope(pEnvBounds);
                        pEnvBounds.Expand(4, 4, true); //矩形框向四周扩大4倍(大于2倍就行),目的是为了保证有充足的刷新区域
                    }
                    else
                        pEnvBounds = m_hookHelper.ActiveView.Extent;
                }
                catch
                {
                    pEnvBounds = m_hookHelper.ActiveView.Extent;
                }

                #region 启动画线
                if (m_NewLineFeedback == null)
                {

                    //移除element
                    RemoveElements();
                    //刷新
                    m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
                    Application.DoEvents();

                    m_NewLineFeedback = new NewLineFeedbackClass();
                    m_NewLineFeedback.Display = m_hookHelper.ActiveView.ScreenDisplay;
                    //必须先得到symbol,后设置symbol
                    ISimpleLineSymbol simpleLineSymbol = m_NewLineFeedback.Symbol as ISimpleLineSymbol;
                    simpleLineSymbol.Style = esriSimpleLineStyle.esriSLSDot;
                    simpleLineSymbol.Width = 1;
                    simpleLineSymbol.Color = TransColorToAEColor(Color.Blue);

                    m_NewLineFeedback.Start(pt);
                }
                else
                {
                    m_NewLineFeedback.AddPoint(pt);
                }

                if (m_ptColl == null)
                {
                    m_ptColl = new PolylineClass();
                }
                //记录节点
                object obj = Type.Missing;
                m_ptColl.AddPoint(pt, ref obj, ref obj);

                #endregion

                #region 绘制结点

                try
                {
                    IElement vertexElement = CreateElement(pt);
                    //
                    g = m_hookHelper.ActiveView as IGraphicsContainer;

                    //g.AddElement(vertexElement, 0);
                    //g.MoveElementToGroup(vertexElement, m_VertexElement);

                    m_VertexElement.AddElement(vertexElement);
                    //刷新
                    m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, vertexElement, pEnvBounds);

                }
                catch
                { }
                #endregion

                try
                {
                    if (m_ptColl.PointCount >= 2)
                    {
                        IPoint fromPt = m_ptColl.get_Point(m_ptColl.PointCount - 2); //倒数第二个点
                        IPoint toPt = m_ptColl.get_Point(m_ptColl.PointCount - 1); //最后第一个点
                        ILine line = new LineClass();
                        line.PutCoords(fromPt, toPt);

                        #region 绘制轨迹线

                        try
                        {
                            object missing = Type.Missing;
                            ISegmentCollection segColl = new PolylineClass();
                            segColl.AddSegment(line as ISegment, ref missing, ref missing);
                            IElement traceElement = CreateElement(segColl as IPolyline);
                            //
                            g = m_hookHelper.ActiveView as IGraphicsContainer;

                            //g.AddElement(traceElement, 0);
                            //g.MoveElementToGroup(traceElement, m_TraceElement);

                            m_TraceElement.AddElement(traceElement);

                            m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, traceElement, pEnvBounds);

                        }
                        catch
                        { }
                        #endregion

                        #region 计算单线的长度,并将结果显示在单线中点偏上上面
                        try
                        {
                            double angle = line.Angle;
                            if ((angle > (Math.PI / 2) && angle < (Math.PI)) || (angle > -Math.PI && angle < -(Math.PI / 2))) // 大于90度小于等于180
                                angle += Math.PI;

                            //标注点Y值偏移量
                            double d_OffsetY = m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.FromPoints(9);

                            //标注点

                            double d_CenterX = (fromPt.X + toPt.X) / 2;
                            double d_CenterY = (fromPt.Y + toPt.Y) / 2 + d_OffsetY; //向上偏移

                            IPoint labelPt = new PointClass();
                            labelPt.PutCoords(d_CenterX, d_CenterY);


                            ITextElement txtElement = CreateTextElement(line.Length.ToString("0.00"));

                            IElement labelelement = txtElement as IElement;
                            labelelement.Geometry = labelPt;
                            object oElement = (object)labelelement;

                            //根据角度旋转
                            TransformByRotate(ref oElement, labelPt, angle);

                            ////添加到GraphicsContainer
                            //g.AddElement(labelelement, 0);

                            ////移到m_LabelElement组中
                            //g.MoveElementToGroup(labelelement, m_LabelElement);

                            //添加到组
                            m_LabelElement.AddElement(labelelement);

                            //刷新

                            m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, labelelement, pEnvBounds);
                        }
                        catch
                        { }
                        #endregion
                    }


                }
                catch
                { }

            }

            public override void OnMouseMove(int Button, int Shift, int X, int Y)
            {
                if (m_NewLineFeedback == null)
                    return;
                IPoint pt = m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X, Y);

                m_NewLineFeedback.MoveTo(pt);

                if (m_ptColl.PointCount == 0)
                    return;
                double d_Total = 0;
                double d_segment = 0;

                IPoint lastPt = m_ptColl.get_Point(m_ptColl.PointCount - 1);
                ILine line = new LineClass();
                line.PutCoords(lastPt, pt);
                //节距离
                d_segment = line.Length;
                _MsgInfo.Segment = d_segment;
                try
                {
                    IPolyline polyline = m_ptColl as IPolyline;
                    if (polyline.IsEmpty)
                    {

                        d_Total = d_segment;
                    }
                    else
                    {
                        d_Total = polyline.Length + d_segment;
                    }

                }
                catch
                {

                }
                //赋值给总长度
                _MsgInfo.Total = d_Total;
            }

            public override void OnDblClick()
            {
                if (m_NewLineFeedback == null)
                    return;

                //绘制线与多边形几何图形时,双击结束绘制

                try
                {
                    m_TraceLine = m_NewLineFeedback.Stop();
                    if (m_TraceLine == null)
                        return;
                }
                catch
                { }
                finally
                {
                    Recycle();
                }
            }
            #endregion

            //回收
            public void Recycle()
            {
                m_NewLineFeedback = null;
                m_ptColl.RemovePoints(0, m_ptColl.PointCount);
                m_ptColl = null;
                m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, m_hookHelper.ActiveView.Extent);
            }

            /// <summary>
            /// 从组中删除所有元素
            /// </summary>
            /// <param name="groupElement"></param>
            void RemoveElementFromGroupElement(IGroupElement groupElement)
            {
                if (groupElement == null || groupElement.ElementCount == 0)
                    return;
                try
                {
                    IGraphicsContainer g = m_hookHelper.ActiveView.GraphicsContainer;
                    for (int index = 0; index < groupElement.ElementCount; index++)
                    {
                        IElement tmp_Ele = groupElement.get_Element(index);
                        if (tmp_Ele is IGroupElement)
                            RemoveElementFromGroupElement(tmp_Ele as IGroupElement);
                        else
                        {
                            try
                            {
                                groupElement.DeleteElement(tmp_Ele);
                            }
                            catch
                            {

                            }
                            finally
                            {
                                tmp_Ele = null;
                            }
                        }
                    }
                    //groupElement.ClearElements();
                }
                catch
                { }
                finally
                {
                    //刷新
                    IEnvelope pEnvBounds = null;

                    //获取上一次轨迹线的范围,以便确定刷新范围
                    try
                    {
                        if (m_TraceLine != null)
                        {
                            m_TraceLine.QueryEnvelope(pEnvBounds);
                            pEnvBounds.Expand(4, 4, true); //矩形框向四周扩大4倍(大于2倍就行),目的是为了保证有充足的刷新区域
                        }
                        else
                            pEnvBounds = m_hookHelper.ActiveView.Extent;
                    }
                    catch
                    {
                        pEnvBounds = m_hookHelper.ActiveView.Extent;
                    }
                    m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, pEnvBounds);
                }
            }
            /// <summary>
            /// 移除节点,标注和轨迹线Element
            /// </summary>
            void RemoveElements()
            {
                try
                {

                    //刷新一次
                    m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, m_hookHelper.ActiveView.Extent);
                    IGraphicsContainer g = m_hookHelper.ActiveView.GraphicsContainer;
                    #region 1-new
                    //RemoveElementFromGroupElement(m_Elements);
                    #endregion
                    #region 2
                    m_LabelElement.ClearElements();
                    m_VertexElement.ClearElements();
                    m_TraceElement.ClearElements();
                    #endregion
                }
                catch
                {

                }
                finally
                {

                    //刷新一次
                    m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, m_hookHelper.ActiveView.Extent);
                }
            }
            /// <summary>
            /// 删除所有与此相关的元素
            /// </summary>
            public void DeleteAllElements()
            {
                //m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
                IGraphicsContainer g = m_hookHelper.ActiveView.GraphicsContainer;

                RemoveElementFromGroupElement(m_Elements);
                try
                {
                    g.DeleteElement(m_Elements as IElement);
                }
                catch
                { }
                finally
                {
                    m_TraceElement = null;

                    m_LabelElement = null;
                    m_VertexElement = null;
                    m_Elements = null;
                    //最后再刷新一次
                    m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
                }
            }

            /// <summary>
            /// 将系统颜色转换为IColor
            /// </summary>
            /// <param name="color"></param>
            /// <returns></returns>
            ESRI.ArcGIS.Display.IColor TransColorToAEColor(Color color)
            {
                IRgbColor rgb = new RgbColorClass();
                rgb.RGB = color.R + color.G * 256 + color.B * 65536;
                return rgb as IColor;
            }

            /// <summary>
            /// 按指定的角度旋转
            /// </summary>
            /// <param name="obj"></param>
            /// <param name="originPt"></param>
            /// <param name="rotate"></param>
            void TransformByRotate(ref object obj, IPoint originPt, double rotate)
            {
                if (obj == null && originPt == null)
                    return;
                try
                {
                    ITransform2D transform2D = obj as ITransform2D;
                    if (transform2D == null)
                        return;
                    transform2D.Rotate(originPt, rotate);

                }
                catch
                { }
            }

            #region 创建Element
            /// <summary>
            /// 创建一个TextElement
            /// </summary>
            /// <param name="text"></param>
            /// <returns></returns>
            ITextElement CreateTextElement(string text)
            {
                //创建一个TextSymbol
                ITextSymbol txtSymbol = new TextSymbolClass();

                //设置字体
                Font dispFont = new Font("Arial", 10, FontStyle.Regular);
                txtSymbol.Font = (stdole.IFontDisp)ESRI.ArcGIS.ADF.COMSupport.OLE.GetIFontDispFromFont(dispFont);

                //设置属性
                txtSymbol.Color = TransColorToAEColor(Color.Red); //颜色

                //创建一个TextElement
                ITextElement txtElement = new TextElementClass();
                txtElement.Symbol = txtSymbol;
                txtElement.Text = text;

                return txtElement;
            }

            /// <summary>
            /// 绘制几何图形
            /// </summary>
            /// <param name="geoType"></param>
            /// <param name="geometry"></param>
            /// <returns></returns>
            ESRI.ArcGIS.Carto.IElement CreateElement(ESRI.ArcGIS.Geometry.IGeometry geometry)
            {
                IElement element = null;
                try
                {
                    switch (geometry.GeometryType)
                    {
                        case esriGeometryType.esriGeometryPolyline://Polyline线
                            ISimpleLineSymbol simpleLineSymbol = m_NewLineFeedback.Symbol as ISimpleLineSymbol;

                            ILineElement lineElement = new LineElementClass();
                            lineElement.Symbol = simpleLineSymbol as ILineSymbol;
                            element = lineElement as IElement;
                            element.Geometry = geometry;
                            break;
                        case esriGeometryType.esriGeometryPoint:
                            //设置结点符号
                            IRgbColor pRGB = new RgbColorClass();
                            pRGB.Red = 255;
                            pRGB.Green = 0;
                            pRGB.Blue = 0;

                            ISimpleMarkerSymbol pSimpleMarkSymbol = new SimpleMarkerSymbolClass();
                            pSimpleMarkSymbol.Color = pRGB as IColor;
                            pSimpleMarkSymbol.Size = 2;
                            pSimpleMarkSymbol.Style = esriSimpleMarkerStyle.esriSMSSquare;

                            IMarkerElement pMarkerElement = new MarkerElementClass();
                            pMarkerElement.Symbol = pSimpleMarkSymbol as IMarkerSymbol;
                            element = pMarkerElement as IElement;
                            element.Geometry = geometry as IGeometry;
                            break;
                    }
                }
                catch
                { }
                return element;
            }
            #endregion
        }
    }
    来自:http://www.cnblogs.com/JinDin/archive/2009/09/02/1543438.html


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yanleigis/archive/2009/11/05/4770250.aspx

  • 相关阅读:
    MySQL视图和存储过程
    MySQL数据操作
    Pair RDD编程
    HDFS组成架构和读写数据流程
    RDD编程
    MySQL数据查询和函数
    数据库学习(二)
    玩爆你的手机联系人--T9搜索(一)
    POJ3259 Wormholes 【Bellmanford推断是否存在负回路】
    Java 小技巧和在Java避免NullPonintException的最佳方法(翻译)
  • 原文地址:https://www.cnblogs.com/linghe/p/1635475.html
Copyright © 2011-2022 走看看