TrackObject.cs
// Copyright 2012 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.Xml; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; using ESRI.ArcGIS.Controls; using System.Collections.Generic; using Microsoft.Win32; using ESRI.ArcGIS.ADF.BaseClasses; using ESRI.ArcGIS.ADF.CATIDs; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.DataSourcesFile; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.SystemUI; using ESRI.ArcGIS.ADF; using ESRI.ArcGIS; namespace DynamicObjectTracking { /// <summary> /// A user defined data structure /// </summary> public struct NavigationData { public double X; public double Y; public double Azimuth; /// <summary> /// struct constructor /// </summary> /// <param name="x">map x coordinate</param> /// <param name="y">map x coordinate</param> /// <param name="azimuth">the new map azimuth</param> public NavigationData(double x, double y, double azimuth) { X = x; Y = y; Azimuth = azimuth; } } /// <summary> /// This command triggers the tracking functionality using Dynamic Display /// </summary> [Guid("803D4188-AB2F-49f9-9340-42C809887063")] [ComVisible(true)] [ClassInterface(ClassInterfaceType.None)] [ProgId("DynamicObjectTracking.TrackObject")] public sealed class TrackObject : BaseCommand { #region COM Registration Function(s) [ComRegisterFunction()] [ComVisible(false)] static void RegisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryRegistration(registerType); // // TODO: Add any COM registration code here // } [ComUnregisterFunction()] [ComVisible(false)] static void UnregisterFunction(Type registerType) { // Required for ArcGIS Component Category Registrar support ArcGISCategoryUnregistration(registerType); // // TODO: Add any COM unregistration code here // } #endregion #region ArcGIS Component Category Registrar generated code /// <summary> /// Required method for ArcGIS Component Category registration - /// Do not modify the contents of this method with the code editor. /// </summary> private static void ArcGISCategoryRegistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Register(regKey); } /// <summary> /// Required method for ArcGIS Component Category unregistration - /// Do not modify the contents of this method with the code editor. /// </summary> private static void ArcGISCategoryUnregistration(Type registerType) { string regKey = string.Format("HKEY_CLASSES_ROOT\\CLSID\\{{{0}}}", registerType.GUID); ControlsCommands.Unregister(regKey); } #endregion #region class members private IHookHelper m_hookHelper = null; private IDynamicMap m_dynamicMap = null; private IPoint m_point = null; private IDynamicGlyph m_VWmarkerGlyph = null; private IDynamicGlyphFactory2 m_dynamicGlyphFactory = null; private IDynamicSymbolProperties2 m_dynamicSymbolProps = null; private bool m_bDrawOnce = true; private IDisplayTransformation m_displayTransformation = null; private List<WKSPoint> m_points = null; private static int m_pointIndex = 0; private bool m_bIsRunning = false; private bool m_bOnce = true; private string m_VWFileName = string.Empty; private string m_navigationDataFileName = string.Empty; private NavigationData m_navigationData; #endregion /// <summary> /// class constructor /// </summary> public TrackObject() { base.m_category = ".NET Samples"; base.m_caption = "Track Dynamic Object"; base.m_message = "Tracking a dynamic object"; base.m_toolTip = "Tracking a dynamic object"; base.m_name = "DotNetSamples.TrackDynamicObject"; try { string bitmapResourceName = GetType().Name + ".bmp"; base.m_bitmap = new Bitmap(GetType(), bitmapResourceName); } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex.Message, "Invalid Bitmap"); } } #region Overriden Class Methods /// <summary> /// Occurs when this command is created /// </summary> /// <param name="hook">Instance of the application</param> public override void OnCreate(object hook) { if (hook == null) return; if (m_hookHelper == null) m_hookHelper = new HookHelperClass(); m_hookHelper.Hook = hook; m_point = new PointClass(); m_points = new List<WKSPoint>(); } /// <summary> /// Occurs when this command is clicked /// </summary> public override void OnClick() { //make sure to switch into dynamic mode m_dynamicMap = (IDynamicMap)m_hookHelper.FocusMap; if (!m_dynamicMap.DynamicMapEnabled) m_dynamicMap.DynamicMapEnabled = true; //do initializations if (m_bOnce) { //generate the navigation data GenerateNavigationData(); m_displayTransformation = m_hookHelper.ActiveView.ScreenDisplay.DisplayTransformation; m_bOnce = false; } //hook the dynamic display events if (!m_bIsRunning) { ((IDynamicMapEvents_Event)m_dynamicMap).DynamicMapFinished += new IDynamicMapEvents_DynamicMapFinishedEventHandler(OnTimerElapsed); ((IDynamicMapEvents_Event)m_dynamicMap).AfterDynamicDraw += new IDynamicMapEvents_AfterDynamicDrawEventHandler(OnAfterDynamicDraw); } else { ((IDynamicMapEvents_Event)m_dynamicMap).DynamicMapFinished -= new IDynamicMapEvents_DynamicMapFinishedEventHandler(OnTimerElapsed); ((IDynamicMapEvents_Event)m_dynamicMap).AfterDynamicDraw -= new IDynamicMapEvents_AfterDynamicDrawEventHandler(OnAfterDynamicDraw); } //set the running flag m_bIsRunning = !m_bIsRunning; } /// <summary> /// set the state of the button of the command /// </summary> public override bool Checked { get { return m_bIsRunning; } } #endregion private void OnTimerElapsed(IDisplay Display, IDynamicDisplay dynamicDisplay) { try { //make sure that the current tracking point index does not exceed the list index if (m_pointIndex == (m_points.Count - 1)) { m_pointIndex = 0; return; } //get the current and the next track location WKSPoint currentPoint = m_points[m_pointIndex]; WKSPoint nextPoint = m_points[m_pointIndex + 1]; //calculate the azimuth to the next location double azimuth = (180.0 / Math.PI) * Math.Atan2(nextPoint.X - currentPoint.X, nextPoint.Y - currentPoint.Y); //set the navigation data structure m_navigationData.X = currentPoint.X; m_navigationData.Y = currentPoint.Y; m_navigationData.Azimuth = azimuth; //update the map extent and rotation CenterMap(m_navigationData); //increment the tracking point index m_pointIndex++; } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex.Message); } } private void CenterMap(NavigationData navigationData) { try { //get the current map visible extent IEnvelope envelope = m_displayTransformation.VisibleBounds; if (null == m_point) { m_point = new PointClass(); } //set new map center coordinate m_point.PutCoords(navigationData.X, navigationData.Y); //center the map envelope.CenterAt(m_point); m_displayTransformation.VisibleBounds = envelope; //rotate the map to new angle m_displayTransformation.Rotation = navigationData.Azimuth; } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex.Message); } } private void GenerateNavigationData() { try { //get the ArcGIS install path from the registry string runtimeVersion = RuntimeManager.ActiveRuntime.Version; RegistryKey key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\ESRI\ArcObjectsSDK" + runtimeVersion); string path = Convert.ToString(key.GetValue("InstallDir")); //get navigationData.xml file from DeveloperKit m_navigationDataFileName = System.IO.Path.Combine(path, @"Samples\data\USAMajorHighways\NavigationData.xml"); if (!System.IO.File.Exists(m_navigationDataFileName)) { throw new Exception("File " + m_navigationDataFileName + " cannot be found!"); } XmlTextReader reader = new XmlTextReader(m_navigationDataFileName); XmlDocument doc = new XmlDocument(); doc.Load(reader); reader.Close(); double X; double Y; //get the navigation items XmlNodeList nodes = doc.DocumentElement.SelectNodes("./navigationItem"); foreach (XmlNode node in nodes) { X = Convert.ToDouble(node.Attributes[0].Value); Y = Convert.ToDouble(node.Attributes[1].Value); WKSPoint p = new WKSPoint(); p.X = X; p.Y = Y; m_points.Add(p); } } catch (Exception ex) { System.Diagnostics.Trace.WriteLine(ex.Message); } } void OnAfterDynamicDraw(esriDynamicMapDrawPhase DynamicMapDrawPhase, IDisplay Display, IDynamicDisplay dynamicDisplay) { if (DynamicMapDrawPhase != esriDynamicMapDrawPhase.esriDMDPDynamicLayers) return; if (m_bDrawOnce) { //cast the DynamicDisplay into DynamicGlyphFactory m_dynamicGlyphFactory = dynamicDisplay.DynamicGlyphFactory as IDynamicGlyphFactory2; //cast the DynamicDisplay into DynamicSymbolProperties m_dynamicSymbolProps = dynamicDisplay as IDynamicSymbolProperties2; //create the VW dynamic marker glyph from the embedded bitmap resource Bitmap bitmap = new Bitmap(GetType(), "VW.bmp"); //get bitmap handler int hBmp = bitmap.GetHbitmap().ToInt32(); //set white transparency color IColor whiteTransparencyColor = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.FromArgb(0, 0, 0)) as IColor; //get the VM dynamic marker glyph m_VWmarkerGlyph = m_dynamicGlyphFactory.CreateDynamicGlyphFromBitmap(esriDynamicGlyphType.esriDGlyphMarker, hBmp, false, whiteTransparencyColor); m_bDrawOnce = false; } //set the symbol alignment so that it will align with towards the symbol heading m_dynamicSymbolProps.set_RotationAlignment(esriDynamicSymbolType.esriDSymbolMarker, esriDynamicSymbolRotationAlignment.esriDSRANorth); //set the symbol's properties m_dynamicSymbolProps.set_DynamicGlyph(esriDynamicSymbolType.esriDSymbolMarker, m_VWmarkerGlyph); m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolMarker, 1.3f, 1.3f); m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolMarker, 1.0f, 1.0f, 0.0f, 1.0f); // yellow //set the heading of the current symbol m_dynamicSymbolProps.set_Heading(esriDynamicSymbolType.esriDSymbolMarker, (float)m_navigationData.Azimuth); //draw the current location dynamicDisplay.DrawMarker(m_point); } } }