ArcObjects Library Reference  

PlaybackDataButton

About the Play back tracking data Sample

[C#]

PlaybackDataButton.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Timers;
using System.IO;
using ESRI.ArcGIS.TrackingAnalyst;
using ESRI.ArcGIS.Geodatabase;
using System.Windows.Forms;
using ESRI.ArcGIS.DataSourcesGDB;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.ADF.Connection.Local;
using System.Drawing;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.ArcMapUI;

namespace TAPlaybackTrackingData
{

  public class PlaybackDataButton : ESRI.ArcGIS.Desktop.AddIns.Button
  {
    private System.Timers.Timer m_timer = null;
    private ITemporalLayer m_temporalLayer = null;
    private bool m_bIsConnected = false;
    private IActiveView m_activeView = null;
    private ITrackingEnvironment3 m_temporalEnv = null;
    private ITemporalOperator3 m_baseTime = null;
    bool m_bIsFirst = true;
    private ITemporalOperator3 m_tempOpIncrement = null;
    private IDocumentEvents_Event m_docEvent = null;

    public PlaybackDataButton()
    {
      m_timer = new System.Timers.Timer(500);
      m_timer.Enabled = false;
      m_timer.Elapsed += new ElapsedEventHandler(OnTimer);
    }

    protected override void OnClick()
    {
      if (!m_bIsConnected)
      {
        try
        {
          //open the shapefile with the recorded data
          IFeatureClass featureClass = openPlaybackData();
          if (null == featureClass)
            return;

          //get the map container
          object mapObj = ArcMap.Application;
          
          //load the Tracking Analyst extension
          ITrackingEnvironment3 trackingEnv = setupTrackingEnv(ref mapObj);
          //set the mode to historic, since you need to do playback
          trackingEnv.DefaultTemporalReference.TemporalMode = enumTemporalMode.enumHistoric;
          //set the units of the temporal period to days
          trackingEnv.DefaultTemporalReference.TemporalPeriodUnits = enumTemporalUnits.enumDays;
          //set the update mode to manual so that it will be controlled by the application
          trackingEnv.DisplayManager.ManualUpdate = true;
          //set the temporal perspective to Aug 03 2000 7PM.
          trackingEnv.DefaultTemporalReference.TemporalPerspective = "8/3/2000 7:0:00 PM";

          //create a temporal operator that will serve as a base time for the tracking environment
          ITemporalOperator3 temporalOpBaseTime = new TemporalOperatorClass() as ITemporalOperator3;
          //set the base time to 6PM, Aug 3 2000
          temporalOpBaseTime.SetDateTime(2000, 8, 3, 18, 0, 0, 0);

          //create the renderer for the temporal layer
          ITemporalRenderer temporalRenderer = setRenderer(featureClass, "DATE_TIME", "EVENTID");

          //create the temporal layer for the playback data
          m_temporalLayer = new TemporalFeatureLayerClass();
          //assign the featureclass for the layer
          ((IFeatureLayer)m_temporalLayer).FeatureClass = featureClass;
          //set the base time to initialize the time window of the layer
          m_temporalLayer.RelativeTimeOperator = (ITemporalOperator)temporalOpBaseTime;
          //set the renderer for the temporal layer 
          m_temporalLayer.Renderer = temporalRenderer as IFeatureRenderer;
          //set the flag in order to display the track of previous locations
          m_temporalLayer.DisplayOnlyLastKnownEvent = false;
          //initialize labels for the event name
          setupLayerLabels(m_temporalLayer, "EVENTID");

          m_activeView = ArcMap.Document.ActiveView;
          m_temporalEnv = trackingEnv;
          m_baseTime = temporalOpBaseTime;

          //add the temporal layer to the map
          ArcMap.Document.FocusMap.AddLayer((ILayer)m_temporalLayer);

          //enable the timer
          m_timer.Enabled = true;
        }
        catch (Exception ex)
        {
          System.Diagnostics.Trace.WriteLine(ex.Message);
        }
      }
      else
      {
        //disable the timer
        m_timer.Enabled = false;

        if (null == m_temporalLayer)
          return;
        //remove the layer
        ArcMap.Document.FocusMap.DeleteLayer((ILayer)m_temporalLayer);
        m_temporalLayer = null;
      }
      m_bIsConnected = !m_bIsConnected;

      m_docEvent = ArcMap.Document as IDocumentEvents_Event;
      m_docEvent.CloseDocument += new IDocumentEvents_CloseDocumentEventHandler(docEvent_CloseDocument);

      ArcMap.Application.CurrentTool = null;
    }

    void docEvent_CloseDocument()
    {
      m_timer.Enabled = false;
    }

    private void setupLayerLabels(ITemporalLayer trackingLayer, string labelField)
    {
      //cast TrackingLayerLabels from the temporal layer
      ITrackingLayerLabels layerLabels = (ITrackingLayerLabels)trackingLayer;

      //set the labels properties
      layerLabels.LabelFieldName = labelField;
      layerLabels.LabelFeatures = true;

      // create text symbol
      ITextSymbol textSymbol = new TextSymbolClass();
      textSymbol.Color = (IColor)Converter.ToRGBColor(Color.Red);
      textSymbol.Size = 15;
      textSymbol.Font = Converter.ToStdFont(new Font(new FontFamily("Arial"), 15.0f, FontStyle.Regular));
      textSymbol.HorizontalAlignment = esriTextHorizontalAlignment.esriTHARight;
      textSymbol.VerticalAlignment = esriTextVerticalAlignment.esriTVABaseline;

      layerLabels.TextSymbol = textSymbol;
    }

    private IFeatureClass openPlaybackData()
    {
      //set the path to the featureclass
      string path = @"..\..\..\..\..\data\Time\ProjectData.gdb";
      if (!System.IO.Directory.Exists(path))
      {
        MessageBox.Show("Cannot find hurricane data:\n" + path, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return null;
      }

      IWorkspaceFactory2 wsFactory = new FileGDBWorkspaceFactoryClass();
      IWorkspace workspace = wsFactory.OpenFromFile( path, 0 );
      IFeatureClass featureClass = ((IFeatureWorkspace)workspace).OpenFeatureClass( "atlantic_hurricanes_2000" );

      return featureClass;
    }

    private ITrackingEnvironment3 setupTrackingEnv(ref object mapObj)
    {
      IExtensionManager extentionManager = new ExtensionManagerClass();

      UID uid = new UIDClass();
      uid.Value = "esriTrackingAnalyst.TrackingEngineUtil";

      ((IExtensionManagerAdmin)extentionManager).AddExtension(uid, ref mapObj);

      ITrackingEnvironment3 trackingEnv = new TrackingEnvironmentClass();
      trackingEnv.Initialize(ref mapObj);
      trackingEnv.EnableTemporalDisplayManagement = true;
      return trackingEnv;
    }

    private IUniqueValueRenderer CreateUniqueValueRenderer(IFeatureClass featureClass, string fieldName)
    {
      IRgbColor color = new RgbColorClass();
      color.Red = 255;
      color.Blue = 0;
      color.Green = 0;

      ICharacterMarkerSymbol charMarkersymbol = new CharacterMarkerSymbolClass();
      charMarkersymbol.Font = Converter.ToStdFont(new Font(new FontFamily("ESRI Default Marker"), 12.0f, FontStyle.Regular));
      charMarkersymbol.CharacterIndex = 96;
      charMarkersymbol.Size = 12.0;
      charMarkersymbol.Color = (IColor)color;


      IRandomColorRamp randomColorRamp = new RandomColorRampClass();
      randomColorRamp.MinSaturation = 20;
      randomColorRamp.MaxSaturation = 40;
      randomColorRamp.MaxValue = 85;
      randomColorRamp.MaxValue = 100;
      randomColorRamp.StartHue = 75;
      randomColorRamp.EndHue = 190;
      randomColorRamp.UseSeed = true;
      randomColorRamp.Seed = 45;

      IUniqueValueRenderer uniqueRenderer = new UniqueValueRendererClass();
      uniqueRenderer.FieldCount = 1;
      uniqueRenderer.set_Field(0, fieldName);
      uniqueRenderer.DefaultSymbol = (ISymbol)charMarkersymbol;
      uniqueRenderer.UseDefaultSymbol = true;



      Random rand = new Random();
      bool bValFound = false;
      IFeatureCursor featureCursor = featureClass.Search(null, true);
      IFeature feature = null;
      string val = string.Empty;
      int fieldID = featureClass.FindField(fieldName);
      if (-1 == fieldID)
        return uniqueRenderer;

      while ((feature = featureCursor.NextFeature()) != null)
      {
        bValFound = false;
        val = Convert.ToString(feature.get_Value(fieldID));
        for (int i = 0; i < uniqueRenderer.ValueCount - 1; i++)
        {
          if (uniqueRenderer.get_Value(i) == val)
            bValFound = true;
        }

        if (!bValFound)//need to add the value to the renderer
        {
          color.Red = rand.Next(255);
          color.Blue = rand.Next(255);
          color.Green = rand.Next(255);

          charMarkersymbol = new CharacterMarkerSymbolClass();
          charMarkersymbol.Font = Converter.ToStdFont(new Font(new FontFamily("ESRI Default Marker"), 10.0f, FontStyle.Regular));
          charMarkersymbol.CharacterIndex = rand.Next(40, 118);
          charMarkersymbol.Size = 20.0;
          charMarkersymbol.Color = (IColor)color;

          //add the value to the renderer
          uniqueRenderer.AddValue(val, "name", (ISymbol)charMarkersymbol);
        }
      }

      //release the featurecursor
      ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(featureCursor);

      return uniqueRenderer;
    }

    private IUniqueValueRenderer CreateTrackUniqueValueRenderer(IFeatureClass featureClass, string fieldName)
    {
      IRgbColor color = new RgbColorClass();
      color.Red = 0;
      color.Blue = 0;
      color.Green = 255;

      ISimpleLineSymbol simpleLineSymbol = new SimpleLineSymbolClass();
      simpleLineSymbol.Color = (IColor)color;
      simpleLineSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
      simpleLineSymbol.Width = 1.0;

      IUniqueValueRenderer uniqueRenderer = new UniqueValueRendererClass();
      uniqueRenderer.FieldCount = 1;
      uniqueRenderer.set_Field(0, fieldName);
      uniqueRenderer.DefaultSymbol = (ISymbol)simpleLineSymbol;
      uniqueRenderer.UseDefaultSymbol = true;

      Random rand = new Random();
      bool bValFound = false;
      IFeatureCursor featureCursor = featureClass.Search(null, true);
      IFeature feature = null;
      string val = string.Empty;
      int fieldID = featureClass.FindField(fieldName);
      if (-1 == fieldID)
        return uniqueRenderer;

      while ((feature = featureCursor.NextFeature()) != null)
      {
        bValFound = false;
        val = Convert.ToString(feature.get_Value(fieldID));
        for (int i = 0; i < uniqueRenderer.ValueCount - 1; i++)
        {
          if (uniqueRenderer.get_Value(i) == val)
            bValFound = true;
        }

        if (!bValFound)//need to add the value to the renderer
        {
          color.Red = rand.Next(255);
          color.Blue = rand.Next(255);
          color.Green = rand.Next(255);

          simpleLineSymbol = new SimpleLineSymbolClass();
          simpleLineSymbol.Color = (IColor)color;
          simpleLineSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
          simpleLineSymbol.Width = 1.0;

          //add the value to the renderer
          uniqueRenderer.AddValue(val, "name", (ISymbol)simpleLineSymbol);
        }
      }

      //release the featurecursor
      ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(featureCursor);

      return uniqueRenderer;
    }
    
    private ITemporalRenderer setRenderer(IFeatureClass featureClass, string temporalField, string eventName)
    {
      CoTrackSymbologyRenderer trackingRenderer = new CoTrackSymbologyRendererClass();
      ITemporalRenderer temporalRenderer = (ITemporalRenderer)trackingRenderer;
      temporalRenderer.TemporalFieldName = temporalField;
      temporalRenderer.TemporalObjectColumnName = eventName;
      temporalRenderer.TimeSymbologyMethod = enumTemporalSymbolizationMethod.enumColor;

      //this is a desktop only code which requires assemblies CartoUI and Framework
      //IRendererPropertyPage rendererPropPage = new UniqueValuePropertyPageClass();

      //enable the most current renderer
      IUniqueValueRenderer uniqueValrenderer = CreateUniqueValueRenderer(featureClass, eventName);
      if (null != uniqueValrenderer)
      {
        ((ITemporalRenderer2)temporalRenderer).MostCurrentRenderer = (IFeatureRenderer)uniqueValrenderer;
        ((ITemporalRenderer2)temporalRenderer).MostCurrentRendererEnabled = true;

        //this is a desktop only code which requires assemblies CartoUI and Framework
        //((ITemporalRenderer2)temporalRenderer).PropPageMostCurrentRenderer = rendererPropPage.ClassID;
      }

      //set the track renderer
      uniqueValrenderer = CreateTrackUniqueValueRenderer(featureClass, eventName);
      if (null != uniqueValrenderer)
      {
        ITrackSymbologyRenderer trackSymbolenderer = trackingRenderer as ITrackSymbologyRenderer;
        trackSymbolenderer.TrackSymbologyRenderer = (IFeatureRenderer)uniqueValrenderer;
        ((ITemporalRenderer2)temporalRenderer).TrackRendererEnabled = true;
        ((ITemporalRenderer2)temporalRenderer).SmoothTracks = true;

        //this is a desktop only code which requires assemblies CartoUI and Framework
        //((ITemporalRenderer2)temporalRenderer).PropPageTrackRenderer = rendererPropPage.ClassID;
      }

      return temporalRenderer;
    }    

    protected override void OnUpdate()
    {
      Enabled = ArcMap.Application != null;
    }

    private void OnTimer(object sender, ElapsedEventArgs e)
    {
      //increment the time-stamp of the tracking environment in order to do the playback
      OnIncrement();
    }

    private void OnIncrement()
    {
      if (m_bIsFirst)
      {
        //create the temporal increment object
        m_tempOpIncrement = new TemporalOperatorClass();
        m_tempOpIncrement.SetInterval(6.0, enumTemporalOperatorUnits.enumTemporalOperatorHours);

        m_bIsFirst = false;
      }

      if (null == m_baseTime)
        return;

      //increment the base time to match the 'current' time
      m_baseTime.Add((ITemporalOperator)m_tempOpIncrement);

      string date = m_baseTime.get_AsString("%c");
      System.Diagnostics.Trace.WriteLine(date);

      //increment the timestamp
      m_temporalEnv.DefaultTemporalReference.TemporalPerspective = (object)date;

      //refresh the display
      m_activeView.Refresh();
      // For better performance, the following line can be used instead of the one above to
      // do a partial refresh of the screen instead of refreshing the whole display.
      //m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, m_temporalLayer, new EnvelopeClass());
    }
  }

}

[Visual Basic .NET]

PlaybackDataButton.vb

Imports System
Imports System.Drawing
Imports System.Timers
Imports System.Windows.Forms
Imports ESRI.ArcGIS.ADF.Connection.Local
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.DataSourcesGDB
Imports ESRI.ArcGIS.Display
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geodatabase
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.TrackingAnalyst

Public Class PlaybackDataButton
  Inherits ESRI.ArcGIS.Desktop.AddIns.Button
  Private m_timer As System.Timers.Timer = Nothing
  Private m_temporalLayer As ITemporalLayer = Nothing
  Private m_bIsConnected As Boolean = False

  Private m_tempOpIncrement As ITemporalOperator3 = Nothing
  Private m_baseTime As ITemporalOperator3 = Nothing
  Private m_temporalEnv As ITrackingEnvironment3 = Nothing
  Private m_bIsFirst As Boolean = True


  Public Sub New()

    m_timer = New System.Timers.Timer(500)
    m_timer.Enabled = False
    AddHandler m_timer.Elapsed, AddressOf OnTimer

  End Sub

  Protected Overrides Sub OnClick()
    If (Not m_bIsConnected) Then
      Try
        'open the shapefile with the recorded data
        Dim featureClass As IFeatureClass = openPlaybackData()
        If Nothing Is featureClass Then
          Return
        End If

        'get the map container
        Dim mapObj As Object = My.ArcMap.Application

        'load the Tracking Analyst extension
        m_temporalEnv = setupTrackingEnv(mapObj)
        'set the mode to historic, since you need to do playback
        m_temporalEnv.DefaultTemporalReference.TemporalMode = enumTemporalMode.enumHistoric
        'set the units of the temporal period to days
        m_temporalEnv.DefaultTemporalReference.TemporalPeriodUnits = enumTemporalUnits.enumDays
                'set the update mode to manual so that it will be controlled by the application
        m_temporalEnv.DisplayManager.ManualUpdate = True
        'set the temporal perspective to Aug 03 2000 7PM.
        m_temporalEnv.DefaultTemporalReference.TemporalPerspective = "8/3/2000 7:0:00 PM"

                'create a temporal operator that will serve as a base time for the tracking environment
        m_baseTime = New TemporalOperatorClass()
        'set the base time to 6PM, Aug 3 2000
        m_baseTime.SetDateTime(2000, 8, 3, 18, 0, 0, 0)

        'create the renderer for the temporal layer
        Dim temporalRenderer As ITemporalRenderer = setRenderer(featureClass, "DATE_TIME", "EVENTID")

        'create the temporal layer for the playback data
        m_temporalLayer = New TemporalFeatureLayerClass()
        'assign the featureclass for the layer
        CType(m_temporalLayer, IFeatureLayer).FeatureClass = featureClass
        'set the base time to initialize the time window of the layer
        m_temporalLayer.RelativeTimeOperator = CType(m_baseTime, ITemporalOperator)
        'set the renderer for the temporal layer 
        m_temporalLayer.Renderer = TryCast(temporalRenderer, IFeatureRenderer)
        'set the flag in order to display the track of previous locations
        m_temporalLayer.DisplayOnlyLastKnownEvent = False
                'initialize labels for the event name
        setupLayerLabels(m_temporalLayer, "EVENTID")

        'add the temporal layer to the map
        My.ArcMap.Document.FocusMap.AddLayer(CType(m_temporalLayer, ILayer))

        'enable the timer
        m_timer.Enabled = True
      Catch ex As Exception
        System.Diagnostics.Trace.WriteLine(ex.Message)
      End Try
    Else
      'disable the timer
      m_timer.Enabled = False

      If Nothing Is m_temporalLayer Then
        Return
      End If
            'remove the layer
      My.ArcMap.Document.FocusMap.DeleteLayer(CType(m_temporalLayer, ILayer))
      m_temporalLayer = Nothing
    End If
    m_bIsConnected = Not m_bIsConnected

    My.ArcMap.Application.CurrentTool = Nothing
  End Sub

  Protected Overrides Sub OnUpdate()
    Enabled = My.ArcMap.Application IsNot Nothing
  End Sub

  Private Sub OnTimer(ByVal sender As Object, ByVal e As ElapsedEventArgs)
    OnIncrement()
  End Sub


  Private Sub OnIncrement()
    If m_bIsFirst Then
      'create the temporal increment object
      m_tempOpIncrement = New TemporalOperatorClass()
      m_tempOpIncrement.SetInterval(6.0, enumTemporalOperatorUnits.enumTemporalOperatorHours)

      m_bIsFirst = False
    End If

    If Nothing Is m_baseTime Then
      Return
    End If

    'increment the base time to match the 'current' time
    m_baseTime.Add(CType(m_tempOpIncrement, ITemporalOperator))

    Dim d As String = m_baseTime.AsString("%c")
    System.Diagnostics.Trace.WriteLine(d)

    'increment the timestamp
    m_temporalEnv.DefaultTemporalReference.TemporalPerspective = d

    'refresh the display
    My.ArcMap.Document.ActiveView.Refresh()
    'For improved performance, the line above can be replaces with the line above this comment.  The
    'lower line of code will only refresh the part of the screen that has changed.
    'My.ArcMap.Document.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGeography, m_temporalLayer, Nothing)
  End Sub


  ''' <summary>
  ''' create the renderer used to draw the tracks
  ''' </summary>
  ''' <param name="featureClass"></param>
  ''' <param name="fieldName"></param>
  ''' <returns></returns>
  Private Function CreateTrackUniqueValueRenderer(ByVal featureClass As IFeatureClass, ByVal fieldName As String) As IUniqueValueRenderer
    Dim color As IRgbColor = New RgbColorClass()
    color.Red = 0
    color.Blue = 0
    color.Green = 255

    Dim simpleLineSymbol As ISimpleLineSymbol = New SimpleLineSymbolClass()
    simpleLineSymbol.Color = CType(color, IColor)
    simpleLineSymbol.Style = ESRI.ArcGIS.Display.esriSimpleLineStyle.esriSLSSolid
    simpleLineSymbol.Width = 1.0

    Dim uniqueRenderer As IUniqueValueRenderer = New UniqueValueRendererClass()
    uniqueRenderer.FieldCount = 1
    uniqueRenderer.Field(0) = fieldName
    uniqueRenderer.DefaultSymbol = CType(simpleLineSymbol, ISymbol)
    uniqueRenderer.UseDefaultSymbol = True

    Dim rand As Random = New Random()
    Dim bValFound As Boolean = False
    Dim featureCursor As IFeatureCursor = featureClass.Search(Nothing, True)
    Dim feature As IFeature = Nothing
    Dim val As String = String.Empty
    Dim fieldID As Integer = featureClass.FindField(fieldName)
    If -1 = fieldID Then
      Return uniqueRenderer
    End If

    feature = featureCursor.NextFeature()
    Do While Not feature Is Nothing
      bValFound = False
      val = Convert.ToString(feature.Value(fieldID))
      Dim i As Integer = 0
      Do While i < uniqueRenderer.ValueCount - 1
        If uniqueRenderer.Value(i) = val Then
          bValFound = True
        End If
        i += 1
      Loop

      If (Not bValFound) Then 'need to add the value to the renderer
        color.Red = rand.Next(255)
        color.Blue = rand.Next(255)
        color.Green = rand.Next(255)

        simpleLineSymbol = New SimpleLineSymbolClass()
        simpleLineSymbol.Color = CType(color, IColor)
        simpleLineSymbol.Style = ESRI.ArcGIS.Display.esriSimpleLineStyle.esriSLSSolid
        simpleLineSymbol.Width = 1.0

        'add the value to the renderer
        uniqueRenderer.AddValue(val, "EVENTID", CType(simpleLineSymbol, ISymbol))
      End If

      feature = featureCursor.NextFeature()
    Loop

    'release the featurecursor
    ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(featureCursor)
    'ESRI.ArcGIS.ADF.BaseClasses.ComReleaser.ReleaseCOMObject(featureCursor)

    Return uniqueRenderer

  End Function

  Private Function CreateUniqueValueRenderer(ByVal featureClass As IFeatureClass, ByVal fieldName As String) As IUniqueValueRenderer
    Dim color As IRgbColor = New RgbColorClass()
    color.Red = 255
    color.Blue = 0
    color.Green = 0

    Dim charMarkersymbol As ICharacterMarkerSymbol = New CharacterMarkerSymbolClass()
    charMarkersymbol.Font = Converter.ToStdFont(New Font(New FontFamily("ESRI Default Marker"), 12.0F, FontStyle.Regular))
    charMarkersymbol.CharacterIndex = 96
    charMarkersymbol.Size = 12.0
    charMarkersymbol.Color = CType(color, IColor)


    Dim randomColorRamp As IRandomColorRamp = New RandomColorRampClass()
    randomColorRamp.MinSaturation = 20
    randomColorRamp.MaxSaturation = 40
    randomColorRamp.MaxValue = 85
    randomColorRamp.MaxValue = 100
    randomColorRamp.StartHue = 75
    randomColorRamp.EndHue = 190
    randomColorRamp.UseSeed = True
    randomColorRamp.Seed = 45

    Dim uniqueRenderer As IUniqueValueRenderer = New UniqueValueRendererClass()
    uniqueRenderer.FieldCount = 1
    uniqueRenderer.Field(0) = fieldName
    uniqueRenderer.DefaultSymbol = CType(charMarkersymbol, ISymbol)
    uniqueRenderer.UseDefaultSymbol = True



    Dim rand As Random = New Random()
    Dim bValFound As Boolean = False
    Dim featureCursor As IFeatureCursor = featureClass.Search(Nothing, True)
    Dim feature As IFeature = Nothing
    Dim val As String = String.Empty
    Dim fieldID As Integer = featureClass.FindField(fieldName)
    If -1 = fieldID Then
      Return uniqueRenderer
    End If

    feature = featureCursor.NextFeature()
    Do While Not feature Is Nothing
      bValFound = False
      val = Convert.ToString(feature.Value(fieldID))
      Dim i As Integer = 0
      Do While i < uniqueRenderer.ValueCount - 1
        If uniqueRenderer.Value(i) = val Then
          bValFound = True
        End If
        i += 1
      Loop

      If (Not bValFound) Then 'need to add the value to the renderer
        color.Red = rand.Next(255)
        color.Blue = rand.Next(255)
        color.Green = rand.Next(255)

        charMarkersymbol = New CharacterMarkerSymbolClass()
        charMarkersymbol.Font = Converter.ToStdFont(New Font(New FontFamily("ESRI Default Marker"), 10.0F, FontStyle.Regular))
        charMarkersymbol.CharacterIndex = rand.Next(40, 118)
        charMarkersymbol.Size = 20.0
        charMarkersymbol.Color = CType(color, IColor)

        'add the value to the renderer
        uniqueRenderer.AddValue(val, "name", CType(charMarkersymbol, ISymbol))
      End If

      feature = featureCursor.NextFeature()
    Loop

    'release the featurecursor
    ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(featureCursor)

    Return uniqueRenderer
  End Function

  Private Sub setupLayerLabels(ByVal trackingLayer As ITemporalLayer, ByVal labelField As String)
    'cast TrackingLayerLabels from the temporal layer
    Dim layerLabels As ITrackingLayerLabels = CType(trackingLayer, ITrackingLayerLabels)

    'set the labels properties
    layerLabels.LabelFieldName = labelField
    layerLabels.LabelFeatures = True

    ' create text symbol
    Dim textSymbol As ITextSymbol = New TextSymbolClass()
    textSymbol.Color = CType(Converter.ToRGBColor(Color.Red), IColor)
    'textSymbol.Color = (IColor)color;
    textSymbol.Size = 15
    textSymbol.Font = Converter.ToStdFont(New Font(New FontFamily("Arial"), 15.0F, FontStyle.Regular))
    textSymbol.HorizontalAlignment = ESRI.ArcGIS.Display.esriTextHorizontalAlignment.esriTHARight
    textSymbol.VerticalAlignment = ESRI.ArcGIS.Display.esriTextVerticalAlignment.esriTVABaseline

    layerLabels.TextSymbol = textSymbol
  End Sub

  Private Function setupTrackingEnv(ByRef mapObj As Object) As ITrackingEnvironment3
    Dim extentionManager As IExtensionManager = New ExtensionManagerClass()

    Dim uid As UID = New UIDClass()
    uid.Value = "esriTrackingAnalyst.TrackingEngineUtil"

    CType(extentionManager, IExtensionManagerAdmin).AddExtension(uid, mapObj)

    Dim trackingEnv As ITrackingEnvironment3 = New TrackingEnvironmentClass()
    trackingEnv.Initialize(mapObj)
    trackingEnv.EnableTemporalDisplayManagement = True
    Return trackingEnv
  End Function

  Private Function openPlaybackData() As IFeatureClass
        'set the path to the featureclass in the sample data
    Dim path As String = "..\..\..\..\..\data\Time\ProjectData.gdb"
    If (Not System.IO.Directory.Exists(path)) Then
      MessageBox.Show("Cannot find hurricane data:" & Constants.vbLf & path, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
      Return Nothing
    End If

    Dim wsFactory As IWorkspaceFactory2 = New FileGDBWorkspaceFactoryClass()
    Dim workspace As IWorkspace = wsFactory.OpenFromFile(path, 0)
    Dim featureClass As IFeatureClass = (CType(workspace, IFeatureWorkspace)).OpenFeatureClass("atlantic_hurricanes_2000")

    Return featureClass
  End Function

  Private Function setRenderer(ByVal featureClass As IFeatureClass, ByVal temporalField As String, ByVal eventName As String) As ITemporalRenderer
    Dim trackingRenderer As CoTrackSymbologyRenderer = New CoTrackSymbologyRendererClass()
    Dim temporalRenderer As ITemporalRenderer = CType(trackingRenderer, ITemporalRenderer)
    temporalRenderer.TemporalFieldName = temporalField
    temporalRenderer.TemporalObjectColumnName = eventName
    temporalRenderer.TimeSymbologyMethod = enumTemporalSymbolizationMethod.enumColor

    'this is a desktop only code which requires assemblies CartoUI and Framework
    'IRendererPropertyPage rendererPropPage = new UniqueValuePropertyPageClass();

    'enable the most current renderer
    Dim uniqueValrenderer As IUniqueValueRenderer = CreateUniqueValueRenderer(featureClass, eventName)
    If Not Nothing Is uniqueValrenderer Then
      CType(temporalRenderer, ITemporalRenderer2).MostCurrentRenderer = CType(uniqueValrenderer, IFeatureRenderer)
      CType(temporalRenderer, ITemporalRenderer2).MostCurrentRendererEnabled = True

      'this is a desktop only code which requires assemblies CartoUI and Framework
      '((ITemporalRenderer2)temporalRenderer).PropPageMostCurrentRenderer = rendererPropPage.ClassID;
    End If

    'set the track renderer
    uniqueValrenderer = CreateTrackUniqueValueRenderer(featureClass, eventName)
    If Not Nothing Is uniqueValrenderer Then
      Dim trackSymbolenderer As ITrackSymbologyRenderer = TryCast(trackingRenderer, ITrackSymbologyRenderer)
      trackSymbolenderer.TrackSymbologyRenderer = CType(uniqueValrenderer, IFeatureRenderer)
      CType(temporalRenderer, ITemporalRenderer2).TrackRendererEnabled = True
      CType(temporalRenderer, ITemporalRenderer2).SmoothTracks = True

      'this is a desktop only code which requires assemblies CartoUI and Framework
      '((ITemporalRenderer2)temporalRenderer).PropPageTrackRenderer = rendererPropPage.ClassID;
    End If

    Return temporalRenderer
  End Function

End Class