Imports System.Collections.ObjectModel Imports ThinkGeo.MapSuite.Core Imports ThinkGeo.MapSuite.DesktopEdition Public Class clsSnapToLayerEditInteractiveOverlay Inherits EditInteractiveOverlay Public Enum ToleranceCoordinates World Screen End Enum Private m_controlPointStyle As PointStyle Private m_draggedControlPointStyle As PointStyle Private m_toSnapInMemoryFeatureLayer As InMemoryFeatureLayer Private m_tolerance As Single 'private int tolerancePixel; Private m_toleranceUnit As DistanceUnit Private geographyUnit As GeographyUnit Private currentWorldExtent As RectangleShape Private mapWidth As Single Private mapHeight As Single Private m_toleranceType As ToleranceCoordinates 'Property for the non dragged control point style. Public Property ControlPointStyle() As PointStyle Get Return m_controlPointStyle End Get Set(ByVal value As PointStyle) m_controlPointStyle = value End Set End Property 'Property for the dragged control point style. Public Property DraggedControlPointStyle() As PointStyle Get Return m_draggedControlPointStyle End Get Set(ByVal value As PointStyle) m_draggedControlPointStyle = value End Set End Property 'InMemoryFeatureLayer for the layer to be snapped to. Public Property ToSnapInMemoryFeatureLayer() As InMemoryFeatureLayer Get Return m_toSnapInMemoryFeatureLayer End Get Set(ByVal value As InMemoryFeatureLayer) m_toSnapInMemoryFeatureLayer = value End Set End Property Public Property ToleranceType() As ToleranceCoordinates Get Return m_toleranceType End Get Set(ByVal value As ToleranceCoordinates) m_toleranceType = value End Set End Property Public Property Tolerance() As Single Get Return m_tolerance End Get Set(ByVal value As Single) m_tolerance = value End Set End Property Public Property ToleranceUnit() As DistanceUnit Get Return m_toleranceUnit End Get Set(ByVal value As DistanceUnit) m_toleranceUnit = value End Set End Property Protected Overrides Function MouseMoveCore(ByVal interactionArguments As ThinkGeo.MapSuite.DesktopEdition.InteractionArguments) As ThinkGeo.MapSuite.DesktopEdition.InteractiveResult Dim snapPointShape As PointShape = Nothing If m_toleranceType = ToleranceCoordinates.Screen Then snapPointShape = FindNearestSnappingPointPixel(New PointShape(interactionArguments.WorldX, interactionArguments.WorldY), interactionArguments.CurrentExtent, interactionArguments.MapWidth, interactionArguments.MapHeight) Else snapPointShape = FindNearestSnappingPoint(New PointShape(interactionArguments.WorldX, interactionArguments.WorldY)) End If Dim oInteractionArguments As New InteractionArguments() If snapPointShape IsNot Nothing Then If m_toleranceType = ToleranceCoordinates.Screen Then Dim oScreenPoint As ScreenPointF oScreenPoint = ExtentHelper.ToScreenCoordinate(interactionArguments.CurrentExtent, snapPointShape, interactionArguments.MapWidth, interactionArguments.MapHeight) oInteractionArguments.ScreenX = oScreenPoint.X oInteractionArguments.ScreenY = oScreenPoint.Y Else oInteractionArguments.WorldX = snapPointShape.X oInteractionArguments.WorldY = snapPointShape.Y End If End If Return MyBase.MouseMoveCore(oInteractionArguments) End Function 'Function to find if dragged control point is within the tolerance of a vertex of layer in screen (pixels) coordinates. Private Function FindNearestSnappingPointPixel(ByVal targetPointShape As PointShape, ByVal _CurrentExtent As RectangleShape, ByVal _MapWidh As Integer, ByVal _MapHeight As Integer) As PointShape m_toSnapInMemoryFeatureLayer.Open() Dim toSnapInMemoryFeatures As Collection(Of Feature) = m_toSnapInMemoryFeatureLayer.FeatureSource.GetFeaturesNearestTo(targetPointShape, geographyUnit.Meter, 1, ReturningColumnsType.AllColumns) m_toSnapInMemoryFeatureLayer.Close() If toSnapInMemoryFeatures.Count = 1 Then Dim polygonShape As PolygonShape = DirectCast(toSnapInMemoryFeatures(0).GetShape(), PolygonShape) For Each vertex As Vertex In polygonShape.OuterRing.Vertices Dim toSnapPointShape As New PointShape(vertex) Dim screenDistance As Single = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(_CurrentExtent, toSnapPointShape, targetPointShape, _MapWidh, _MapHeight) If screenDistance <= m_tolerance Then Return New PointShape(toSnapPointShape.X, toSnapPointShape.Y) End If Next End If Return Nothing End Function 'Function to find if dragged control point is within the tolerance of a vertex of layer in world coordinates. Private Function FindNearestSnappingPoint(ByVal targetPointShape As PointShape) As PointShape m_toSnapInMemoryFeatureLayer.Open() Dim toSnapInMemoryFeatures As Collection(Of Feature) = m_toSnapInMemoryFeatureLayer.FeatureSource.GetFeaturesNearestTo(targetPointShape, geographyUnit.Meter, 1, ReturningColumnsType.AllColumns) m_toSnapInMemoryFeatureLayer.Close() If toSnapInMemoryFeatures.Count = 1 Then Dim polygonShape As PolygonShape = DirectCast(toSnapInMemoryFeatures(0).GetShape(), PolygonShape) For Each vertex As Vertex In polygonShape.OuterRing.Vertices Dim toSnapPointShape As New PointShape(vertex) Dim Distance As Double = toSnapPointShape.GetDistanceTo(targetPointShape, geographyUnit, m_toleranceUnit) If Distance <= m_tolerance Then Return New PointShape(toSnapPointShape.X, toSnapPointShape.Y) End If Next End If Return Nothing End Function 'Overrides the DrawCore function to draw the Edit Layers, the vertices and tolerance ellipses of layer to snap to, 'and the control points. Protected Overrides Sub DrawCore(ByVal canvas As GeoCanvas) 'Sets the geography Unit used in FindNearestSnappingPoint function geographyUnit = canvas.MapUnit currentWorldExtent = canvas.CurrentWorldExtent mapWidth = canvas.Width mapHeight = canvas.Height 'Draws the Edit Shapes as default. Dim labelsInAllLayers As New Collection(Of SimpleCandidate)() EditShapesLayer.Open() EditShapesLayer.Draw(canvas, labelsInAllLayers) canvas.Flush() 'Draw the vertices and tolerance ellipses of layer to snap to. m_toSnapInMemoryFeatureLayer.Open() Dim toSnapPoints As Collection(Of Feature) = m_toSnapInMemoryFeatureLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns) m_toSnapInMemoryFeatureLayer.Close() For Each feature As Feature In toSnapPoints Dim polygonShape As PolygonShape = DirectCast(feature.GetShape(), PolygonShape) For Each vertex As Vertex In polygonShape.OuterRing.Vertices 'Draws the vertex. Dim pointShape As New PointShape(vertex) canvas.DrawEllipse(pointShape, 5, 5, New GeoSolidBrush(GeoColor.StandardColors.Black), DrawingLevel.LevelOne) 'Draws the tolerance ellipse. If m_toleranceType = ToleranceCoordinates.Screen Then Dim screenPointF As ScreenPointF = ExtentHelper.ToScreenCoordinate(canvas.CurrentWorldExtent, pointShape, canvas.Width, canvas.Height) canvas.DrawEllipse(screenPointF, m_tolerance * 2, m_tolerance * 2, New GeoPen(GeoColor.StandardColors.Black), New GeoSolidBrush(), DrawingLevel.LevelFour, _ 0, 0, PenBrushDrawingOrder.PenFirst) Else Dim ellipseShape As New EllipseShape(pointShape, m_tolerance, canvas.MapUnit, m_toleranceUnit) canvas.DrawArea(ellipseShape, New GeoPen(GeoColor.StandardColors.Black), DrawingLevel.LevelOne) End If Next Next 'Draws the control points. ExistingControlPointsLayer.Open() Dim controlPoints As Collection(Of Feature) = ExistingControlPointsLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns) 'Loops thru the control points. For Each feature As Feature In controlPoints 'Looks at the value of "state" to draw the control point as dragged or not. If feature.ColumnValues("state") <> "selected" Then Dim features As Feature() = New Feature(0) {feature} m_controlPointStyle.Draw(features, canvas, labelsInAllLayers, labelsInAllLayers) Else Dim features As Feature() = New Feature(0) {feature} m_draggedControlPointStyle.Draw(features, canvas, labelsInAllLayers, labelsInAllLayers) End If Next End Sub End Class