ObjectLocationClass.cs
Dynamic display — tracking dynamic object
ObjectLocationClass.cs
// Copyright 2006 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 

using System;
using System.Data;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using ESRI.ArcGIS.ADF.CATIDs;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.SystemUI;

namespace DynamicObjectTracking
{
  /// <summary>
  /// A custom layer used in order to draw the tracked object position
  /// </summary>
  [Guid("01E3C94B-B61C-412b-8476-2F8C2237787E")]
  [ComVisible(true)]
  [ClassInterface(ClassInterfaceType.None)]
  [ProgId("DynamicObjectTracking.ObjectLocationClass")]
  public sealed class ObjectLocationClass : CustomLayerBase, IDynamicLayer
  {
    #region class members
    private int m_trailLength = 10;
    private IPoint m_point = null;
    private bool m_bIsImmediateDirty = false;
    private bool m_bOnce = true;
    private int m_nRecompileRate = -1;
    private bool m_bDynamicGlyphsCreated = false;
    private IDynamicGlyph[] m_markerGlyphs = null;
    private IDynamicGlyphFactory m_dynamicGlyphFactory = null;
    private IDynamicSymbolProperties m_dynamicSymbolProps = null;
    #endregion

    #region class constructor
    public ObjectLocationClass() : base()
    {
      //set the name of the layer
      this.m_sName = "Tracks";

      //add additional column to the table to store the navigation data
      m_table.Columns.Add("NavigationData", typeof(NavigationData));     //1

      m_point = new PointClass();

      //set an array to store the glyphs used to symbol the tracked object
      m_markerGlyphs = new IDynamicGlyph[2];
    }
    #endregion

    
    /// <summary>
    /// the ILayer.Draw method. Declared as an abstract by the base class and thus must be overriden
    /// </summary>
    /// <param name="drawPhase"></param>
    /// <param name="Display"></param>
    /// <param name="trackCancel"></param>
    public override void Draw(esriDrawPhase drawPhase, IDisplay Display, ITrackCancel trackCancel)
    {
      
    }

    /// <summary>
    /// Returns the UID (ProgID or CLSID)
    /// </summary>
    public override UID ID
    {
      get
      {
        m_uid.Value = "DynamicObjectTracking.ObjectLocationClass";
        return m_uid;
      }
    }
    
    /// <summary>
    /// add new navigation info for the tracked object
    /// </summary>
    /// <param name="navigationData"></param>
    public void AddNavigationData(NavigationData navigationData)
    {
      try
      {
        //create a new record in the layer's table
        DataRow r = base.NewItem();
        //assign the navigation info data into the new record
        r[1] = navigationData;

        //add the record to the table
        lock (m_table)
          base.AddItem(r);

        //get read of old records
        if (base.NumOfRecords > m_trailLength)
        {
          //delete the first item
          DataRow oldRow = base[0];
          lock (m_table)
          {
            oldRow.Delete();
            m_table.AcceptChanges();
          }
        }
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.WriteLine(ex.Message);
      }
    }
    /// <summary>
    /// control over the tracked item last locations trail
    /// </summary>
    public int TrailLength
    {
      get { return m_trailLength;  }
      set { m_trailLength = value; }
    }

    #region IDynamicLayer Members

