About the Arranging MOLE graphics using manual decluttering Sample
[C#]
MainForm.cs
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.IO; using System.Runtime.InteropServices; using ESRI.ArcGIS.ADF; using ESRI.ArcGIS.Carto; using ESRI.ArcGIS.Controls; using ESRI.ArcGIS.DefenseSolutions; using ESRI.ArcGIS.Display; using ESRI.ArcGIS.esriSystem; using ESRI.ArcGIS.Geometry; using ESRI.ArcGIS.SystemUI; namespace ManualGroupDraw { public sealed partial class MainForm : Form { #region class private members private IMapControl3 m_mapControl = null; private Random m_Random = new Random(); private IMoleGroupElement m_MoleGroup = new MoleGroupElementClass(); #endregion #region Constructor public MainForm() { InitializeComponent(); } #endregion #region Form Event Handlers private 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; } private void MainForm_Load(object sender, EventArgs e) { // get the MapControl m_mapControl = (IMapControl3) axMapControl1.Object; // get a map from the SDK sample data string dataPath = GetSdkDataPath() + @"MilitaryOverlayEditor\"; string defaultMxDoc = dataPath + "molebasemap.mxd"; // load the map into the map control if (this.m_mapControl.CheckMxFile(defaultMxDoc)) { object missing = System.Reflection.Missing.Value; this.m_mapControl.LoadMxFile (defaultMxDoc, missing, missing); } else { string errorMsg = "Could not load default map document - Application may not work!"; errorMsg += "\n" + defaultMxDoc; System.Diagnostics.Trace.WriteLine (errorMsg); MessageBox.Show (errorMsg); } // begin with no decluttering cbDeclutter.SelectedIndex = 0; } private void cbDeclutter_SelectedIndexChanged(object sender, EventArgs e) { // get the selected option from the combo box moleDeclutterOptionEnum[] options = { moleDeclutterOptionEnum.moleDeclutterNone, moleDeclutterOptionEnum.moleDeclutterLeader, moleDeclutterOptionEnum.moleDeclutterManual, moleDeclutterOptionEnum.moleDeclutterStack }; moleDeclutterOptionEnum option = options[cbDeclutter.SelectedIndex]; if ( m_MoleGroup.DeclutterOption != option ) { // the option has changed - set the new option and recalculate if necessary m_MoleGroup.DeclutterOption = option; m_MoleGroup.EnableDeclutter = ( option != moleDeclutterOptionEnum.moleDeclutterNone ); IGroupElement groupElement = m_MoleGroup as IGroupElement; if ( option == moleDeclutterOptionEnum.moleDeclutterManual && groupElement.ElementCount > 0 ) { // calculate the decluttered positions manually - in decimal degrees double xStep = 25; double xDeclutter = -0.5 * groupElement.ElementCount * xStep; if ( xDeclutter < -180 ) { // don't fall off the end of the world xStep = 360 / groupElement.ElementCount; xDeclutter = -180 - 0.5 * xStep; } else xDeclutter -= 0.5 * xStep; IPoint point = new PointClass(); IMoleDeclutterElement moleDeclutterElement = m_MoleGroup as IMoleDeclutterElement; for ( int i = 0; i < groupElement.ElementCount; ++i ) { // set a declutter point for each element // these lines of code have no effect in stack or leader mode IElement element = groupElement.get_Element (i); xDeclutter += xStep; point.PutCoords (xDeclutter, 45); moleDeclutterElement.DeclutterElement (element, point as IGeometry); } } // update the display m_mapControl.ActiveView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); } } private void btnAddGroup_Click(object sender, EventArgs e) { // tell the user that we are busy for a few seconds, and don't let them press the button again Cursor = Cursors.WaitCursor; btnAddGroup.Enabled = false; cbDeclutter.Enabled = true; // tell MOLE to leave it cluttered, for now m_MoleGroup.DeclutterOption = moleDeclutterOptionEnum.moleDeclutterNone; m_MoleGroup.EnableDeclutter = false; // generate some elements (vary the number of elements as much as desired) IPoint point = new PointClass(); IGroupElement groupElement = m_MoleGroup as IGroupElement; DemoSymbolIDs symIDs = new DemoSymbolIDs(); for ( int i = 0; i < 10; ++i ) { // create a MarkerElement with a MOLE symbol IMoleSymbol moleSymbol = new MoleMarkerSymbolClass(); moleSymbol.SymbolID = symIDs[i]; IMarkerElement markerElement = new MarkerElementClass(); markerElement.Symbol = moleSymbol as IMarkerSymbol; IElement element = markerElement as IElement; // add the element to the group at a random clustered location point.PutCoords(m_Random.Next(-15, 15), m_Random.Next(-15, 15)); element.Geometry = point as IGeometry; groupElement.AddElement (element); } // add the group to the map and update the view m_mapControl.ActiveView.GraphicsContainer.AddElement (m_MoleGroup as IElement, 0); m_mapControl.ActiveView.PartialRefresh (esriViewDrawPhase.esriViewGraphics, null, null); // tell the user that we are no longer busy Cursor = Cursors.Default; } #endregion #region Map Control Event Handlers private void axMapControl1_OnMapReplaced(object sender, IMapControlEvents2_OnMapReplacedEvent e) { //put the current document name in the status bar if (m_mapControl.DocumentFilename != null) statusBarXY.Text = System.IO.Path.GetFileName(m_mapControl.DocumentFilename); } private void axMapControl1_OnMouseMove(object sender, IMapControlEvents2_OnMouseMoveEvent e) { statusBarXY.Text = string.Format("{0}, {1} {2}", e.mapX.ToString("#######.##"), e.mapY.ToString("#######.##"), axMapControl1.MapUnits.ToString().Substring(4)); } #endregion } }
[Visual Basic .NET]
MainForm.vb
Imports System Imports System.Drawing Imports System.Collections Imports System.ComponentModel Imports System.Windows.Forms Imports System.Data Imports System.IO Imports System.Runtime.InteropServices Imports ESRI.ArcGIS.esriSystem Imports ESRI.ArcGIS.Carto Imports ESRI.ArcGIS.Controls Imports ESRI.ArcGIS.ADF Imports ESRI.ArcGIS.SystemUI Imports ESRI.ArcGIS Imports ESRI.ArcGIS.Display Imports ESRI.ArcGIS.Geometry Imports ESRI.ArcGIS.DefenseSolutions Namespace ManualGroupDraw Public NotInheritable Partial Class MainForm Inherits Form #Region "class private members" Private m_mapControl As IMapControl3 = Nothing Private m_Random As New Random() Private m_MoleGroup As IMoleGroupElement = New MoleGroupElementClass() #End Region #Region "Constructor" Public Sub New() InitializeComponent() End Sub #End Region #Region "Form Event Handlers" Private Sub MainForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load ' get the MapControl m_mapControl = DirectCast(axMapControl1.Object, IMapControl3) ' get a map from the SDK sample data Dim dataPath As String = GetSdkDataPath() + "MilitaryOverlayEditor\" Dim defaultMxDoc As String = dataPath & "molebasemap.mxd" ' load the map into the map control If Me.m_mapControl.CheckMxFile(defaultMxDoc) Then Dim missing As Object = System.Reflection.Missing.Value Me.m_mapControl.LoadMxFile(defaultMxDoc, missing, missing) Else Dim errorMsg As String = "Could not load default map document - Application may not work!" errorMsg &= Environment.NewLine & defaultMxDoc System.Diagnostics.Trace.WriteLine(errorMsg) MessageBox.Show(errorMsg) End If ' begin with no decluttering cbDeclutter.SelectedIndex = 0 End Sub Private Function GetSdkDataPath() As String 'get the ArcGIS path from the registry Dim key As Microsoft.Win32.RegistryKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("SOFTWARE\ESRI\ArcGIS_SXS_SDK") Dim path As String = Convert.ToString(key.GetValue("InstallDir")) 'set the of the logo Dim str As String = System.IO.Path.Combine(path, "Samples\data\") If (Not System.IO.Directory.Exists(str)) Then MessageBox.Show("Path :" & str & " does not exist!") Return String.Empty End If Return str End Function Private Sub cbDeclutter_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs) Handles cbDeclutter.SelectedIndexChanged ' get the selected option from the combo box Dim declutterOptions As moleDeclutterOptionEnum() = {moleDeclutterOptionEnum.moleDeclutterNone, moleDeclutterOptionEnum.moleDeclutterLeader, moleDeclutterOptionEnum.moleDeclutterManual, moleDeclutterOptionEnum.moleDeclutterStack} Dim declutterOption As moleDeclutterOptionEnum = declutterOptions(cbDeclutter.SelectedIndex) If m_MoleGroup.DeclutterOption <> declutterOption Then ' the option has changed - set the new option and recalculate if necessary m_MoleGroup.DeclutterOption = declutterOption m_MoleGroup.EnableDeclutter = (declutterOption <> moleDeclutterOptionEnum.moleDeclutterNone) Dim groupElement As IGroupElement = TryCast(m_MoleGroup, IGroupElement) If declutterOption = moleDeclutterOptionEnum.moleDeclutterManual AndAlso groupElement.ElementCount > 0 Then ' calculate the decluttered positions manually - in decimal degrees Dim xStep As Double = 25 Dim xDeclutter As Double = -0.5 * groupElement.ElementCount * xStep If xDeclutter < -180 Then ' don't fall off the end of the world xStep = 360 / groupElement.ElementCount xDeclutter = -180 - 0.5 * xStep Else xDeclutter -= 0.5 * xStep End If Dim point As IPoint = New PointClass() Dim moleDeclutterElement As IMoleDeclutterElement = TryCast(m_MoleGroup, IMoleDeclutterElement) For i As Integer = 0 To groupElement.ElementCount - 1 ' set a declutter point for each element ' these lines of code have no effect in stack or leader mode Dim element As IElement = TryCast(groupElement.Element(i), IElement) xDeclutter += xStep point.PutCoords(xDeclutter, 45) moleDeclutterElement.DeclutterElement(element, TryCast(point, IGeometry)) Next End If ' update the display m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) End If End Sub Private Sub btnAddGroup_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnAddGroup.Click ' tell the user that we are busy for a few seconds, and don't let them press the button again Cursor = Cursors.WaitCursor btnAddGroup.Enabled = False cbDeclutter.Enabled = True ' tell MOLE to leave it cluttered, for now m_MoleGroup.DeclutterOption = moleDeclutterOptionEnum.moleDeclutterNone m_MoleGroup.EnableDeclutter = False ' generate some elements (vary the number of elements as much as desired) Dim point As IPoint = New PointClass() Dim groupElement As IGroupElement = TryCast(m_MoleGroup, IGroupElement) Dim symIDs As New DemoSymbolIDs() For i As Integer = 0 To 9 ' create a MarkerElement with a MOLE symbol Dim moleSymbol As IMoleSymbol = New MoleMarkerSymbolClass() moleSymbol.SymbolID = symIDs(i) Dim markerElement As IMarkerElement = New MarkerElementClass() markerElement.Symbol = TryCast(moleSymbol, IMarkerSymbol) Dim element As IElement = TryCast(markerElement, IElement) ' add the element to the group at a random clustered location point.PutCoords(m_Random.Next(-15, 15), m_Random.Next(-15, 15)) element.Geometry = TryCast(point, IGeometry) groupElement.AddElement(element) Next ' add the group to the map and update the view m_mapControl.ActiveView.GraphicsContainer.AddElement(TryCast(m_MoleGroup, IElement), 0) m_mapControl.ActiveView.PartialRefresh(esriViewDrawPhase.esriViewGraphics, Nothing, Nothing) ' tell the user that we are no longer busy Cursor = Cursors.Default End Sub #End Region #Region "Map Control Event Handlers" Private Sub axMapControl1_OnMapReplaced(ByVal sender As Object, ByVal e As IMapControlEvents2_OnMapReplacedEvent) Handles axMapControl1.OnMapReplaced 'put the current document name in the status bar If m_mapControl.DocumentFilename IsNot Nothing Then statusBarXY.Text = System.IO.Path.GetFileName(m_mapControl.DocumentFilename) End If End Sub Private Sub axMapControl1_OnMouseMove(ByVal sender As Object, ByVal e As IMapControlEvents2_OnMouseMoveEvent) Handles axMapControl1.OnMouseMove statusBarXY.Text = String.Format("{0}, {1} {2}", e.mapX.ToString("#######.##"), e.mapY.ToString("#######.##"), axMapControl1.MapUnits.ToString().Substring(4)) End Sub #End Region End Class End Namespace