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

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



说明:
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类


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

usingSystem;
usingSystem.Drawing;
usingSystem.Runtime.InteropServices;
usingESRI.ArcGIS.ADF.BaseClasses;
usingESRI.ArcGIS.ADF.CATIDs;
usingESRI.ArcGIS.Controls;
usingESRI.ArcGIS.Carto;
usingESRI.ArcGIS.Geodatabase;
usingESRI.ArcGIS.Display;
usingESRI.ArcGIS.Geometry;
usingSystem.Windows.Forms;

namespaceMhGis.GisTool.Pb_Toolbar
{
classTrackLine:BaseTool
{
privateIHookHelperm_hookHelper=null;
privateINewLineFeedbackm_NewLineFeedback=null;
privateIPointCollectionm_ptColl;//记录节点

privateMeasureMsgInfo_MsgInfo=null;
privateIPolylinem_TraceLine=null;//完整的轨迹线
//
privateIGroupElementm_Elements=null;//用于保存包含此功能产生的所有Element
privateIGroupElementm_TraceElement=null;//测距轨迹线
privateIGroupElementm_VertexElement=null;//结点
privateIGroupElementm_LabelElement=null;//距离标记

publicTrackLine()
{
//
//TODO:Definevaluesforthepublicproperties
//
base.m_category="";//localizabletext
base.m_caption="";//localizabletext
base.m_message="ThisshouldworkinArcMap/MapControl/PageLayoutControl";//localizabletext
base.m_toolTip="";//localizabletext
base.m_name="";//uniqueid,non-localizable(e.g."MyCategory_MyTool")
try
{
//
//TODO:changeresourcenameifnecessary
//
stringbitmapResourceName=GetType().Name+".bmp";
base.m_bitmap=newBitmap(GetType(),bitmapResourceName);
base.m_cursor=newSystem.Windows.Forms.Cursor(GetType(),GetType().Name+".cur");
}
catch(Exceptionex)
{
System.Diagnostics.Trace.WriteLine(ex.Message,
"InvalidBitmap");
}
}

publicMeasureMsgInfoMsgInfo
{
set
{
_MsgInfo
=value;
_MsgInfo.FormClosing
+=newFormClosingEventHandler(msgInfo_FromClosing);
}
}

#regionOverridenClassMethods

///<summary>
///Occurswhenthistooliscreated
///</summary>
///<paramname="hook">Instanceoftheapplication</param>
publicoverridevoidOnCreate(objecthook)
{
try
{
m_hookHelper
=newHookHelperClass();
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:Addotherinitializationcode
}
voidInit()
{
//初始化
m_Elements=newGroupElementClass();
m_TraceElement
=newGroupElementClass();
m_VertexElement
=newGroupElementClass();
m_LabelElement
=newGroupElementClass();

//初始化,并添加到GraphicsContainer
IGraphicsContainerg=m_hookHelper.ActiveViewasIGraphicsContainer;
g.AddElement(m_Elements
asIElement,0);
g.AddElement(m_TraceElement
asIElement,0);
g.AddElement(m_VertexElement
asIElement,0);
g.AddElement(m_LabelElement
asIElement,0);

//添加到m_Elements中
g.MoveElementToGroup(m_VertexElementasIElement,m_Elements);
g.MoveElementToGroup(m_LabelElement
asIElement,m_Elements);
g.MoveElementToGroup(m_TraceElement
asIElement,m_Elements);
}
///<summary>
///Occurswhenthistoolisclicked
///</summary>
publicoverridevoidOnClick()
{
Init();
}

voidmsgInfo_FromClosing(objectsender,FormClosingEventArgse)
{
DeleteAllElements();
_MsgInfo
=null;

//thrownewException("Themethodoroperationisnotimplemented.");
}
publicoverridevoidOnMouseDown(intButton,intShift,intX,intY)
{
if(Button==2)
return;
IPointpt
=m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);
IGraphicsContainerg
=m_hookHelper.ActiveView.GraphicsContainer;
IEnvelopepEnvBounds
=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
=newNewLineFeedbackClass();
m_NewLineFeedback.Display
=m_hookHelper.ActiveView.ScreenDisplay;
//必须先得到symbol,后设置symbol
ISimpleLineSymbolsimpleLineSymbol=m_NewLineFeedback.SymbolasISimpleLineSymbol;
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
=newPolylineClass();
}
//记录节点
objectobj=Type.Missing;
m_ptColl.AddPoint(pt,
refobj,refobj);

#endregion



#region绘制结点

try
{
IElementvertexElement
=CreateElement(pt);
//
g=m_hookHelper.ActiveViewasIGraphicsContainer;

//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)
{
IPointfromPt
=m_ptColl.get_Point(m_ptColl.PointCount-2);//倒数第二个点
IPointtoPt=m_ptColl.get_Point(m_ptColl.PointCount-1);//最后第一个点
ILineline=newLineClass();
line.PutCoords(fromPt,toPt);

#region绘制轨迹线

try
{
objectmissing=Type.Missing;
ISegmentCollectionsegColl
=newPolylineClass();
segColl.AddSegment(line
asISegment,refmissing,refmissing);
IElementtraceElement
=CreateElement(segCollasIPolyline);
//
g=m_hookHelper.ActiveViewasIGraphicsContainer;

//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
{
doubleangle=line.Angle;
if((angle>(Math.PI/2)&&angle<(Math.PI))||(angle>-Math.PI&&angle<-(Math.PI/2)))//大于90度小于等于180
angle+=Math.PI;

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

//标注点

doubled_CenterX=(fromPt.X+toPt.X)/2;
doubled_CenterY=(fromPt.Y+toPt.Y)/2+d_OffsetY;//向上偏移

IPointlabelPt
=newPointClass();
labelPt.PutCoords(d_CenterX,d_CenterY);


ITextElementtxtElement
=CreateTextElement(line.Length.ToString("0.00"));

IElementlabelelement
=txtElementasIElement;
labelelement.Geometry
=labelPt;
objectoElement=(object)labelelement;

//根据角度旋转
TransformByRotate(refoElement,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
{}

}

publicoverridevoidOnMouseMove(intButton,intShift,intX,intY)
{
if(m_NewLineFeedback==null)
return;
IPointpt
=m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation.ToMapPoint(X,Y);

m_NewLineFeedback.MoveTo(pt);

if(m_ptColl.PointCount==0)
return;
doubled_Total=0;
doubled_segment=0;

IPointlastPt
=m_ptColl.get_Point(m_ptColl.PointCount-1);
ILineline
=newLineClass();
line.PutCoords(lastPt,pt);
//节距离
d_segment=line.Length;
_MsgInfo.Segment
=d_segment;
try
{
IPolylinepolyline
=m_ptCollasIPolyline;
if(polyline.IsEmpty)
{

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

}
catch
{

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

publicoverridevoidOnDblClick()
{
if(m_NewLineFeedback==null)
return;

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

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

//回收
publicvoidRecycle()
{
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>
///<paramname="groupElement"></param>
voidRemoveElementFromGroupElement(IGroupElementgroupElement)
{
if(groupElement==null||groupElement.ElementCount==0)
return;
try
{
IGraphicsContainerg
=m_hookHelper.ActiveView.GraphicsContainer;
for(intindex=0;index<groupElement.ElementCount;index++)
{
IElementtmp_Ele
=groupElement.get_Element(index);
if(tmp_EleisIGroupElement)
RemoveElementFromGroupElement(tmp_Ele
asIGroupElement);
else
{
try
{
groupElement.DeleteElement(tmp_Ele);
}
catch
{

}
finally
{
tmp_Ele
=null;
}
}
}
//groupElement.ClearElements();
}
catch
{}
finally
{
//刷新
IEnvelopepEnvBounds=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>
voidRemoveElements()
{
try
{

//刷新一次
m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics,null,m_hookHelper.ActiveView.Extent);
IGraphicsContainerg
=m_hookHelper.ActiveView.GraphicsContainer;
#region1-new
//RemoveElementFromGroupElement(m_Elements);
#endregion
#region2
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>
publicvoidDeleteAllElements()
{
//m_hookHelper.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics,null,null);
IGraphicsContainerg=m_hookHelper.ActiveView.GraphicsContainer;

RemoveElementFromGroupElement(m_Elements);
try
{
g.DeleteElement(m_Elements
asIElement);
}
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>
///<paramname="color"></param>
///<returns></returns>
ESRI.ArcGIS.Display.IColorTransColorToAEColor(Colorcolor)
{
IRgbColorrgb
=newRgbColorClass();
rgb.RGB
=color.R+color.G*256+color.B*65536;
returnrgbasIColor;
}

///<summary>
///按指定的角度旋转
///</summary>
///<paramname="obj"></param>
///<paramname="originPt"></param>
///<paramname="rotate"></param>
voidTransformByRotate(refobjectobj,IPointoriginPt,doublerotate)
{
if(obj==null&&originPt==null)
return;
try
{
ITransform2Dtransform2D
=objasITransform2D;
if(transform2D==null)
return;
transform2D.Rotate(originPt,rotate);

}
catch
{}
}

#region创建Element
///<summary>
///创建一个TextElement
///</summary>
///<paramname="text"></param>
///<returns></returns>
ITextElementCreateTextElement(stringtext)
{
//创建一个TextSymbol
ITextSymboltxtSymbol=newTextSymbolClass();

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

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

//创建一个TextElement
ITextElementtxtElement=newTextElementClass();
txtElement.Symbol
=txtSymbol;
txtElement.Text
=text;

returntxtElement;
}

///<summary>
///绘制几何图形
///</summary>
///<paramname="geoType"></param>
///<paramname="geometry"></param>
///<returns></returns>
ESRI.ArcGIS.Carto.IElementCreateElement(ESRI.ArcGIS.Geometry.IGeometrygeometry)
{
IElementelement
=null;
try
{
switch(geometry.GeometryType)
{
caseesriGeometryType.esriGeometryPolyline://Polyline线
ISimpleLineSymbolsimpleLineSymbol=m_NewLineFeedback.SymbolasISimpleLineSymbol;

ILineElementlineElement
=newLineElementClass();
lineElement.Symbol
=simpleLineSymbolasILineSymbol;
element
=lineElementasIElement;
element.Geometry
=geometry;
break;
caseesriGeometryType.esriGeometryPoint:
//设置结点符号
IRgbColorpRGB=newRgbColorClass();
pRGB.Red
=255;
pRGB.Green
=0;
pRGB.Blue
=0;

ISimpleMarkerSymbolpSimpleMarkSymbol
=newSimpleMarkerSymbolClass();
pSimpleMarkSymbol.Color
=pRGBasIColor;
pSimpleMarkSymbol.Size
=2;
pSimpleMarkSymbol.Style
=esriSimpleMarkerStyle.esriSMSSquare;

IMarkerElementpMarkerElement
=newMarkerElementClass();
pMarkerElement.Symbol
=pSimpleMarkSymbolasIMarkerSymbol;
element
=pMarkerElementasIElement;
element.Geometry
=geometryasIGeometry;
break;
}
}
catch
{}
returnelement;
}
#endregion
}
}
来自:http://www.cnblogs.com/JinDin/archive/2009/09/02/1543438.html

你可能感兴趣的:(ArcEngine)