    /// <summary>
    /// The dynamic layer draw method
    /// </summary>
    /// <param name="DynamicDrawPhase">the current drawphase of the drawing</param>
    /// <param name="Display">the ActiveView's display</param>
    /// <param name="DynamicDisplay">the ActiveView's dynamic display</param>
    public void DrawDynamicLayer(esriDynamicDrawPhase DynamicDrawPhase, IDisplay Display, IDynamicDisplay DynamicDisplay)
    {
      try
      {
        if (Display == null || !this.m_visible)
          return;

        //make sure that the current drawphase if immediate
        if (esriDynamicDrawPhase.esriDDPImmediate != DynamicDrawPhase)
          return;

        if (m_bOnce)
        {
          //cast the DynamicDisplay into DynamicGlyphFactory
          m_dynamicGlyphFactory = DynamicDisplay.DynamicGlyphFactory;
          //cast the DynamicDisplay into DynamicSymbolProperties
          m_dynamicSymbolProps = DynamicDisplay as IDynamicSymbolProperties;
          m_bOnce = false;
        }

        //create the dynamic symbols for the layer
        if (!m_bDynamicGlyphsCreated)
        {
          this.CreateDynamicSymbols(m_dynamicGlyphFactory);

          m_bDynamicGlyphsCreated = true;
        }

        //set the symbol alignment so that it will align with towards the symbol heading
        m_dynamicSymbolProps.set_RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker, esriDynamicSymbolRotationAlignment.esriDSRANorth);

        NavigationData navigationData;
        int i = 0;

        //iterate through the records of the dynamic object locations
        foreach (DataRow r in this)
        {
          if (r[1] is DBNull)
            continue;
 
          //set the symbol's properties
          if (i == (m_trailLength - 1)) //in case of the current location record
          {
            m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.3f, 1.3f);
            m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 0.0f, 0.0f, 1.0f); // RED
            m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker, m_markerGlyphs[0]);
          }
          else //for each of the trail locations record
          {
            m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f);
            m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 0.0f, 1.0f, 0.0f, 1.0f); // GREEN
            m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker, m_markerGlyphs[1]);
          }
          i++;

          //get the navigation data from the record
          navigationData = (NavigationData)r[1];
          //assign the coordinate to the map point
          m_point.PutCoords(navigationData.X, navigationData.Y);

          //set the heading of the current symbol
          m_dynamicSymbolProps.set_Heading(esriDynamicSymbolType.esriDSymbolMarker, (float)navigationData.Azimuth);

          //draw the current location
          DynamicDisplay.DrawMarker(m_point);
        }
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.WriteLine(ex.Message);
      }
    }

    /// <summary>
    /// get the dirty flag of the layer
    /// </summary>
    /// <param name="DynamicDrawPhase"></param>
    /// <returns></returns>
    public bool get_DynamicLayerDirty(esriDynamicDrawPhase DynamicDrawPhase)
    {
      if (DynamicDrawPhase == esriDynamicDrawPhase.esriDDPImmediate)
        return m_bIsImmediateDirty;

      return false;
    }

    /// <summary>
    /// set the dirty flag of the layer
    /// </summary>
    /// <param name="DynamicDrawPhase"></param>
    /// <param name="Dirty"></param>
    public void set_DynamicLayerDirty(esriDynamicDrawPhase DynamicDrawPhase, bool Dirty)
    {
      if (DynamicDrawPhase == esriDynamicDrawPhase.esriDDPImmediate)
        m_bIsImmediateDirty = Dirty;
    }

    /// <summary>
    /// This is the rate in which the DynamicDisplay builds the Display-Lists of the 'compiled'
    /// DrawPhase
    /// </summary>
    public int DynamicRecompileRate
    {
      get { return m_nRecompileRate; }
    }

    #endregion

    /// <summary>
    /// create the layer's glyphs used to set the symbol of the tracked object
    /// </summary>
    /// <param name="pDynamicGlyphFactory"></param>
    private void CreateDynamicSymbols(IDynamicGlyphFactory pDynamicGlyphFactory)
    {
      try
      {
        // Sets the transparency color
        IRgbColor tranparencyColor = new RgbColorClass();
        tranparencyColor.Red = 0;
        tranparencyColor.Green = 0;
        tranparencyColor.Blue = 0;

        IRgbColor color = new RgbColorClass();
        color.Red = 255;
        color.Green = 255;
        color.Blue = 255;


        // Create Character Marker Symbols
        // -------------------------------
        stdole.IFont fontEsri;
        fontEsri = new stdole.StdFontClass();
        fontEsri.Name = "ESRI Default Marker";
        fontEsri.Size = 32;
        ICharacterMarkerSymbol characterMarkerSymbol = new CharacterMarkerSymbolClass();
        characterMarkerSymbol.Color = color as IColor;
        characterMarkerSymbol.Font = fontEsri as stdole.IFontDisp;
        characterMarkerSymbol.Size = 40;
        characterMarkerSymbol.Angle = 0;
        characterMarkerSymbol.CharacterIndex = 73;

        //create the glyph from the marker symbol
        m_markerGlyphs[0] = pDynamicGlyphFactory.CreateDynamicGlyph(characterMarkerSymbol as ISymbol);

        characterMarkerSymbol.Size = 32;
        characterMarkerSymbol.CharacterIndex = 72;

        //create the glyph from the marker symbol
        m_markerGlyphs[1] = pDynamicGlyphFactory.CreateDynamicGlyph(characterMarkerSymbol as ISymbol);
      }
      catch (Exception ex)
      {
        System.Diagnostics.Trace.WriteLine(ex.Message);
      }
    }
  }
}