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