您的位置:首页 > 编程语言 > C#

c#+ArcEngine93实现实时显示测距结果功能

2009-08-11 10:16 405 查看
利用ArcEngine实现距离量测,面积量测的功能已很简单,相信众多的ArcGIS爱好者都能写. 但单纯的实现功能总觉得欠什么.本人喜欢改代码,喜欢优化代码,在原有的功能基础上总喜欢"润色",使之更好看.前一整子在玩skyline时看到 skyline 的测距功能能实时显示量测的距离,于是联想到之前自己用C#+ArcEngine 写的测距功能.何不也优化一下自己代码? 想到就做到.最近手有点痒,算练练手.
废话少说,先附上效果图:
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
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: