About the Dynamic display layer Sample
[C#]
MyDynamicLayerClass.cs
using System;
using System.Data;
using System.Drawing;
using System.Timers;
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;
using ESRI.ArcGIS.ADF;
namespace MyDynamicLayer
{
/// <summary>
/// This layer implements a DynamicLayer based on the DynamicLayerBase base-class
/// </summary>
[Guid("27FB44EB-0426-415f-BFA3-D1581056C0C4")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("MyDynamicLayer.MyDynamicLayerClass")]
public sealed class MyDynamicLayerClass : ESRI.ArcGIS.ADF.BaseClasses.BaseDynamicLayer
{
#region class members
private IPoint m_point = null;
private bool m_bDynamicGlyphsCreated = false;
private bool m_bOnce = true;
private IDynamicGlyph[] m_markerGlyphs = null;
private IDynamicGlyph m_textGlyph = null;
private Timer m_updateTimer = null;
private double m_extentMaxX = 1000.0;
private double m_extentMaxY = 1000.0;
private double m_extentMinX = 0.0;
private double m_extentMinY = 0.0;
private IDynamicGlyphFactory2 m_dynamicGlyphFactory = null;
private IDynamicSymbolProperties m_dynamicSymbolProps = null;
private IDynamicCompoundMarker m_dynamicCompoundMarker = null;
private DataTable m_table = null;
private const int m_nNumOfItems = 100;
#endregion
#region class constructor
public MyDynamicLayerClass() : base()
{
m_table = new DataTable ("rows");
m_table.Columns.Add("OID", typeof (int)); //0
m_table.Columns.Add("X", typeof(double)); //1
m_table.Columns.Add("Y", typeof(double)); //2
m_table.Columns.Add("STEPX", typeof(double)); //3
m_table.Columns.Add("STEPY", typeof(double)); //4
m_table.Columns.Add("HEADING", typeof(double)); //5
m_table.Columns.Add("TYPE", typeof(int)); //6
//set the ID column to be AutoIncremented
m_table.Columns[0].AutoIncrement = true;
m_point = new PointClass();
//set an array to store the glyphs used to symbolize the tracked object
m_markerGlyphs = new IDynamicGlyph[3];
//set the update timer for the layer
m_updateTimer = new Timer(50);
m_updateTimer.Enabled = false;
m_updateTimer.Elapsed += new ElapsedEventHandler(OnLayerUpdateEvent);
}
#endregion
#region overriden methods
/// <summary>
/// The dynamic layer draw method
/// </summary>
/// <param name="DynamicDrawPhase">the current drawphase of the dynamic drawing</param>
/// <param name="Display">the ActiveView's display</param>
/// <param name="DynamicDisplay">the ActiveView's dynamic display</param>
public override void DrawDynamicLayer(ESRI.ArcGIS.Display.esriDynamicDrawPhase DynamicDrawPhase, ESRI.ArcGIS.Display.IDisplay Display, ESRI.ArcGIS.Display.IDynamicDisplay DynamicDisplay)
{
try
{
//make sure that the display is valid as well as that the layer is visible
if (null == DynamicDisplay || null == Display || !this.m_visible)
return;
//make sure that the current drawphase is immediate. In this sample there is no use of the
//compiled drawPhase. Use the esriDDPCompiled drawPhase in order to draw semi-static items (items
//which have update rate lower than the display update rate).
if (DynamicDrawPhase != esriDynamicDrawPhase.esriDDPImmediate)
return;
if (m_bOnce)
{
//cast the DynamicDisplay into DynamicGlyphFactory
m_dynamicGlyphFactory = DynamicDisplay.DynamicGlyphFactory as IDynamicGlyphFactory2;
//cast the DynamicDisplay into DynamicSymbolProperties
m_dynamicSymbolProps = DynamicDisplay as IDynamicSymbolProperties;
//cast the compound marker symbol
m_dynamicCompoundMarker = DynamicDisplay as IDynamicCompoundMarker;
IntializeLayerData (Display.DisplayTransformation);
GetLayerExtent();
m_bOnce = false;
}
//get the display fitted bounds
m_extentMaxX = Display.DisplayTransformation.FittedBounds.XMax;
m_extentMaxY = Display.DisplayTransformation.FittedBounds.YMax;
m_extentMinX = Display.DisplayTransformation.FittedBounds.XMin;
m_extentMinY = Display.DisplayTransformation.FittedBounds.YMin;
//create the dynamic symbols for the layer
if (!m_bDynamicGlyphsCreated)
{
this.CreateDynamicSymbols(m_dynamicGlyphFactory);
m_bDynamicGlyphsCreated = true;
}
double X, Y, heading;
int type;
//iterate through the layers' items
foreach (DataRow r in m_table.Rows)
{
if (r[1] is DBNull || r[2] is DBNull)
continue;
//get the item's coordinate, heading and type
X = Convert.ToDouble(r[1]);
Y = Convert.ToDouble(r[2]);
heading = Convert.ToDouble(r[5]);
type = Convert.ToInt32(r[6]);
//assign the items' coordinate to the cached point
m_point.PutCoords(X, Y);
//set the symbol's properties
switch (type)
{
case 0:
//set the heading of the current symbols' text
m_dynamicSymbolProps.set_Heading(esriDynamicSymbolType.esriDSymbolText, 0.0f);
m_dynamicSymbolProps.set_Heading(esriDynamicSymbolType.esriDSymbolMarker, 0.0f);
//set the symbol alignment so that it will align with the screen
m_dynamicSymbolProps.set_RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker, esriDynamicSymbolRotationAlignment.esriDSRAScreen);
//set the text alignment so that it will also align with the screen
m_dynamicSymbolProps.set_RotationAlignment(esriDynamicSymbolType.esriDSymbolText, esriDynamicSymbolRotationAlignment.esriDSRAScreen);
//scale the item
m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 0.8f, 0.8f);
//set the items' color (blue)
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 0.0f, 0.0f, 1.0f, 1.0f); // Blue
//assign the item's glyph to the dynamic-symbol
m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker, m_markerGlyphs[0]);
//set the labels text glyph
m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolText, m_textGlyph);
//set the color of the text
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolText, 1.0f, 1.0f, 0.0f, 1.0f); // Yellow
//draw the item as a compound marker. This means that you do not have to draw the items and their
//accompanying labels separately, and thus allow you to write less code as well as get better
//performance.
m_dynamicCompoundMarker.DrawCompoundMarker4
(m_point,
//"TOP",
//"BOTTOM",
"Item " + Convert.ToString(r[0]),
heading.ToString("###.##"),
m_point.X.ToString("###.#####"),
m_point.Y.ToString("###.#####"));
break;
case 1:
//set the heading of the current symbol
m_dynamicSymbolProps.set_Heading(esriDynamicSymbolType.esriDSymbolMarker, (float)heading);
//set the symbol alignment so that it will align with towards the symbol heading
m_dynamicSymbolProps.set_RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker, esriDynamicSymbolRotationAlignment.esriDSRANorth);
m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f);
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 0.0f, 1.0f, 0.6f, 1.0f); // GREEN
m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker, m_markerGlyphs[1]);
//draw the current location
DynamicDisplay.DrawMarker(m_point);
break;
case 2:
//set the heading of the current symbol
m_dynamicSymbolProps.set_Heading(esriDynamicSymbolType.esriDSymbolMarker, (float)heading);
//set the symbol alignment so that it will align with towards the symbol heading
m_dynamicSymbolProps.set_RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker, esriDynamicSymbolRotationAlignment.esriDSRANorth);
m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.1f, 1.1f);
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f, 1.0f, 1.0f); // WHITE
m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker, m_markerGlyphs[2]);
//draw the current location
DynamicDisplay.DrawMarker(m_point);
break;
}
}
// by setting immediate flag to false, we signal the dynamic display that the layer is current.
base.m_bIsImmediateDirty = false;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
/// <summary>
/// Returns the UID (ProgID or CLSID)
/// </summary>
public override UID ID
{
get
{
m_uid.Value = "MyDynamicLayer.MyDynamicLayerClass";
return m_uid;
}
}
#endregion
#region public methods
public void Connect()
{
m_updateTimer.Enabled = true;
}
public void Disconnect()
{
m_updateTimer.Enabled = false;
}
public DataRow NewItem ()
{
if (m_table == null)
return null;
else
return m_table.NewRow ();
}
public void AddItem (DataRow row)
{
if (row == null)
return;
else
m_table.Rows.Add (row);
}
#endregion
#region private utility methods
/// <summary>
/// create the layer's glyphs used to set the symbol of the dynamic-layer items
/// </summary>
/// <param name="pDynamicGlyphFactory"></param>
private void CreateDynamicSymbols(IDynamicGlyphFactory2 pDynamicGlyphFactory)
{
try
{
//set the background color
IColor color = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor (Color.FromArgb (255, 255, 255)) as IColor;
// Create Character Marker Symbols glyph
// --------------------------------------
ICharacterMarkerSymbol characterMarkerSymbol = new CharacterMarkerSymbolClass ();
characterMarkerSymbol.Color = color as IColor;
characterMarkerSymbol.Font = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToStdFont(new Font("ESRI Environmental & Icons", 32));
characterMarkerSymbol.Size = 40;
characterMarkerSymbol.Angle = 0;
characterMarkerSymbol.CharacterIndex = 36;
//create the glyph from the marker symbol
m_markerGlyphs[0] = pDynamicGlyphFactory.CreateDynamicGlyph(characterMarkerSymbol as ISymbol);
characterMarkerSymbol.Size = 32;
characterMarkerSymbol.CharacterIndex = 224;
//create the glyph from the marker symbol
m_markerGlyphs[1] = pDynamicGlyphFactory.CreateDynamicGlyph(characterMarkerSymbol as ISymbol);
// Create the glyph from embedded bitmap
// -----------------------------------
// Sets the transparency color
IColor transparentColor = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.FromArgb(255, 255, 255)) as IColor;
Bitmap bitmap = new Bitmap (GetType (), "B2.bmp");
m_markerGlyphs[2] = pDynamicGlyphFactory.CreateDynamicGlyphFromBitmap(esriDynamicGlyphType.esriDGlyphMarker, bitmap.GetHbitmap ().ToInt32 (), false, transparentColor);
// Create a glyph for the labels text, use the first 'internal' text glyph
// ------------------------------------------------------------------------
m_textGlyph = pDynamicGlyphFactory.get_DynamicGlyph(1, esriDynamicGlyphType.esriDGlyphText, 1);
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
/// <summary>
/// timer elapsed event handler, used to update the layer
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
/// <remarks>This layer has synthetic data, and therefore need the timer in order
/// to update the layers' items.</remarks>
private void OnLayerUpdateEvent(object sender, ElapsedEventArgs e)
{
try
{
double X, Y, stepX, stepY, heading;
//iterate through the layers' records
foreach (DataRow r in m_table.Rows)
{
if (r[1] is DBNull || r[2] is DBNull)
continue;
//get the current item location and the item's steps
X = Convert.ToDouble(r[1]);
Y = Convert.ToDouble(r[2]);
stepX = Convert.ToDouble(r[3]);
stepY = Convert.ToDouble(r[4]);
//increment the item's location
X += stepX;
Y += stepY;
//test that the item's location is within the fitted bounds
if (X > m_extentMaxX) stepX = -Math.Abs(stepX);
if (X < m_extentMinX) stepX = Math.Abs(stepX);
if (Y > m_extentMaxY) stepY = -Math.Abs(stepY);
if (Y < m_extentMinY) stepY = Math.Abs(stepY);
//calculate the item's heading
heading = (360.0 + 90.0 - Math.Atan2(stepY, stepX) * 180 / Math.PI) % 360.0;
//update the item's record
r[1] = X;
r[2] = Y;
r[3] = stepX;
r[4] = stepY;
r[5] = heading;
lock (m_table)
{
r.AcceptChanges();
}
//set the dirty flag to true in order to let the DynamicDisplay that the layer needs redraw.
base.m_bIsImmediateDirty = true;
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
/// <summary>
/// Calculates the layer extent
/// </summary>
private void GetLayerExtent()
{
if (null == m_table)
return;
IEnvelope env = new EnvelopeClass();
env.SpatialReference = base.m_spatialRef;
IPoint point = new PointClass();
foreach (DataRow r in m_table.Rows)
{
if (r[1] is DBNull || r[2] is DBNull)
continue;
point.Y = Convert.ToDouble(r[3]);
point.X = Convert.ToDouble(r[4]);
env.Union(point.Envelope);
}
base.m_extent = env;
}
/// <summary>
/// Initialize the synthetic data of the layer
/// </summary>
private void IntializeLayerData (IDisplayTransformation displayTransformation)
{
try
{
//get the map's fitted bounds
IEnvelope extent = displayTransformation.FittedBounds;
//calculate the step for which will be used to increment the items
double XStep = extent.Width / 5000.0;
double YStep = extent.Height / 5000.0;
Random rnd = new Random ();
double stepX, stepY;
//generate the items
for (int i = 0; i < m_nNumOfItems; i++)
{
//calculate the step for each item
stepX = XStep * rnd.NextDouble ();
stepY = YStep * rnd.NextDouble ();
//create new record
DataRow r = NewItem ();
//set the item's coordinate
r[1] = extent.XMin + rnd.NextDouble () * (extent.XMax - extent.XMin);
r[2] = extent.YMin + rnd.NextDouble () * (extent.YMax - extent.YMin);
//set the item's steps
r[3] = stepX;
r[4] = stepY;
//calculate the heading
r[5] = (360.0 + 90.0 - Math.Atan2 (stepY, stepX) * 180 / Math.PI) % 360.0;
//add a type ID in order to define the symbol for the item
switch (i % 3)
{
case 0:
r[6] = 0;
break;
case 1:
r[6] = 1;
break;
case 2:
r[6] = 2;
break;
}
//add the new item record to the table
AddItem (r);
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine (ex.Message);
}
}
#endregion
}
}
[Visual Basic .NET]
MyDynamicLayerClass.vb
Imports Microsoft.VisualBasic
Imports System
Imports System.Data
Imports System.Drawing
Imports System.Timers
Imports System.Runtime.InteropServices
Imports System.Collections.Generic
Imports ESRI.ArcGIS.ADF.CATIDs
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Display
Imports ESRI.ArcGIS.esriSystem
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.SystemUI
Imports ESRI.ArcGIS.ADF
''' <summary>
''' This layer implements a DynamicLayer based on the DynamicLayerBase base-class
''' </summary>
<Guid("27FB44EB-0426-415f-BFA3-D1581056C0C4"), ComVisible(True), ClassInterface(ClassInterfaceType.None), ProgId("MyDynamicLayerClass")> _
Public NotInheritable Class MyDynamicLayerClass : Inherits ESRI.ArcGIS.ADF.BaseClasses.BaseDynamicLayer
#Region "class members"
Private m_point As IPoint = Nothing
Private m_bDynamicGlyphsCreated As Boolean = False
Private m_bOnce As Boolean = True
Private m_markerGlyphs As IDynamicGlyph() = Nothing
Private m_textGlyph As IDynamicGlyph = Nothing
Private m_updateTimer As Timer = Nothing
Private m_extentMaxX As Double = 1000.0
Private m_extentMaxY As Double = 1000.0
Private m_extentMinX As Double = 0.0
Private m_extentMinY As Double = 0.0
Private m_dynamicGlyphFactory As IDynamicGlyphFactory2 = Nothing
Private m_dynamicSymbolProps As IDynamicSymbolProperties = Nothing
Private m_dynamicCompoundMarker As IDynamicCompoundMarker = Nothing
Private m_table As DataTable = Nothing
Private Const m_nNumOfItems As Integer = 100
#End Region
#Region "class constructor"
Public Sub New()
MyBase.New()
m_table = New DataTable ("rows")
m_table.Columns.Add("OID", GetType(Integer)) '0
m_table.Columns.Add("X", GetType(Double)) '1
m_table.Columns.Add("Y", GetType(Double)) '2
m_table.Columns.Add("STEPX", GetType(Double)) '3
m_table.Columns.Add("STEPY", GetType(Double)) '4
m_table.Columns.Add("HEADING", GetType(Double)) '5
m_table.Columns.Add("TYPE", GetType(Integer)) '6
'set the ID column to be AutoIncremented
m_table.Columns(0).AutoIncrement = True
m_point = New PointClass()
'set an array to store the glyphs used to symbolize the tracked object
m_markerGlyphs = New IDynamicGlyph(2){}
'set the update timer for the layer
m_updateTimer = New Timer(50)
m_updateTimer.Enabled = False
AddHandler m_updateTimer.Elapsed, AddressOf OnLayerUpdateEvent
End Sub
#End Region
#Region "overridden methods"
''' <summary>
''' The dynamic layer draw method
''' </summary>
''' <param name="DynamicDrawPhase">the current drawphase of the dynamic drawing</param>
''' <param name="Display">the ActiveView's display</param>
''' <param name="DynamicDisplay">the ActiveView's dynamic display</param>
Public Overrides Sub DrawDynamicLayer(ByVal DynamicDrawPhase As ESRI.ArcGIS.Display.esriDynamicDrawPhase, ByVal Display As ESRI.ArcGIS.Display.IDisplay, ByVal DynamicDisplay As ESRI.ArcGIS.Display.IDynamicDisplay)
Try
'make sure that the display is valid as well as that the layer is visible
If Nothing Is DynamicDisplay OrElse Nothing Is Display OrElse (Not Me.m_visible) Then
Return
End If
'make sure that the current drawphase is immediate. In this sample there is no use of the
'compiled drawPhase. Use the esriDDPCompiled drawPhase in order to draw semi-static items (items
'which have update rate lower than the display update rate).
If DynamicDrawPhase <> esriDynamicDrawPhase.esriDDPImmediate Then
Return
End If
If m_bOnce Then
'cast the DynamicDisplay into DynamicGlyphFactory
m_dynamicGlyphFactory = TryCast(DynamicDisplay.DynamicGlyphFactory, IDynamicGlyphFactory2)
'cast the DynamicDisplay into DynamicSymbolProperties
m_dynamicSymbolProps = TryCast(DynamicDisplay, IDynamicSymbolProperties)
'cast the compound marker symbol
m_dynamicCompoundMarker = TryCast(DynamicDisplay, IDynamicCompoundMarker)
IntializeLayerData (Display.DisplayTransformation)
GetLayerExtent()
m_bOnce = False
End If
'get the display fitted bounds
m_extentMaxX = Display.DisplayTransformation.FittedBounds.XMax
m_extentMaxY = Display.DisplayTransformation.FittedBounds.YMax
m_extentMinX = Display.DisplayTransformation.FittedBounds.XMin
m_extentMinY = Display.DisplayTransformation.FittedBounds.YMin
'create the dynamic symbols for the layer
If (Not m_bDynamicGlyphsCreated) Then
Me.CreateDynamicSymbols(m_dynamicGlyphFactory)
m_bDynamicGlyphsCreated = True
End If
Dim X, Y, heading As Double
Dim type As Integer
'iterate through the layers' items
For Each r As DataRow In m_table.Rows
If TypeOf r(1) Is DBNull OrElse TypeOf r(2) Is DBNull Then
Continue For
End If
'get the item's coordinate, heading and type
X = Convert.ToDouble(r(1))
Y = Convert.ToDouble(r(2))
heading = Convert.ToDouble(r(5))
type = Convert.ToInt32(r(6))
'assign the items' coordinate to the cached point
m_point.PutCoords(X, Y)
'set the symbol's properties
Select Case type
Case 0
'set the heading of the current symbols' text
m_dynamicSymbolProps.Heading(esriDynamicSymbolType.esriDSymbolText)= 0.0f
m_dynamicSymbolProps.Heading(esriDynamicSymbolType.esriDSymbolMarker)= 0.0f
'set the symbol alignment so that it will align with the screen
m_dynamicSymbolProps.RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker)=esriDynamicSymbolRotationAlignment.esriDSRAScreen
'set the text alignment so that it will also align with the screen
m_dynamicSymbolProps.RotationAlignment(esriDynamicSymbolType.esriDSymbolText)= esriDynamicSymbolRotationAlignment.esriDSRAScreen
'scale the item
m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 0.8f, 0.8f)
'set the items' color (blue)
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 0.0f, 0.0f, 1.0f, 1.0f) ' Blue
'assign the item's glyph to the dynamic-symbol
m_dynamicSymbolProps.DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker)= m_markerGlyphs(0)
'set the labels text glyph
m_dynamicSymbolProps.DynamicGlyph(esriDynamicSymbolType.esriDSymbolText)= m_textGlyph
'set the color of the text
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolText, 1.0f, 1.0f, 0.0f, 1.0f) ' Yellow
'draw the item as a compound marker. This means that you do not have to draw the items and their
'accompanying labels separately, and thus allow you to write less code as well as get better
'performance.
'"TOP",
'"BOTTOM",
m_dynamicCompoundMarker.DrawCompoundMarker4 (m_point, "Item " & Convert.ToString(r(0)), heading.ToString("###.##"), m_point.X.ToString("###.#####"), m_point.Y.ToString("###.#####"))
Case 1
'set the heading of the current symbol
m_dynamicSymbolProps.Heading(esriDynamicSymbolType.esriDSymbolMarker)= CSng(heading)
'set the symbol alignment so that it will align with towards the symbol heading
m_dynamicSymbolProps.RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker)= esriDynamicSymbolRotationAlignment.esriDSRANorth
m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f)
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 0.0f, 1.0f, 0.6f, 1.0f) ' GREEN
m_dynamicSymbolProps.DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker)= m_markerGlyphs(1)
'draw the current location
DynamicDisplay.DrawMarker(m_point)
Case 2
'set the heading of the current symbol
m_dynamicSymbolProps.Heading(esriDynamicSymbolType.esriDSymbolMarker)= CSng(heading)
'set the symbol alignment so that it will align with towards the symbol heading
m_dynamicSymbolProps.RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker)= esriDynamicSymbolRotationAlignment.esriDSRANorth
m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.1f, 1.1f)
m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f, 1.0f, 1.0f) ' WHITE
m_dynamicSymbolProps.DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker)= m_markerGlyphs(2)
'draw the current location
DynamicDisplay.DrawMarker(m_point)
End Select
Next r
' by setting immediate flag to false, we signal the dynamic display that the layer is current.
MyBase.m_bIsImmediateDirty = False
Catch ex As Exception
System.Diagnostics.Trace.WriteLine(ex.Message)
End Try
End Sub
''' <summary>
''' Returns the UID (ProgID or CLSID)
''' </summary>
Public Overrides ReadOnly Property ID() As UID
Get
m_uid.Value = "MyDynamicLayer.MyDynamicLayerClass"
Return m_uid
End Get
End Property
#End Region
#Region "public methods"
Public Sub Connect()
m_updateTimer.Enabled = True
End Sub
Public Sub Disconnect()
m_updateTimer.Enabled = False
End Sub
Public Function NewItem() As DataRow
If m_table Is Nothing Then
Return Nothing
Else
Return m_table.NewRow ()
End If
End Function
Public Sub AddItem(ByVal row As DataRow)
If row Is Nothing Then
Return
Else
m_table.Rows.Add (row)
End If
End Sub
#End Region
#Region "private utility methods"
''' <summary>
''' create the layer's glyphs used to set the symbol of the dynamic-layer items
''' </summary>
''' <param name="pDynamicGlyphFactory"></param>
Private Sub CreateDynamicSymbols(ByVal pDynamicGlyphFactory As IDynamicGlyphFactory2)
Try
'set the background color
Dim backgroundColor As IColor
backgroundColor = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.FromArgb(255, 255, 255))
' Create Character Marker Symbols glyph
' --------------------------------------
Dim characterMarkerSymbol As ICharacterMarkerSymbol = New CharacterMarkerSymbolClass()
characterMarkerSymbol.Color = TryCast(backgroundColor, IColor)
characterMarkerSymbol.Font = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToStdFont(New Font("ESRI Environmental & Icons", 32))
characterMarkerSymbol.Size = 40
characterMarkerSymbol.Angle = 0
characterMarkerSymbol.CharacterIndex = 36
'create the glyph from the marker symbol
m_markerGlyphs(0) = pDynamicGlyphFactory.CreateDynamicGlyph(TryCast(characterMarkerSymbol, ISymbol))
characterMarkerSymbol.Size = 32
characterMarkerSymbol.CharacterIndex = 224
'create the glyph from the marker symbol
m_markerGlyphs(1) = pDynamicGlyphFactory.CreateDynamicGlyph(TryCast(characterMarkerSymbol, ISymbol))
' Create the glyph from embedded bitmap
' -----------------------------------
' Sets the transparency color
Dim transparenyColor As IColor
transparenyColor = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.FromArgb(255, 255, 255))
Dim bitmap as new Bitmap(me.GetType(), "B2.bmp")
m_markerGlyphs(2) = pDynamicGlyphFactory.CreateDynamicGlyphFromBitmap(esriDynamicGlyphType.esriDGlyphMarker,bitmap.GetHbitmap.ToInt32(),False,transparenyColor)
' Create a glyph for the labels text, use the first 'internal' text glyph
' ------------------------------------------------------------------------
m_textGlyph = pDynamicGlyphFactory.DynamicGlyph(1, esriDynamicGlyphType.esriDGlyphText, 1)
Catch ex As Exception
System.Diagnostics.Trace.WriteLine(ex.Message)
End Try
End Sub
''' <summary>
''' timer elapsed event handler, used to update the layer
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
''' <remarks>This layer has synthetic data, and therefore need the timer in order
''' to update the layers' items.</remarks>
Private Sub OnLayerUpdateEvent(ByVal sender As Object, ByVal e As ElapsedEventArgs)
Try
Dim X, Y, stepX, stepY, heading As Double
'iterate through the layers' records
For Each r As DataRow In m_table.Rows
If TypeOf r(1) Is DBNull OrElse TypeOf r(2) Is DBNull Then
Continue For
End If
'get the current item location and the item's steps
X = Convert.ToDouble(r(1))
Y = Convert.ToDouble(r(2))
stepX = Convert.ToDouble(r(3))
stepY = Convert.ToDouble(r(4))
'increment the item's location
X += stepX
Y += stepY
'test that the item's location is within the fitted bounds
If X > m_extentMaxX Then
stepX = -Math.Abs(stepX)
End If
If X < m_extentMinX Then
stepX = Math.Abs(stepX)
End If
If Y > m_extentMaxY Then
stepY = -Math.Abs(stepY)
End If
If Y < m_extentMinY Then
stepY = Math.Abs(stepY)
End If
'calculate the item's heading
heading = (360.0 + 90.0 - Math.Atan2(stepY, stepX) * 180 / Math.PI) Mod 360.0
'update the item's record
r(1) = X
r(2) = Y
r(3) = stepX
r(4) = stepY
r(5) = heading
SyncLock m_table
r.AcceptChanges()
End SyncLock
'set the dirty flag to true in order to let the DynamicDisplay that the layer needs redraw.
MyBase.m_bIsImmediateDirty = True
Next r
Catch ex As Exception
System.Diagnostics.Trace.WriteLine(ex.Message)
End Try
End Sub
''' <summary>
''' Calculates the layer extent
''' </summary>
Private Sub GetLayerExtent()
If Nothing Is m_table Then
Return
End If
Dim env As IEnvelope = New EnvelopeClass()
env.SpatialReference = MyBase.m_spatialRef
Dim point As IPoint = New PointClass()
For Each r As DataRow In m_table.Rows
If TypeOf r(1) Is DBNull OrElse TypeOf r(2) Is DBNull Then
Continue For
End If
point.Y = Convert.ToDouble(r(3))
point.X = Convert.ToDouble(r(4))
env.Union(point.Envelope)
Next r
MyBase.m_extent = env
End Sub
''' <summary>
''' Initialize the synthetic data of the layer
''' </summary>
Private Sub IntializeLayerData(ByVal displayTransformation As IDisplayTransformation)
Try
'get the map's fitted bounds
Dim extent As IEnvelope = displayTransformation.FittedBounds
'calculate the step for which will be used to increment the items
Dim XStep As Double = extent.Width / 5000.0
Dim YStep As Double = extent.Height / 5000.0
Dim rnd As Random = New Random ()
Dim stepX, stepY As Double
'generate the items
For i As Integer = 0 To m_nNumOfItems - 1
'calculate the step for each item
stepX = XStep * rnd.NextDouble ()
stepY = YStep * rnd.NextDouble ()
'create new record
Dim r As DataRow = NewItem ()
'set the item's coordinate
r(1) = extent.XMin + rnd.NextDouble () * (extent.XMax - extent.XMin)
r(2) = extent.YMin + rnd.NextDouble () * (extent.YMax - extent.YMin)
'set the item's steps
r(3) = stepX
r(4) = stepY
'calculate the heading
r(5) = (360.0 + 90.0 - Math.Atan2 (stepY, stepX) * 180 / Math.PI) Mod 360.0
'add a type ID in order to define the symbol for the item
Select Case i Mod 3
Case 0
r(6) = 0
Case 1
r(6) = 1
Case 2
r(6) = 2
End Select
'add the new item record to the table
AddItem (r)
Next i
Catch ex As Exception
System.Diagnostics.Trace.WriteLine (ex.Message)
End Try
End Sub
#End Region
End Class