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