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类



//=================================功能测距==========================
//描述:实时显示测量距离,节点位置,总长度
//编程: 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(
44true); //矩形框向四周扩大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, nullnull);
                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(
44true); //矩形框向四周扩大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, nullnull);
            }
        }

        
/// <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
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值