About the Move a graphic along a path in ArcMap Sample
[C#]
AnimationUtils.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.ADF.BaseClasses;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Animation;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Geometry;
namespace AnimationDeveloperSamples
{
public class AnimationUtils
{
public static void CreateMapGraphicTrack(ICreateGraphicTrackOptions pOptions, IAGAnimationTracks tracks, IAGAnimationContainer pContainer)
{
pOptions.PathGeometry=SimplifyPath2D(pOptions.PathGeometry,pOptions.ReverseOrder,pOptions.SimplificationFactor);
IAGAnimationType animType = new AnimationTypeMapGraphic();
//remove tracks with the same name if overwrite is true
if (pOptions.OverwriteTrack == true)
{
IArray trackArray = new ArrayClass();
trackArray = tracks.get_TracksOfType(animType);
int count = trackArray.Count;
for (int i = 0; i < count; i++)
{
IAGAnimationTrack temp = (IAGAnimationTrack)trackArray.get_Element(i);
if (temp.Name == pOptions.TrackName)
tracks.RemoveTrack(temp);
}
}
//create the new track
IAGAnimationTrack animTrack = tracks.CreateTrack(animType);
IAGAnimationTrackKeyframes animTrackKeyframes = (IAGAnimationTrackKeyframes)animTrack;
animTrackKeyframes.EvenTimeStamps = false;
animTrack.Name = pOptions.TrackName;
IGeometry path = pOptions.PathGeometry;
IPointCollection pointCollection = (IPointCollection)path;
ICurve curve = (ICurve)path;
double length = curve.Length;
double accuLength = 0;
//loop through all points to create the keyframes
int pointCount = pointCollection.PointCount;
if (pointCount <= 1)
return;
for (int i = 0; i < pointCount; i++)
{
IPoint currentPoint = pointCollection.get_Point(i);
IPoint nextPoint = new PointClass();
if (i < pointCount-1)
nextPoint = pointCollection.get_Point(i + 1);
IPoint lastPoint = new PointClass();
if (i == 0)
lastPoint = currentPoint;
else
lastPoint = pointCollection.get_Point(i-1);
IAGKeyframe tempKeyframe = animTrackKeyframes.CreateKeyframe(i);
//set keyframe properties
double x;
double y;
currentPoint.QueryCoords(out x, out y);
tempKeyframe.set_PropertyValue(0, currentPoint);
tempKeyframe.Name = "Map Graphic keyframe " + i.ToString();
//set keyframe timestamp
accuLength += CalculateDistance(lastPoint, currentPoint);
double timeStamp = accuLength / length;
tempKeyframe.TimeStamp = timeStamp;
double x1;
double y1;
double angle;
if (i < pointCount - 1)
{
nextPoint.QueryCoords(out x1, out y1);
if ((y1 - y) > 0)
angle = Math.Acos((x1 - x) / Math.Sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)));
else
{
angle = 6.2832 - Math.Acos((x1 - x) / Math.Sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)));
}
tempKeyframe.set_PropertyValue(1, angle);
}
else
{
IAGKeyframe lastKeyframe = animTrackKeyframes.get_Keyframe(i-1);
tempKeyframe.set_PropertyValue(1, lastKeyframe.get_PropertyValue(1));
}
}
//attach the point element
if(pOptions.PointElement != null)
animTrack.AttachObject(pOptions.PointElement);
//attach the track extension, which contains a line element for trace
IMapGraphicTrackExtension graphicTrackExtension = new MapGraphicTrackExtension();
graphicTrackExtension.ShowTrace = pOptions.AnimatePath;
IAGAnimationTrackExtensions trackExtensions = (IAGAnimationTrackExtensions)animTrack;
trackExtensions.AddExtension(graphicTrackExtension);
}
private static double CalculateDistance(IPoint FromPoint, IPoint ToPoint)
{
double distance;
distance = Math.Sqrt((ToPoint.X - FromPoint.X) * (ToPoint.X - FromPoint.X) + (ToPoint.Y - FromPoint.Y) * (ToPoint.Y - FromPoint.Y));
return distance;
}
private static IGeometry SimplifyPath2D(IGeometry path, bool bReverse, double simpFactor)
{
IGeometry oldPath = path;
IPointCollection oldPointCollection = oldPath as IPointCollection;
IPolyline newPath = new PolylineClass();
IPointCollection newPointCollection = newPath as IPointCollection;
ISpatialReference sr = oldPath.SpatialReference;
int pointCount;
pointCount = oldPointCollection.PointCount;
double[] lastCoord = new double[2];
IPoint beginningPoint = new PointClass();
oldPointCollection.QueryPoint(bReverse ? (pointCount - 1) : 0, beginningPoint);
beginningPoint.QueryCoords(out lastCoord[0], out lastCoord[1]);
bool bKeep = true;
IPolyline oldLine = oldPath as IPolyline;
double length = oldLine.Length;
object Missing = Type.Missing;
newPointCollection.AddPoint(beginningPoint, ref Missing, ref Missing);
for (int i = 1; i < pointCount - 1; i++) //simplify 2D path
{
double[] coord = new double[2];
IPoint currentPoint = new PointClass();
oldPointCollection.QueryPoint(bReverse ? (pointCount - i - 1) : i, currentPoint);
currentPoint.QueryCoords(out coord[0], out coord[1]);
double[] d = new double[2];
d[0] = coord[0] - lastCoord[0];
d[1] = coord[1] - lastCoord[1];
double distance;
distance = Math.Sqrt(d[0] * d[0] + d[1] * d[1]);
if (distance < (0.25 * simpFactor * length))
{
bKeep = false;
}
else
{
bKeep = true;
}
if (bKeep)
{
newPointCollection.AddPoint(currentPoint, ref Missing, ref Missing);
lastCoord[0] = coord[0];
lastCoord[1] = coord[1];
}
}
IPoint finalPoint = new PointClass();
oldPointCollection.QueryPoint(bReverse ? 0 : (pointCount - 1), finalPoint);
newPointCollection.AddPoint(finalPoint, ref Missing, ref Missing);
newPath.SpatialReference = sr;
return (IGeometry)newPath;
}
}
}
[Visual Basic .NET]
AnimationUtils.vb
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Text
Imports System.Windows.Forms
Imports ESRI.ArcGIS.ADF.BaseClasses
Imports ESRI.ArcGIS.ADF.CATIDs
Imports ESRI.ArcGIS.Animation
Imports ESRI.ArcGIS.ADF
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Controls
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.SystemUI
Imports ESRI.ArcGIS.Geometry
Public Class AnimationUtils
Public Shared Sub CreateMapGraphicTrack(ByVal pOptions As ICreateGraphicTrackOptions, ByVal tracks As IAGAnimationTracks, ByVal pContainer As IAGAnimationContainer)
pOptions.PathGeometry = SimplifyPath2D(pOptions.PathGeometry, pOptions.ReverseOrder, pOptions.SimplificationFactor)
Dim animType As IAGAnimationType = New AnimationTypeMapGraphic()
Dim i As Integer = 0
'remove tracks with the same name if overwrite is true
If pOptions.OverwriteTrack = True Then
Dim trackArray As IArray = New ArrayClass()
trackArray = tracks.TracksOfType(animType)
Dim count As Integer = trackArray.Count
Do While i < count
Dim temp As IAGAnimationTrack = CType(trackArray.Element(i), IAGAnimationTrack)
If temp.Name = pOptions.TrackName Then
tracks.RemoveTrack(temp)
End If
i += 1
Loop
End If
'create the new track
Dim animTrack As IAGAnimationTrack = tracks.CreateTrack(animType)
Dim animTrackKeyframes As IAGAnimationTrackKeyframes = CType(animTrack, IAGAnimationTrackKeyframes)
animTrackKeyframes.EvenTimeStamps = False
animTrack.Name = pOptions.TrackName
Dim path As IGeometry = pOptions.PathGeometry
Dim pointCollection As IPointCollection = CType(path, IPointCollection)
Dim curve As ICurve = CType(path, ICurve)
Dim length As Double = curve.Length
Dim accuLength As Double = 0
'loop through all points to create the keyframes
Dim pointCount As Integer = pointCollection.PointCount
If pointCount <= 1 Then
Return
End If
i = 0
Do While i < pointCount
Dim currentPoint As IPoint = pointCollection.Point(i)
Dim nextPoint As IPoint = New PointClass()
If i < pointCount - 1 Then
nextPoint = pointCollection.Point(i + 1)
End If
Dim lastPoint As IPoint = New PointClass()
If i = 0 Then
lastPoint = currentPoint
Else
lastPoint = pointCollection.Point(i - 1)
End If
Dim tempKeyframe As IAGKeyframe = animTrackKeyframes.CreateKeyframe(i)
'set keyframe properties
Dim x As Double
Dim y As Double
currentPoint.QueryCoords(x, y)
tempKeyframe.PropertyValue(0) = currentPoint
tempKeyframe.Name = "Map Graphic keyframe " & i.ToString()
'set keyframe timestamp
accuLength += CalculateDistance(lastPoint, currentPoint)
Dim timeStamp As Double = accuLength / length
tempKeyframe.TimeStamp = timeStamp
Dim x1 As Double
Dim y1 As Double
Dim angle As Double
If i < pointCount - 1 Then
nextPoint.QueryCoords(x1, y1)
If (y1 - y) > 0 Then
angle = Math.Acos((x1 - x) / Math.Sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)))
Else
angle = 6.2832 - Math.Acos((x1 - x) / Math.Sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)))
End If
tempKeyframe.PropertyValue(1) = angle
Else
Dim lastKeyframe As IAGKeyframe = animTrackKeyframes.Keyframe(i - 1)
tempKeyframe.PropertyValue(1) = lastKeyframe.PropertyValue(1)
End If
i += 1
Loop
'attach the point element
If Not pOptions.PointElement Is Nothing Then
animTrack.AttachObject(pOptions.PointElement)
End If
'attach the track extension, which contains a line element for trace
Dim graphicTrackExtension As IMapGraphicTrackExtension = New MapGraphicTrackExtension()
graphicTrackExtension.ShowTrace = pOptions.AnimatePath
Dim trackExtensions As IAGAnimationTrackExtensions = CType(animTrack, IAGAnimationTrackExtensions)
trackExtensions.AddExtension(graphicTrackExtension)
End Sub
Private Shared Function CalculateDistance(ByVal FromPoint As IPoint, ByVal ToPoint As IPoint) As Double
Dim distance As Double
distance = Math.Sqrt((ToPoint.X - FromPoint.X) * (ToPoint.X - FromPoint.X) + (ToPoint.Y - FromPoint.Y) * (ToPoint.Y - FromPoint.Y))
Return distance
End Function
Private Shared Function SimplifyPath2D(ByVal path As IGeometry, ByVal bReverse As Boolean, ByVal simpFactor As Double) As IGeometry
Dim oldPath As IGeometry = path
Dim oldPointCollection As IPointCollection = TryCast(oldPath, IPointCollection)
Dim newPath As IPolyline = New PolylineClass()
Dim newPointCollection As IPointCollection = TryCast(newPath, IPointCollection)
Dim sr As ISpatialReference = oldPath.SpatialReference
Dim pointCount As Integer
pointCount = oldPointCollection.PointCount
Dim lastCoord As Double() = New Double(1) {}
Dim beginningPoint As IPoint = New PointClass()
If bReverse Then
oldPointCollection.QueryPoint(pointCount - 1, beginningPoint)
Else
oldPointCollection.QueryPoint(0, beginningPoint)
End If
beginningPoint.QueryCoords(lastCoord(0), lastCoord(1))
Dim bKeep As Boolean = True
Dim oldLine As IPolyline = TryCast(oldPath, IPolyline)
Dim length As Double = oldLine.Length
Dim Missing As Object = Type.Missing
newPointCollection.AddPoint(beginningPoint, Missing, Missing)
Dim i As Integer = 1
Do While i < pointCount - 1 'simplify 2D path
Dim coord As Double() = New Double(1) {}
Dim currentPoint As IPoint = New PointClass()
If bReverse Then
oldPointCollection.QueryPoint(pointCount - i - 1, currentPoint)
Else
oldPointCollection.QueryPoint(i, currentPoint)
End If
currentPoint.QueryCoords(coord(0), coord(1))
Dim d As Double() = New Double(1) {}
d(0) = coord(0) - lastCoord(0)
d(1) = coord(1) - lastCoord(1)
Dim distance As Double
distance = Math.Sqrt(d(0) * d(0) + d(1) * d(1))
If distance < (0.25 * simpFactor * length) Then
bKeep = False
Else
bKeep = True
End If
If bKeep Then
newPointCollection.AddPoint(currentPoint, Missing, Missing)
lastCoord(0) = coord(0)
lastCoord(1) = coord(1)
End If
i += 1
Loop
Dim finalPoint As IPoint = New PointClass()
If bReverse Then
oldPointCollection.QueryPoint(0, finalPoint)
Else
oldPointCollection.QueryPoint(pointCount - 1, finalPoint)
End If
newPointCollection.AddPoint(finalPoint, Missing, Missing)
newPath.SpatialReference = sr
Return CType(newPath, IGeometry)
End Function
End Class