About the Triangle graphic element Sample
[C#]
TriangleElementClass.cs
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.esriSystem;
namespace TriangleElement
{
[ComVisible(true)]
[Guid("DC8482C9-5DD6-44dc-BF3C-54B18AB813C9")]
public interface ITriangleElement
{
ISimpleFillSymbol FillSymbol { get; set;}
double Size { get; set;}
double Angle { get; set;}
}
[Guid(TriangleElementClass.CLASSGUID)]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("TriangleElement.TriangleElementClass")]
public sealed class TriangleElementClass : ITriangleElement,
IElement,
IElementProperties,
IElementProperties2,
IElementProperties3,
IBoundsProperties,
ITransform2D,
IGraphicElement,
IPersistVariant,
IClone,
IDocumentVersionSupportGEN
{
#region class members
//some win32 imports and constants
[System.Runtime.InteropServices.DllImport("gdi32", EntryPoint = "GetDeviceCaps", ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
public static extern int GetDeviceCaps(int hDC, int nIndex);
private const double c_Cosine30 = 0.866025403784439;
private const double c_Deg2Rad = (Math.PI / 180.0);
private const double c_Rad2Deg = (180.0 / Math.PI);
private const int c_Version = 2;
public const string CLASSGUID = "cbf943e2-ce6d-49f4-a4a7-ce16f02379ad";
public const int LOGPIXELSX = 88;
public const int LOGPIXELSY = 90;
private IPolygon m_triangle = null;
private IPoint m_pointGeometry = null;
private ISimpleFillSymbol m_fillSymbol = null;
private double m_rotation = 0.0;
private double m_size = 20.0;
private ISelectionTracker m_selectionTracker = null;
private IDisplay m_cachedDisplay = null;
private ISpatialReference m_nativeSR = null;
private string m_elementName = string.Empty;
private string m_elementType = "TriangleElement";
private object m_customProperty = null;
private bool m_autoTrans = true;
private double m_scaleRef = 0.0;
private esriAnchorPointEnum m_anchorPointType = esriAnchorPointEnum.esriCenterPoint;
private double m_dDeviceRatio = 0;
#endregion
#region class constructor
public TriangleElementClass()
{
//initialize the element's geometry
m_triangle = new PolygonClass();
m_triangle.SetEmpty();
InitMembers();
}
#endregion
#region ITriangleElement Members
public ISimpleFillSymbol FillSymbol
{
get
{
return m_fillSymbol;
}
set
{
m_fillSymbol = value;
}
}
public double Size
{
get
{
return m_size;
}
set
{
m_size = value;
}
}
public double Angle
{
get
{
return m_rotation;
}
set
{
m_rotation = value;
}
}
#endregion
#region IElement Members
public void Activate(IDisplay Display)
{
//cache the display
m_cachedDisplay = Display;
SetupDeviceRatio(Display.hDC, Display);
//need to calculate the points of the triangle polygon
if(m_triangle.IsEmpty)
BuildTriangleGeometry(m_pointGeometry);
//need to refresh the element's tracker
RefreshTracker();
}
public void Deactivate()
{
m_cachedDisplay = null;
}
public void Draw(IDisplay Display, ITrackCancel TrackCancel)
{
if (null != m_triangle && null != m_fillSymbol)
{
Display.SetSymbol((ISymbol)m_fillSymbol);
Display.DrawPolygon(m_triangle);
}
}
public IGeometry Geometry
{
get
{
return Clone(m_pointGeometry) as IGeometry;
}
set
{
try
{
m_pointGeometry = Clone(value) as IPoint;
UpdateElementSpatialRef();
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
}
public bool HitTest(double x, double y, double Tolerance)
{
if (null == m_cachedDisplay)
return false;
IPoint point = new PointClass();
point.PutCoords(x,y);
return ((IRelationalOperator)m_triangle).Contains((IGeometry)point);
}
public bool Locked
{
get
{
return false;
}
set
{
}
}
public void QueryBounds(IDisplay Display, IEnvelope Bounds)
{
//return a bounding envelope
IPolygon polygon = new PolygonClass();
polygon.SetEmpty();
((ISymbol)m_fillSymbol).QueryBoundary(Display.hDC, Display.DisplayTransformation, m_triangle, polygon);
Bounds.XMin = polygon.Envelope.XMin;
Bounds.XMax = polygon.Envelope.XMax;
Bounds.YMin = polygon.Envelope.YMin;
Bounds.YMax = polygon.Envelope.YMax;
Bounds.SpatialReference = polygon.Envelope.SpatialReference;
}
public void QueryOutline(IDisplay Display, IPolygon Outline)
{
//return a polygon which is the outline of the element
IPolygon polygon = new PolygonClass();
polygon.SetEmpty();
((ISymbol)m_fillSymbol).QueryBoundary(Display.hDC, Display.DisplayTransformation, m_triangle, polygon);
((IPointCollection)Outline).AddPointCollection((IPointCollection)polygon);
}
public ISelectionTracker SelectionTracker
{
get { return m_selectionTracker; }
}
#endregion
#region IElementProperties Members
/// <summary>
/// Indicates if transform is applied to symbols and other parts of element.
/// False = only apply transform to geometry.
/// Update font size in ITransform2D routines
/// </summary>
public bool AutoTransform
{
get
{
return m_autoTrans;
}
set
{
m_autoTrans = value;
}
}
public object CustomProperty
{
get
{
return m_customProperty;
}
set
{
m_customProperty = value;
}
}
public string Name
{
get
{
return m_elementName;
}
set
{
m_elementName = value;
}
}
public string Type
{
get
{
return m_elementType;
}
set
{
m_elementType = value;
}
}
#endregion
#region IElementProperties2 Members
public bool CanRotate()
{
return true;
}
public double ReferenceScale
{
get
{
return m_scaleRef;
}
set
{
m_scaleRef = value;
}
}
#endregion
#region IElementProperties3 Members
public esriAnchorPointEnum AnchorPoint
{
get
{
return m_anchorPointType;
}
set
{
m_anchorPointType = value;
}
}
#endregion
#region IBoundsProperties Members
public bool FixedAspectRatio
{
get
{
return true;
}
set
{
throw new Exception("The method or operation is not implemented.");
}
}
public bool FixedSize
{
get { return true; }
}
#endregion
#region ITransform2D Members
public void Move(double dx, double dy)
{
if (null == m_triangle)
return;
((ITransform2D)m_triangle).Move(dx, dy);
((ITransform2D)m_pointGeometry).Move(dx, dy);
RefreshTracker();
}
public void MoveVector(ILine v)
{
if (null == m_triangle)
return;
((ITransform2D)m_triangle).MoveVector(v);
((ITransform2D)m_pointGeometry).MoveVector(v);
RefreshTracker();
}
public void Rotate(IPoint Origin, double rotationAngle)
{
if (null == m_triangle)
return;
((ITransform2D)m_triangle).Rotate(Origin, rotationAngle);
((ITransform2D)m_pointGeometry).Rotate(Origin, rotationAngle);
m_rotation = rotationAngle * c_Rad2Deg;
RefreshTracker();
}
public void Scale(IPoint Origin, double sx, double sy)
{
if (null == m_triangle)
return;
((ITransform2D)m_triangle).Scale(Origin, sx, sy);
((ITransform2D)m_pointGeometry).Scale(Origin, sx, sy);
if (m_autoTrans)
{
m_size *= Math.Max(sx, sy);
}
RefreshTracker();
}
public void Transform(esriTransformDirection direction, ITransformation transformation)
{
if (null == m_triangle)
return;
//Geometry
((ITransform2D)m_triangle).Transform(direction, transformation);
IAffineTransformation2D affineTrans = (IAffineTransformation2D)transformation;
if (affineTrans.YScale != 1.0)
m_size *= Math.Max(affineTrans.YScale, affineTrans.XScale);
RefreshTracker();
}
#endregion
#region IGraphicElement Members
public ISpatialReference SpatialReference
{
get
{
return m_nativeSR;
}
set
{
m_nativeSR = value;
UpdateElementSpatialRef();
}
}
#endregion
#region IPersistVariant Members
public UID ID
{
get
{
UID uid = new UIDClass();
uid.Value = "{" + TriangleElementClass.CLASSGUID + "}";
return uid;
}
}
public void Load(IVariantStream Stream)
{
int ver = (int)Stream.Read();
if (ver > c_Version || ver <= 0)
throw new Exception("Wrong version!");
InitMembers();
m_size = (double)Stream.Read();
m_scaleRef = (double)Stream.Read();
m_anchorPointType = (esriAnchorPointEnum)Stream.Read();
m_autoTrans = (bool)Stream.Read();
m_elementType = (string)Stream.Read();
m_elementName = (string)Stream.Read();
m_nativeSR = Stream.Read() as ISpatialReference;
m_fillSymbol = Stream.Read() as ISimpleFillSymbol;
m_pointGeometry = Stream.Read() as IPoint;
m_triangle = Stream.Read() as IPolygon;
if (ver == 2)
{
m_rotation = (double)Stream.Read();
}
}
public void Save(IVariantStream Stream)
{
Stream.Write(c_Version);
Stream.Write(m_size);
Stream.Write(m_scaleRef);
Stream.Write(m_anchorPointType);
Stream.Write(m_autoTrans);
Stream.Write(m_elementType);
Stream.Write(m_elementName);
Stream.Write(m_nativeSR);
Stream.Write(m_fillSymbol);
Stream.Write(m_pointGeometry);
Stream.Write(m_triangle);
Stream.Write(m_rotation);
}
#endregion
#region IClone Members
public void Assign(IClone src)
{
//1. make sure that src is pointing to a valid object
if (null == src)
{
throw new COMException("Invalid object.");
}
//2. make sure that the type of src is of type 'TriangleElementClass'
if (!(src is TriangleElementClass))
{
throw new COMException("Bad object type.");
}
//3. assign the properties of src to the current instance
TriangleElementClass srcTriangle = (TriangleElementClass)src;
m_elementName = srcTriangle.Name;
m_elementType = srcTriangle.Type;
m_autoTrans = srcTriangle.AutoTransform;
m_scaleRef = srcTriangle.ReferenceScale;
m_rotation = srcTriangle.Angle;
m_size = srcTriangle.Size;
m_anchorPointType = srcTriangle.AnchorPoint;
IObjectCopy objCopy = new ObjectCopyClass();
//take care of the custom property
if (null != srcTriangle.CustomProperty)
{
if (srcTriangle.CustomProperty is IClone)
m_customProperty = (object)((IClone)srcTriangle.CustomProperty).Clone();
else if (srcTriangle.CustomProperty is IPersistStream)
{
m_customProperty = objCopy.Copy((object)srcTriangle.CustomProperty);
}
else if (srcTriangle.CustomProperty.GetType().IsSerializable)
{
//serialize to a memory stream
MemoryStream memoryStream = new MemoryStream();
BinaryFormatter binaryFormatter = new BinaryFormatter();
binaryFormatter.Serialize(memoryStream, srcTriangle.CustomProperty);
byte[] bytes = memoryStream.ToArray();
memoryStream = new MemoryStream(bytes);
m_customProperty = binaryFormatter.Deserialize(memoryStream);
}
}
if (null != srcTriangle.SpatialReference)
m_nativeSR = objCopy.Copy(srcTriangle.SpatialReference) as ISpatialReference;
else
m_nativeSR = null;
if (null != srcTriangle.FillSymbol)
{
m_fillSymbol = objCopy.Copy(srcTriangle.FillSymbol) as ISimpleFillSymbol;
}
else
m_fillSymbol = null;
if (null != srcTriangle.Geometry)
{
m_triangle = objCopy.Copy(srcTriangle.Geometry) as IPolygon;
m_pointGeometry = objCopy.Copy(((IArea)m_triangle).Centroid) as IPoint;
}
else
{
m_triangle = null;
m_pointGeometry = null;
}
}
public IClone Clone()
{
TriangleElementClass triangle = new TriangleElementClass();
triangle.Assign((IClone)this);
return (IClone)triangle;
}
public bool IsEqual(IClone other)
{
//1. make sure that the 'other' object is pointing to a valid object
if (null == other)
throw new COMException("Invalid object.");
//2. verify the type of 'other'
if (!(other is TriangleElementClass))
throw new COMException("Bad object type.");
TriangleElementClass otherTriangle = (TriangleElementClass)other;
//test that all of the object's properties are the same.
//please note the usage of IsEqual when using ArcObjects components that
//supports cloning
if (otherTriangle.Name == m_elementName &&
otherTriangle.Type == m_elementType &&
otherTriangle.AutoTransform == m_autoTrans &&
otherTriangle.ReferenceScale == m_scaleRef &&
otherTriangle.Angle == m_rotation &&
otherTriangle.Size == m_size &&
otherTriangle.AnchorPoint == m_anchorPointType &&
((IClone)otherTriangle.Geometry).IsEqual((IClone)m_triangle) &&
((IClone)otherTriangle.FillSymbol).IsEqual((IClone)m_fillSymbol) &&
((IClone)otherTriangle.SpatialReference).IsEqual((IClone)m_nativeSR))
return true;
return false;
}
public bool IsIdentical(IClone other)
{
//1. make sure that the 'other' object is pointing to a valid object
if (null == other)
throw new COMException("Invalid object.");
//2. verify the type of 'other'
if (!(other is TriangleElementClass))
throw new COMException("Bad object type.");
//3. test if the other is the 'this'
if ((TriangleElementClass)other == this)
return true;
return false;
}
#endregion
#region IDocumentVersionSupportGEN Members
public object ConvertToSupportedObject(esriArcGISVersion docVersion)
{
//in case of 8.3, create a character marker element and use a triangle marker...
ICharacterMarkerSymbol charMarkerSymbol = new CharacterMarkerSymbolClass();
charMarkerSymbol.Color = m_fillSymbol.Color;
charMarkerSymbol.Angle = m_rotation;
charMarkerSymbol.Size = m_size;
charMarkerSymbol.Font = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToStdFont(new Font("ESRI Default Marker", (float)m_size, FontStyle.Regular));
charMarkerSymbol.CharacterIndex = 184;
IMarkerElement markerElement = new MarkerElementClass();
markerElement.Symbol = (IMarkerSymbol)charMarkerSymbol;
IPoint point = ((IClone)m_pointGeometry).Clone() as IPoint;
IElement element = (IElement)markerElement;
element.Geometry = (IGeometry)point;
return element;
}
public bool IsSupportedAtVersion(esriArcGISVersion docVersion)
{
//support all versions except 8.3
if (esriArcGISVersion.esriArcGISVersion83 == docVersion)
return false;
else
return true;
}
#endregion
#region private methods
private IClone Clone(object obj)
{
if (null == obj || !(obj is IClone))
return null;
return ((IClone)obj).Clone();
}
private int TwipsPerPixelX()
{
return 16;
}
private int TwipsPerPixelY()
{
return 16;
}
private void SetupDeviceRatio(int hDC, ESRI.ArcGIS.Display.IDisplay display)
{
if (display.DisplayTransformation != null)
{
if (display.DisplayTransformation.Resolution != 0)
{
m_dDeviceRatio = display.DisplayTransformation.Resolution / 72;
// Check the ReferenceScale of the display transformation. If not zero, we need to
// adjust the Size, XOffset and YOffset of the Symbol we hold internally before drawing.
if (display.DisplayTransformation.ReferenceScale != 0)
m_dDeviceRatio = m_dDeviceRatio * display.DisplayTransformation.ReferenceScale / display.DisplayTransformation.ScaleRatio;
}
}
else
{
// If we don't have a display transformation, calculate the resolution
// from the actual device.
if (display.hDC != 0)
{
// Get the resolution from the device context hDC.
m_dDeviceRatio = System.Convert.ToDouble(GetDeviceCaps(hDC, LOGPIXELSX)) / 72;
}
else
{
// If invalid hDC assume we're drawing to the screen.
m_dDeviceRatio = 1 / (TwipsPerPixelX() / 20); // 1 Point = 20 Twips.
}
}
}
private double PointsToMap(IDisplayTransformation displayTransform, double dPointSize)
{
double tempPointsToMap = 0;
if (displayTransform == null)
tempPointsToMap = dPointSize * m_dDeviceRatio;
else
{
tempPointsToMap = displayTransform.FromPoints(dPointSize);
}
return tempPointsToMap;
}
private void BuildTriangleGeometry(IPoint pointGeometry)
{
try
{
if (null == m_triangle || null == pointGeometry || null == m_cachedDisplay)
return;
m_triangle.SpatialReference = pointGeometry.SpatialReference;
m_triangle.SetEmpty();
object missing = System.Reflection.Missing.Value;
IPointCollection pointCollection = (IPointCollection)m_triangle;
double radius = PointsToMap(m_cachedDisplay.DisplayTransformation, m_size);
double X = pointGeometry.X;
double Y = pointGeometry.Y;
IPoint point = new PointClass();
point.X = X + radius * c_Cosine30;
point.Y = Y - 0.5 * radius;
pointCollection.AddPoint(point, ref missing, ref missing);
point = new PointClass();
point.X = X;
point.Y = Y + radius;
pointCollection.AddPoint(point, ref missing, ref missing);
point = new PointClass();
point.X = X - radius * c_Cosine30;
point.Y = Y - 0.5 * radius;
pointCollection.AddPoint(point, ref missing, ref missing);
m_triangle.Close();
if (m_rotation != 0.0)
{
((ITransform2D)pointCollection).Rotate(pointGeometry, m_rotation * c_Deg2Rad);
}
return;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
private void SetDefaultDymbol()
{
IColor color = (IColor)ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.Black);
ISimpleLineSymbol lineSymbol = new SimpleLineSymbolClass();
lineSymbol.Style = esriSimpleLineStyle.esriSLSSolid;
lineSymbol.Width = 1.0;
lineSymbol.Color = color;
color = (IColor)ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.Navy);
if (null == m_fillSymbol)
m_fillSymbol = new SimpleFillSymbolClass();
m_fillSymbol.Color = color;
m_fillSymbol.Style = esriSimpleFillStyle.esriSFSSolid;
m_fillSymbol.Outline = (ILineSymbol)lineSymbol;
}
/// <summary>
/// assign the triangle's geometry to the selection tracker
/// </summary>
private void RefreshTracker()
{
if (null == m_cachedDisplay)
return;
m_selectionTracker.Display = (IScreenDisplay)m_cachedDisplay;
IPolygon outline = new PolygonClass();
this.QueryOutline(m_cachedDisplay, outline);
m_selectionTracker.Geometry = (IGeometry)outline;
}
private void UpdateElementSpatialRef()
{
if (null == m_cachedDisplay ||
null == m_nativeSR ||
null == m_triangle ||
null == m_cachedDisplay.DisplayTransformation.SpatialReference)
return;
if (null == m_triangle.SpatialReference)
m_triangle.SpatialReference = m_cachedDisplay.DisplayTransformation.SpatialReference;
m_triangle.Project(m_nativeSR);
RefreshTracker();
}
private void InitMembers()
{
//initialize the selection tracker
m_selectionTracker = new PolygonTrackerClass();
m_selectionTracker.Locked = false;
m_selectionTracker.ShowHandles = true;
//set a default symbol
SetDefaultDymbol();
}
#endregion
}
}
[Visual Basic .NET]
TriangleElementClass.vb
Imports Microsoft.VisualBasic
Imports System
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Runtime.Serialization.Formatters.Binary
Imports System.IO
Imports ESRI.ArcGIS.ADF
Imports ESRI.ArcGIS.Carto
Imports ESRI.ArcGIS.Display
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.esriSystem
<ComVisible(True), Guid("DC8482C9-5DD6-44dc-BF3C-54B18AB813C9")> _
Public Interface ITriangleElement
Property FillSymbol() As ISimpleFillSymbol
Property Size() As Double
Property Angle() As Double
End Interface
<Guid(TriangleElementClass.CLASSGUID), ClassInterface(ClassInterfaceType.None), ProgId("TriangleElement.TriangleElementClass")> _
Public NotInheritable Class TriangleElementClass
Implements ITriangleElement, _
IElement, _
IElementProperties, _
IElementProperties2, _
IElementProperties3, _
IBoundsProperties, _
ITransform2D, _
IGraphicElement, _
IPersistVariant, _
IClone, _
IDocumentVersionSupportGEN
#Region "class members"
'some win32 imports and constants
<System.Runtime.InteropServices.DllImport("gdi32", EntryPoint:="GetDeviceCaps", ExactSpelling:=True, CharSet:=System.Runtime.InteropServices.CharSet.Ansi, SetLastError:=True)> _
Public Shared Function GetDeviceCaps(ByVal hDC As Integer, ByVal nIndex As Integer) As Integer
End Function
Private Const c_Cosine30 As Double = 0.866025403784439
Private Const c_Deg2Rad As Double = (Math.PI / 180.0)
Private Const c_Rad2Deg As Double = (180.0 / Math.PI)
Private Const c_Version As Integer = 2
Public Const CLASSGUID As String = "cbf943e2-ce6d-49f4-a4a7-ce16f02379ad"
Public Const LOGPIXELSX As Integer = 88
Public Const LOGPIXELSY As Integer = 90
Private m_triangle As IPolygon = Nothing
Private m_pointGeometry As IPoint = Nothing
Private m_fillSymbol As ISimpleFillSymbol = Nothing
Private m_rotation As Double = 0.0
Private m_size As Double = 20.0
Private m_selectionTracker As ISelectionTracker = Nothing
Private m_cachedDisplay As IDisplay = Nothing
Private m_nativeSR As ISpatialReference = Nothing
Private m_elementName As String = String.Empty
Private m_elementType As String = "TriangleElement"
Private m_customProperty As Object = Nothing
Private m_autoTrans As Boolean = True
Private m_scaleRef As Double = 0.0
Private m_anchorPointType As esriAnchorPointEnum = esriAnchorPointEnum.esriCenterPoint
Private m_dDeviceRatio As Double = 0
#End Region
#Region "class constructor"
Public Sub New()
'initialize the element's geometry
m_triangle = New PolygonClass()
m_triangle.SetEmpty()
InitMembers()
End Sub
#End Region
#Region "ITriangleElement Members"
Public Property FillSymbol() As ISimpleFillSymbol Implements ITriangleElement.FillSymbol
Get
Return m_fillSymbol
End Get
Set(ByVal value As ISimpleFillSymbol)
m_fillSymbol = value
End Set
End Property
Public Property Size() As Double Implements ITriangleElement.Size
Get
Return m_size
End Get
Set(ByVal value As Double)
m_size = value
End Set
End Property
Public Property Angle() As Double Implements ITriangleElement.Angle
Get
Return m_rotation
End Get
Set(ByVal value As Double)
m_rotation = value
End Set
End Property
#End Region
#Region "IElement Members"
Public Sub Activate(ByVal Display As IDisplay) Implements IElement.Activate
'cache the display
m_cachedDisplay = Display
SetupDeviceRatio(Display.hDC, Display)
'need to calculate the points of the triangle polygon
If m_triangle.IsEmpty Then
BuildTriangleGeometry(m_pointGeometry)
End If
'need to refresh the element's tracker
RefreshTracker()
End Sub
Public Sub Deactivate() Implements IElement.Deactivate
m_cachedDisplay = Nothing
End Sub
Public Sub Draw(ByVal Display As IDisplay, ByVal TrackCancel As ITrackCancel) Implements IElement.Draw
If Not Nothing Is m_triangle AndAlso Not Nothing Is m_fillSymbol Then
Display.SetSymbol(CType(m_fillSymbol, ISymbol))
Display.DrawPolygon(m_triangle)
End If
End Sub
Public Property Geometry() As IGeometry Implements IElement.Geometry
Get
Return TryCast(Clone(m_pointGeometry), IGeometry)
End Get
Set(ByVal value As IGeometry)
Try
m_pointGeometry = TryCast(Clone(value), IPoint)
UpdateElementSpatialRef()
Catch ex As Exception
System.Diagnostics.Trace.WriteLine(ex.Message)
End Try
End Set
End Property
Public Function HitTest(ByVal x As Double, ByVal y As Double, ByVal Tolerance As Double) As Boolean Implements IElement.HitTest
If Nothing Is m_cachedDisplay Then
Return False
End If
Dim point As IPoint = New PointClass()
point.PutCoords(x, y)
Return (CType(m_triangle, IRelationalOperator)).Contains(CType(point, IGeometry))
End Function
Public Property Locked() As Boolean Implements IElement.Locked
Get
Return False
End Get
Set(ByVal value As Boolean)
End Set
End Property
Public Sub QueryBounds(ByVal Display As IDisplay, ByVal Bounds As IEnvelope) Implements IElement.QueryBounds
'return a bounding envelope
Dim polygon As IPolygon = New PolygonClass()
polygon.SetEmpty()
CType(m_fillSymbol, ISymbol).QueryBoundary(Display.hDC, Display.DisplayTransformation, m_triangle, polygon)
Bounds.XMin = polygon.Envelope.XMin
Bounds.XMax = polygon.Envelope.XMax
Bounds.YMin = polygon.Envelope.YMin
Bounds.YMax = polygon.Envelope.YMax
Bounds.SpatialReference = polygon.Envelope.SpatialReference
End Sub
Public Sub QueryOutline(ByVal Display As IDisplay, ByVal Outline As IPolygon) Implements IElement.QueryOutline
'return a polygon which is the outline of the element
Dim polygon As IPolygon = New PolygonClass()
polygon.SetEmpty()
CType(m_fillSymbol, ISymbol).QueryBoundary(Display.hDC, Display.DisplayTransformation, m_triangle, polygon)
CType(Outline, IPointCollection).AddPointCollection(CType(polygon, IPointCollection))
End Sub
Public ReadOnly Property SelectionTracker() As ISelectionTracker Implements IElement.SelectionTracker
Get
Return m_selectionTracker
End Get
End Property
#End Region
#Region "IElementProperties Members"
''' <summary>
''' Indicates if transform is applied to symbols and other parts of element.
''' False = only apply transform to geometry.
''' Update font size in ITransform2D routines
''' </summary>
Public Property AutoTransform() As Boolean Implements IElementProperties.AutoTransform, IElementProperties2.AutoTransform, IElementProperties3.AutoTransform
Get
Return m_autoTrans
End Get
Set(ByVal value As Boolean)
m_autoTrans = value
End Set
End Property
Public Property CustomProperty() As Object Implements IElementProperties.CustomProperty, IElementProperties2.CustomProperty, IElementProperties3.CustomProperty
Get
Return m_customProperty
End Get
Set(ByVal value As Object)
m_customProperty = value
End Set
End Property
Public Property Name() As String Implements IElementProperties.Name, IElementProperties2.Name, IElementProperties3.Name
Get
Return m_elementName
End Get
Set(ByVal value As String)
m_elementName = value
End Set
End Property
Public Property Type() As String Implements IElementProperties.Type, IElementProperties2.Type, IElementProperties3.Type
Get
Return m_elementType
End Get
Set(ByVal value As String)
m_elementType = value
End Set
End Property
#End Region
#Region "IElementProperties2 Members"
Public Function CanRotate() As Boolean Implements IElementProperties2.CanRotate, IElementProperties3.CanRotate
Return True
End Function
Public Property ReferenceScale() As Double Implements IElementProperties2.ReferenceScale, IElementProperties3.ReferenceScale
Get
Return m_scaleRef
End Get
Set(ByVal value As Double)
m_scaleRef = value
End Set
End Property
#End Region
#Region "IElementProperties3 Members"
Public Property AnchorPoint() As esriAnchorPointEnum Implements IElementProperties3.AnchorPoint
Get
Return m_anchorPointType
End Get
Set(ByVal value As esriAnchorPointEnum)
m_anchorPointType = value
End Set
End Property
#End Region
#Region "IBoundsProperties Members"
Public Property FixedAspectRatio() As Boolean Implements IBoundsProperties.FixedAspectRatio
Get
Return True
End Get
Set(ByVal value As Boolean)
Throw New Exception("The method or operation is not implemented.")
End Set
End Property
Public ReadOnly Property FixedSize() As Boolean Implements IBoundsProperties.FixedSize
Get
Return True
End Get
End Property
#End Region
#Region "ITransform2D Members"
Public Sub Move(ByVal dx As Double, ByVal dy As Double) Implements ITransform2D.Move
If Nothing Is m_triangle Then
Return
End If
CType(m_triangle, ITransform2D).Move(dx, dy)
CType(m_pointGeometry, ITransform2D).Move(dx, dy)
RefreshTracker()
End Sub
Public Sub MoveVector(ByVal v As ILine) Implements ITransform2D.MoveVector
If Nothing Is m_triangle Then
Return
End If
CType(m_triangle, ITransform2D).MoveVector(v)
CType(m_pointGeometry, ITransform2D).MoveVector(v)
RefreshTracker()
End Sub
Public Sub Rotate(ByVal Origin As IPoint, ByVal rotationAngle As Double) Implements ITransform2D.Rotate
If Nothing Is m_triangle Then
Return
End If
CType(m_triangle, ITransform2D).Rotate(Origin, rotationAngle)
CType(m_pointGeometry, ITransform2D).Rotate(Origin, rotationAngle)
m_rotation = rotationAngle * c_Rad2Deg
RefreshTracker()
End Sub
Public Sub Scale(ByVal Origin As IPoint, ByVal sx As Double, ByVal sy As Double) Implements ITransform2D.Scale
If Nothing Is m_triangle Then
Return
End If
CType(m_triangle, ITransform2D).Scale(Origin, sx, sy)
CType(m_pointGeometry, ITransform2D).Scale(Origin, sx, sy)
If m_autoTrans Then
m_size *= Math.Max(sx, sy)
End If
RefreshTracker()
End Sub
Public Sub Transform(ByVal direction As esriTransformDirection, ByVal transformation As ITransformation) Implements ITransform2D.Transform
If Nothing Is m_triangle Then
Return
End If
'Geometry
CType(m_triangle, ITransform2D).Transform(direction, transformation)
Dim affineTrans As IAffineTransformation2D = CType(transformation, IAffineTransformation2D)
If affineTrans.YScale <> 1.0 Then
m_size *= Math.Max(affineTrans.YScale, affineTrans.XScale)
End If
RefreshTracker()
End Sub
#End Region
#Region "IGraphicElement Members"
Public Property SpatialReference() As ISpatialReference Implements IElementProperties3.SpatialReference, IGraphicElement.SpatialReference
Get
Return m_nativeSR
End Get
Set(ByVal value As ISpatialReference)
m_nativeSR = value
UpdateElementSpatialRef()
End Set
End Property
#End Region
#Region "IPersistVariant Members"
Public ReadOnly Property ID() As UID Implements IPersistVariant.ID
Get
Dim uid As UID = New UIDClass()
uid.Value = "{" & TriangleElementClass.CLASSGUID & "}"
Return uid
End Get
End Property
Public Sub Load(ByVal Stream As IVariantStream) Implements IPersistVariant.Load
Dim ver As Integer = CInt(Fix(Stream.Read()))
If ver > c_Version OrElse ver <= 0 Then
Throw New Exception("Wrong version!")
End If
InitMembers()
m_size = CDbl(Stream.Read())
m_scaleRef = CDbl(Stream.Read())
m_anchorPointType = CType(Stream.Read(), esriAnchorPointEnum)
m_autoTrans = CBool(Stream.Read())
m_elementType = CStr(Stream.Read())
m_elementName = CStr(Stream.Read())
m_nativeSR = TryCast(Stream.Read(), ISpatialReference)
m_fillSymbol = TryCast(Stream.Read(), ISimpleFillSymbol)
m_pointGeometry = TryCast(Stream.Read(), IPoint)
m_triangle = TryCast(Stream.Read(), IPolygon)
If ver = 2 Then
m_rotation = CDbl(Stream.Read())
End If
End Sub
Public Sub Save(ByVal Stream As IVariantStream) Implements IPersistVariant.Save
Stream.Write(c_Version)
Stream.Write(m_size)
Stream.Write(m_scaleRef)
Stream.Write(m_anchorPointType)
Stream.Write(m_autoTrans)
Stream.Write(m_elementType)
Stream.Write(m_elementName)
Stream.Write(m_nativeSR)
Stream.Write(m_fillSymbol)
Stream.Write(m_pointGeometry)
Stream.Write(m_triangle)
Stream.Write(m_rotation)
End Sub
#End Region
#Region "IClone Members"
Public Sub Assign(ByVal src As IClone) Implements IClone.Assign
'1. make sure that src is pointing to a valid object
If Nothing Is src Then
Throw New COMException("Invalid object.")
End If
'2. make sure that the type of src is of type 'TriangleElementClass'
If Not (TypeOf src Is TriangleElementClass) Then
Throw New COMException("Bad object type.")
End If
'3. assign the properties of src to the current instance
Dim srcTriangle As TriangleElementClass = CType(src, TriangleElementClass)
m_elementName = srcTriangle.Name
m_elementType = srcTriangle.Type
m_autoTrans = srcTriangle.AutoTransform
m_scaleRef = srcTriangle.ReferenceScale
m_rotation = srcTriangle.Angle
m_size = srcTriangle.Size
m_anchorPointType = srcTriangle.AnchorPoint
Dim objCopy As IObjectCopy = New ObjectCopyClass()
'take care of the custom property
If Not Nothing Is srcTriangle.CustomProperty Then
If TypeOf srcTriangle.CustomProperty Is IClone Then
m_customProperty = CObj((CType(srcTriangle.CustomProperty, IClone)).Clone())
ElseIf TypeOf srcTriangle.CustomProperty Is IPersistStream Then
m_customProperty = objCopy.Copy(CObj(srcTriangle.CustomProperty))
ElseIf srcTriangle.CustomProperty.GetType().IsSerializable Then
'serialize to a memory stream
Dim memoryStream As MemoryStream = New MemoryStream()
Dim binaryFormatter As BinaryFormatter = New BinaryFormatter()
binaryFormatter.Serialize(memoryStream, srcTriangle.CustomProperty)
Dim bytes As Byte() = memoryStream.ToArray()
memoryStream = New MemoryStream(bytes)
m_customProperty = binaryFormatter.Deserialize(memoryStream)
End If
End If
If Not Nothing Is srcTriangle.SpatialReference Then
m_nativeSR = TryCast(objCopy.Copy(srcTriangle.SpatialReference), ISpatialReference)
Else
m_nativeSR = Nothing
End If
If Not Nothing Is srcTriangle.FillSymbol Then
m_fillSymbol = TryCast(objCopy.Copy(srcTriangle.FillSymbol), ISimpleFillSymbol)
Else
m_fillSymbol = Nothing
End If
If Not Nothing Is srcTriangle.Geometry Then
m_triangle = TryCast(objCopy.Copy(srcTriangle.Geometry), IPolygon)
m_pointGeometry = TryCast(objCopy.Copy((CType(m_triangle, IArea)).Centroid), IPoint)
Else
m_triangle = Nothing
m_pointGeometry = Nothing
End If
End Sub
Public Function Clone() As IClone Implements IClone.Clone
Dim triangle As TriangleElementClass = New TriangleElementClass()
triangle.Assign(CType(Me, IClone))
Return CType(triangle, IClone)
End Function
Public Function IsEqual(ByVal other As IClone) As Boolean Implements IClone.IsEqual
'1. make sure that the 'other' object is pointing to a valid object
If Nothing Is other Then
Throw New COMException("Invalid object.")
End If
'2. verify the type of 'other'
If Not (TypeOf other Is TriangleElementClass) Then
Throw New COMException("Bad object type.")
End If
Dim otherTriangle As TriangleElementClass = CType(other, TriangleElementClass)
'test that all ot the object's properties are the same.
'please note the usage of IsEqual when using ArcObjects components that
'supports cloning
If otherTriangle.Name = m_elementName AndAlso otherTriangle.Type = m_elementType AndAlso otherTriangle.AutoTransform = m_autoTrans AndAlso otherTriangle.ReferenceScale = m_scaleRef AndAlso otherTriangle.Angle = m_rotation AndAlso otherTriangle.Size = m_size AndAlso otherTriangle.AnchorPoint = m_anchorPointType AndAlso (CType(otherTriangle.Geometry, IClone)).IsEqual(CType(m_triangle, IClone)) AndAlso (CType(otherTriangle.FillSymbol, IClone)).IsEqual(CType(m_fillSymbol, IClone)) AndAlso (CType(otherTriangle.SpatialReference, IClone)).IsEqual(CType(m_nativeSR, IClone)) Then
Return True
End If
Return False
End Function
Public Function IsIdentical(ByVal other As IClone) As Boolean Implements IClone.IsIdentical
'1. make sure that the 'other' object is pointing to a valid object
If Nothing Is other Then
Throw New COMException("Invalid object.")
End If
'2. verify the type of 'other'
If Not (TypeOf other Is TriangleElementClass) Then
Throw New COMException("Bad object type.")
End If
'3. test if the other is the 'this'
If CType(other, TriangleElementClass) Is Me Then
Return True
End If
Return False
End Function
#End Region
#Region "IDocumentVersionSupportGEN Members"
Public Function ConvertToSupportedObject(ByVal docVersion As esriArcGISVersion) As Object Implements IDocumentVersionSupportGEN.ConvertToSupportedObject
'in case of 8.3, create a character marker element and use a triangle marker...
Dim charMarkerSymbol As ICharacterMarkerSymbol = New CharacterMarkerSymbolClass()
charMarkerSymbol.Color = m_fillSymbol.Color
charMarkerSymbol.Angle = m_rotation
charMarkerSymbol.Size = m_size
charMarkerSymbol.Font = ESRI.ArcGIS.ADF.Connection.Local.Converter.ToStdFont(New Font("ESRI Default Marker", CSng(m_size), FontStyle.Regular))
charMarkerSymbol.CharacterIndex = 184
Dim markerElement As IMarkerElement = New MarkerElementClass()
markerElement.Symbol = CType(charMarkerSymbol, IMarkerSymbol)
Dim point As IPoint = TryCast((CType(m_pointGeometry, IClone)).Clone(), IPoint)
Dim element As IElement = CType(markerElement, IElement)
element.Geometry = CType(point, IGeometry)
Return element
End Function
Public Function IsSupportedAtVersion(ByVal docVersion As esriArcGISVersion) As Boolean Implements IDocumentVersionSupportGEN.IsSupportedAtVersion
'support all versions except 8.3
If esriArcGISVersion.esriArcGISVersion83 = docVersion Then
Return False
Else
Return True
End If
End Function
#End Region
#Region "private methods"
Private Function Clone(ByVal obj As Object) As IClone
If Nothing Is obj OrElse Not (TypeOf obj Is IClone) Then
Return Nothing
End If
Return (CType(obj, IClone)).Clone()
End Function
Private Function TwipsPerPixelX() As Integer
Return 16
End Function
Private Function TwipsPerPixelY() As Integer
Return 16
End Function
Private Sub SetupDeviceRatio(ByVal hDC As Integer, ByVal display As ESRI.ArcGIS.Display.IDisplay)
If Not display.DisplayTransformation Is Nothing Then
If display.DisplayTransformation.Resolution <> 0 Then
m_dDeviceRatio = display.DisplayTransformation.Resolution / 72
' Check the ReferenceScale of the display transformation. If not zero, we need to
' adjust the Size, XOffset and YOffset of the Symbol we hold internally before drawing.
If display.DisplayTransformation.ReferenceScale <> 0 Then
m_dDeviceRatio = m_dDeviceRatio * display.DisplayTransformation.ReferenceScale / display.DisplayTransformation.ScaleRatio
End If
End If
Else
' If we don't have a display transformation, calculate the resolution
' from the actual device.
If display.hDC <> 0 Then
' Get the resolution from the device context hDC.
m_dDeviceRatio = System.Convert.ToDouble(GetDeviceCaps(hDC, LOGPIXELSX)) / 72
Else
' If invalid hDC assume we're drawing to the screen.
m_dDeviceRatio = 1 / (TwipsPerPixelX() / 20) ' 1 Point = 20 Twips.
End If
End If
End Sub
Private Function PointsToMap(ByVal displayTransform As IDisplayTransformation, ByVal dPointSize As Double) As Double
Dim tempPointsToMap As Double = 0
If displayTransform Is Nothing Then
tempPointsToMap = dPointSize * m_dDeviceRatio
Else
tempPointsToMap = displayTransform.FromPoints(dPointSize)
End If
Return tempPointsToMap
End Function
Private Sub BuildTriangleGeometry(ByVal pointGeometry As IPoint)
Try
If Nothing Is m_triangle OrElse Nothing Is pointGeometry OrElse Nothing Is m_cachedDisplay Then
Return
End If
m_triangle.SpatialReference = pointGeometry.SpatialReference
m_triangle.SetEmpty()
Dim missing As Object = System.Reflection.Missing.Value
Dim pointCollection As IPointCollection = CType(m_triangle, IPointCollection)
Dim radius As Double = PointsToMap(m_cachedDisplay.DisplayTransformation, m_size)
Dim X As Double = pointGeometry.X
Dim Y As Double = pointGeometry.Y
Dim point As IPoint = New PointClass()
point.X = X + radius * c_Cosine30
point.Y = Y - 0.5 * radius
pointCollection.AddPoint(point, missing, missing)
point = New PointClass()
point.X = X
point.Y = Y + radius
pointCollection.AddPoint(point, missing, missing)
point = New PointClass()
point.X = X - radius * c_Cosine30
point.Y = Y - 0.5 * radius
pointCollection.AddPoint(point, missing, missing)
m_triangle.Close()
If m_rotation <> 0.0 Then
CType(pointCollection, ITransform2D).Rotate(pointGeometry, m_rotation * c_Deg2Rad)
End If
Return
Catch ex As Exception
System.Diagnostics.Trace.WriteLine(ex.Message)
End Try
End Sub
Private Sub SetDefaultDymbol()
Dim c As IColor = CType(ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.Black), IColor)
Dim lineSymbol As ISimpleLineSymbol = New SimpleLineSymbolClass()
lineSymbol.Style = esriSimpleLineStyle.esriSLSSolid
lineSymbol.Width = 1.0
lineSymbol.Color = c
c = CType(ESRI.ArcGIS.ADF.Connection.Local.Converter.ToRGBColor(Color.Navy), IColor)
If Nothing Is m_fillSymbol Then
m_fillSymbol = New SimpleFillSymbolClass()
End If
m_fillSymbol.Color = c
m_fillSymbol.Style = esriSimpleFillStyle.esriSFSSolid
m_fillSymbol.Outline = CType(lineSymbol, ILineSymbol)
End Sub
''' <summary>
''' assign the triangle's geometry to the selection tracker
''' </summary>
Private Sub RefreshTracker()
If Nothing Is m_cachedDisplay Then
Return
End If
m_selectionTracker.Display = CType(m_cachedDisplay, IScreenDisplay)
Dim outline As IPolygon = New PolygonClass()
Me.QueryOutline(m_cachedDisplay, outline)
m_selectionTracker.Geometry = CType(outline, IGeometry)
End Sub
Private Sub UpdateElementSpatialRef()
If Nothing Is m_cachedDisplay OrElse Nothing Is m_nativeSR OrElse Nothing Is m_triangle OrElse Nothing Is m_cachedDisplay.DisplayTransformation.SpatialReference Then
Return
End If
If Nothing Is m_triangle.SpatialReference Then
m_triangle.SpatialReference = m_cachedDisplay.DisplayTransformation.SpatialReference
End If
m_triangle.Project(m_nativeSR)
RefreshTracker()
End Sub
Private Sub InitMembers()
'initialize the selection tracker
m_selectionTracker = New PolygonTrackerClass()
m_selectionTracker.Locked = False
m_selectionTracker.ShowHandles = True
'set a default symbol
SetDefaultDymbol()
End Sub
#End Region
End Class