ArcObjects Library Reference  

AnimationUtils

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