1、前言
在ArcEngine
中,轨迹播放的实现方法很简单:
- 创建一个定时器
Timer
- 在定时器的
Tick
事件中绘制IElement
我这里做了一个例子,效果如下图所示:
2、实现方法
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class MainForm : Form
{
private IPolyline pPolyline;
private double length;
private double step;
// 构造函数
public MainForm()
{
InitializeComponent();
Init();
}
// 初始化变量
private void Init()
{
// 加载地图
axMapControl1.LoadMxFile(@"C:\Users\DSF\Desktop\data\道路.mxd");
axMapControl1.Extent = axMapControl1.FullExtent;
// 获取线段
IFeatureLayer pFeatureLayer = axMapControl1.get_Layer(0) as IFeatureLayer;
IFeatureClass pFeatureClass = pFeatureLayer.FeatureClass;
IFeature pFeature = pFeatureClass.GetFeature(0);
pPolyline = pFeature.ShapeCopy as IPolyline;
// 初始化时间器
timer1.Enabled = false;
length = 0;
step = 100000;
}
// 开始
private void btnStartAnimation_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
timer1.Start();
}
// 停止
private void btnStopAnimation_Click(object sender, EventArgs e)
{
timer1.Stop();
timer1.Enabled = false;
}
// 计时器时间
private void timer1_Tick(object sender, EventArgs e)
{
if (timer1.Enabled)
{
if (length < pPolyline.Length)
{
// 获取当前点
IPoint pCurrentPoint = new ESRI.ArcGIS.Geometry.Point();
pPolyline.QueryPoint(esriSegmentExtension.esriNoExtension, length, false, pCurrentPoint);
// 获取下一个点
IPoint pNextPoint = new ESRI.ArcGIS.Geometry.Point();
pPolyline.QueryPoint(esriSegmentExtension.esriNoExtension, length + step, false, pNextPoint);
// 计算方位角
double angle = CalculateAngle(pCurrentPoint, pNextPoint);
IPictureMarkerSymbol pPictureMarkerSymbol = CreateSymbol(pCurrentPoint, pNextPoint);
// 创建元素
IMarkerElement pMarkerElement = new MarkerElement() as IMarkerElement;
pMarkerElement.Symbol = pPictureMarkerSymbol;
IElement pElement = pMarkerElement as IElement;
pElement.Geometry = pCurrentPoint;
// 添加元素
IActiveView pActiveView = axMapControl1.ActiveView;
IGraphicsContainer pGraphicsContainer = pActiveView.GraphicsContainer;
pGraphicsContainer.DeleteAllElements();
pGraphicsContainer.AddElement(pElement, 0);
pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
length += step;
}
else
{
// 获取当前点
IPoint pCurrentPoint = new ESRI.ArcGIS.Geometry.Point();
pPolyline.QueryPoint(esriSegmentExtension.esriNoExtension, length, false, pCurrentPoint);
// 获取下一个点
IPoint pNextPoint = new ESRI.ArcGIS.Geometry.Point();
pPolyline.QueryPoint(esriSegmentExtension.esriExtendTangents, length + step, false, pNextPoint);
// 计算方位角
double angle = CalculateAngle(pCurrentPoint, pNextPoint);
IPictureMarkerSymbol pPictureMarkerSymbol = CreateSymbol(pCurrentPoint, pNextPoint);
// 创建元素
IMarkerElement pMarkerElement = new MarkerElement() as IMarkerElement;
pMarkerElement.Symbol = pPictureMarkerSymbol;
IElement pElement = pMarkerElement as IElement;
pElement.Geometry = pCurrentPoint;
// 添加元素
IActiveView pActiveView = axMapControl1.ActiveView;
IGraphicsContainer pGraphicsContainer = pActiveView.GraphicsContainer;
pGraphicsContainer.DeleteAllElements();
pGraphicsContainer.AddElement(pElement, 0);
pActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, null, null);
// 停止计时器
length = 0;
timer1.Stop();
timer1.Enabled = false;
}
}
}
// 计算角度
private double CalculateAngle(IPoint pCurrentPoint, IPoint pNextPoint)
{
if (pCurrentPoint.X == pNextPoint.X)
{
if (pCurrentPoint.Y <= pNextPoint.Y)
{
return 90;
}
else
{
return 270;
}
}
else if (pCurrentPoint.X < pNextPoint.X)
{
double deltaX = Math.Abs(pNextPoint.X - pCurrentPoint.X);
double deltaY = Math.Abs(pNextPoint.Y - pCurrentPoint.Y);
if (pCurrentPoint.Y <= pNextPoint.Y)
{
return Math.Atan(deltaY / deltaX) * 180 / Math.PI;
}
else
{
return 360 - Math.Atan(deltaY / deltaX) * 180 / Math.PI;
}
}
else
{
double deltaX = Math.Abs(pNextPoint.X - pCurrentPoint.X);
double deltaY = Math.Abs(pNextPoint.Y - pCurrentPoint.Y);
if (pCurrentPoint.Y <= pNextPoint.Y)
{
return 180 - Math.Atan(deltaY / deltaX) * 180 / Math.PI;
}
else
{
return 180 + Math.Atan(deltaY / deltaX) * 180 / Math.PI;
}
}
}
// 创建符号
private IPictureMarkerSymbol CreateSymbol(IPoint pCurrentPoint, IPoint pNextPoint)
{
IPictureMarkerSymbol pPictureMarkerSymbol = new PictureMarkerSymbol();
pPictureMarkerSymbol.Angle = CalculateAngle(pCurrentPoint, pNextPoint);
pPictureMarkerSymbol.CreateMarkerSymbolFromFile(esriIPictureType.esriIPicturePNG, @"C:\Users\DSF\Desktop\plane.png");
pPictureMarkerSymbol.Size = 25;
return pPictureMarkerSymbol;
}
}
}