MainForm.cs
// Copyright 2010 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.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Diagnostics; using System.Threading; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.GlobeCore; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.SystemUI; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.DataSourcesGDB; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.Geodatabase; using ESRI.ArcGIS.DefenseSolutions; namespace GlobeControlApp { public sealed partial class MainForm : Form { #region private class members private IGlobeControl m_globeControl = null; private IGlobeViewUtil m_globeViewUtil = null; #endregion #region class constructor public MainForm() { InitializeComponent(); } #endregion #region Main Menu event handlers private void menuOpenDoc_Click(object sender, EventArgs e) { //execute Open Document command ICommand command = new ControlsGlobeOpenDocCommandClass(); command.OnCreate(m_globeControl.Object); command.OnClick(); } private void menuExitApp_Click(object sender, EventArgs e) { //exit the application Application.Exit(); } #endregion /// <summary> /// Mouse move event handler /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void axGlobeControl1_OnMouseMove(object sender, IGlobeControlEvents_OnMouseMoveEvent e) { double dLon, dLat, dAlt; //convert the window coordinate into geographic coordinates m_globeViewUtil.WindowToGeographic( m_globeControl.GlobeDisplay, m_globeControl.GlobeDisplay.ActiveViewer, e.x, e.y, true, out dLon, out dLat, out dAlt); //report the mouse geographic coordinate onto the statusbar statusBarXY.Text = string.Format("{0} {1} {2}", dLon.ToString("###.###"), dLat.ToString("###.###"), dAlt.ToString("###.###")); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) { } // ================================================================= // The following code was added to a default(wizard generated) // Globe Control Application in order to obtain a MOLE Layer in 3D, // insert a feature, and refresh the layer. // ================================================================= IFeatureClass m_MoleFC = null; private static string m_DataPath = null; private int m_addedUnitCt = 0; /// <summary> /// Form Load event handler /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void MainForm_Load(object sender, EventArgs e) { m_globeControl = axGlobeControl1.Object as IGlobeControl; //cast the GlobeViewUtil from the GlobeCamera m_globeViewUtil = m_globeControl.GlobeCamera as IGlobeViewUtil; } /// <summary> /// Add a "Add Unit" button and use this as its event handler /// </summary> private void butTest_Click(object sender, EventArgs e) { if (!MoleFcIsValid()) return; AddUnitToFC( m_MoleFC ); IGlobeDisplay globeDisplay = axGlobeControl1.GlobeDisplay; RefreshMoleLayers( globeDisplay ); } /// <summary> /// Add a "Move All Units" button and use this as its event handler /// </summary> private void butTest2_Click(object sender, EventArgs e) { if (!MoleFcIsValid()) return; MoveAllUnits( m_MoleFC ); IGlobeDisplay globeDisplay = axGlobeControl1.GlobeDisplay; RefreshMoleLayers( globeDisplay ); } /// <summary> /// Refreshes all MOLE Layers in a GlobeDisplay/Globe /// </summary> private void RefreshMoleLayers(IGlobeDisplay globeDisplay) { try { IBasicMap map = globeDisplay.Globe as IBasicMap; // find the mole Force Element layers and refresh them IEnumLayer enumLayer = map.get_Layers(null, true); enumLayer.Reset(); ILayer layer = null; while ((layer = enumLayer.Next()) != null) { if (layer is IForceElementLayer) { // Code required to get a MOLE Layer to rebuild & refresh in Globe ICachedGraphicLayer MoleLayer = layer as ICachedGraphicLayer; MoleLayer.Refresh(); globeDisplay.SuspendTileFetch(); I3DSettings layer3DSettings = MoleLayer as I3DSettings; if ((layer3DSettings != null) && (layer3DSettings.DisplayOption == mole3DDisplayEnum.mole3DDisplayExtrude)) { // use optimized refresh ESRI.ArcGIS.Display.IDisplay display = globeDisplay as ESRI.ArcGIS.Display.IDisplay; layer.Draw(esriDrawPhase.esriDPGeography, display, null); } else { // Use normal GlobeDisplay refresh (Does not perform as well) (globeDisplay as IGlobeDisplayLayers).RefreshLayer(layer); } globeDisplay.ResumeTileFetch(); } } } catch (Exception e) { Trace.WriteLine(e.Message); } } /// <summary> /// Adds a Unit to a feature class with the MOLE data model /// </summary> private void AddUnitToFC(IFeatureClass featureClass) { try { // Random Number Generation (so each new unit shows up at a different point) const double maxRandom = 5.0; System.Random randomGenerator = new System.Random(); double dRandom = randomGenerator.NextDouble() * maxRandom; // create the new feature IFeature newFeature = featureClass.CreateFeature(); // get an insert cursor IFeatureCursor insertCursor = featureClass.Insert( false ); if (newFeature != null) { // create a random point for the unit's location IPoint point = new PointClass(); point.PutCoords( -117.0 + dRandom, 35.0 + dRandom / 2.0 ); point.Z = 100.0; IZAware za = point as IZAware; za.ZAware = true; // set the feature's shape newFeature.Shape = (point as IGeometry); // set feature fields (SIC, name) string symbolIdCode = "S"; char affilCode = 'F'; // Set a different affiliation for each new unit added. int affil = m_addedUnitCt % 4; switch (affil) { case 0: affilCode = 'F'; break; case 1: affilCode = 'H'; break; case 2: affilCode = 'N'; break; case 3: affilCode = 'U'; break; default: break; } // Set the Symbol ID code. symbolIdCode = symbolIdCode + affilCode + "GPUCI-----USG"; newFeature.set_Value( newFeature.Table.FindField( "Symbol_ID" ), symbolIdCode ); // Increment the unit counter used for the unit label. m_addedUnitCt++; // Set the label for the unit's graphic. string testName = "Test Insert Unit " + m_addedUnitCt; newFeature.set_Value( newFeature.Table.FindField( "Name" ), testName ); insertCursor.InsertFeature( newFeature as IFeatureBuffer ); } insertCursor.Flush(); // make sure changes are committed before we exit } catch (Exception e) { Trace.WriteLine( e.Message ); } } /// <summary> /// Moves all point geometries in a Feature Class /// </summary> private void MoveAllUnits(IFeatureClass featureClass) { try { // get all features IFeatureCursor updateCursor = featureClass.Update( null, false ); IFeature updateFeature = updateCursor.NextFeature(); while (updateFeature != null) { IGeometry geometry = updateFeature.Shape; IPoint point = geometry as IPoint; // make sure not an empty/corrupt geometry if ((geometry != null) && (point != null) && (!geometry.IsEmpty)) { point.X += 0.20; updateFeature.Shape = geometry; updateCursor.UpdateFeature( updateFeature ); } updateFeature = updateCursor.NextFeature(); } } catch (Exception e) { Trace.WriteLine( e.Message ); } } /// <summary> /// Loads a MOLE Layer in Globe /// </summary> /// <remarks> /// This is very similar to the 2D usage with additional code to /// set the I3DSettings properties for the layer /// </remarks> private IFeatureClass LoadMoleFeatureClassInGlobe(IGlobe globe) { string dbPath = MoleMDB; IFeatureClass fc = LoadAccessFeatureClass( dbPath, "FriendlyForces"); Debug.WriteLine("Attempting to Add MOLE Layer"); IGeoFeatureLayer pFeatureLayer = new FeatureLayer() as IGeoFeatureLayer; pFeatureLayer.FeatureClass = fc; //Create a MOLE layer and attach the feature layer to it ICachedGraphicFeatureLayer pLayer = new ForceElementLayer() as ICachedGraphicFeatureLayer; pLayer.FeatureLayer = pFeatureLayer; //Set the size for symbols in the layer IForceElementLayer pForceElementLayer = pLayer as IForceElementLayer; pForceElementLayer.Size = 0.20; // Set 3D Settings I3DSettings p3DSettings = pForceElementLayer as I3DSettings; p3DSettings.DisplayOption = mole3DDisplayEnum.mole3DDisplayExtrude; // or .mole3DDisplayBoth; // or .mole3DDisplayDrape p3DSettings.EnableCallouts = true; p3DSettings.DefaultElevationMeters = 10000; ILayer layer = pLayer as ILayer; layer.Name = "MOLE 3D Unit Layer"; globe.AddLayerType(layer, ESRI.ArcGIS.GlobeCore.esriGlobeLayerType.esriGlobeLayerTypeDraped, true); System.Diagnostics.Debug.WriteLine("Layer Added"); return fc; } /// <summary> /// Opens a Feature Class from an Access PGDB /// </summary> private IFeatureClass LoadAccessFeatureClass(string dbPath, string featureClassName) { // open the access database IWorkspaceFactory pWSF = new AccessWorkspaceFactoryClass(); IWorkspace pWS = pWSF.OpenFromFile(dbPath, 0); // make sure the database was opened if (pWS == null) { MessageBox.Show("Could not locate and/or open database at: \"" + dbPath + "\"", "Error!"); return null; } IFeatureWorkspace pFWS = pWS as IFeatureWorkspace; IFeatureClass pFC; lock (pFWS) // lock to prevent multi-process access { // open the feature class pFC = pFWS.OpenFeatureClass(featureClassName); } // make sure the feature class was opened if (pFC == null) { MessageBox.Show("Could not open feature class: " + featureClassName + ".", "Error!"); return null; } return pFC; } /// <summary> /// Path to ArcGIS Install /// </summary> private static string GetSdkDataPath() { //get the ArcGIS path from the registry Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\ESRI\ArcGIS_SXS_SDK"); string path = Convert.ToString(key.GetValue("InstallDir")); //set the of the logo string str = System.IO.Path.Combine(path, @"Samples\data\"); if (!System.IO.Directory.Exists(str)) { MessageBox.Show("Path :" + str + " does not exist!"); return string.Empty; } return str; } /// <summary> /// Path to MOLE Globe Access PGDB data file /// </summary> public static string MoleMDB { get { if (m_DataPath == null) { m_DataPath = GetSdkDataPath() + @"MilitaryOverlayEditor\mole_globe.mdb"; } return m_DataPath; } } // Checks if a valid MOLE feature class has been loaded onto the globe. private bool MoleFcIsValid() { if (m_MoleFC == null) { MessageBox.Show("Please open an ArcGlobe (.3dd) document\nbefore pressing this button.", "MOLE Globe", MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } return true; } // Called when a Globe document is opened. private void axGlobeControl1_OnGlobeReplaced(object sender, IGlobeControlEvents_OnGlobeReplacedEvent e) { // Load the MOLE Unit Feature Class m_MoleFC = LoadMoleFeatureClassInGlobe(this.axGlobeControl1.Globe as IGlobe); } } }