using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.WpfDesktopEdition; using System.Windows.Input; using Invivo.Framework; namespace Invivo.Workspaces.Map { public class SnapToLayerEditInteractiveOverlay : EditInteractiveOverlay { private PointStyle controlPointStyle; private PointStyle draggedControlPointStyle; private PointStyle selectedControlPointStyle; private InMemoryFeatureLayer toSnapInMemoryFeatureLayer; private float tolerance; private DistanceUnit toleranceUnit; private GeographyUnit geographyUnit; private bool labelDisplay; private RectangleShape currentWorldExtent; private float mapWidth; private float mapHeight; private ToleranceCoordinates toleranceType; private Dictionary polygonesCut; public SnapToLayerEditInteractiveOverlay() : base() { this.CanAddVertex = true; //this.CanDrag = true; this.CanDrag = false; this.CanRemoveVertex = true; this.CanResize = false; this.CanRotate = false; ExistingControlPointsLayer.Open(); ExistingControlPointsLayer.Columns.Add(new FeatureSourceColumn("IsSelected")); ExistingControlPointsLayer.Close(); } //Property for the non dragged control point style. public PointStyle ControlPointStyle { get { return controlPointStyle; } set { controlPointStyle = value; } } //Property for the dragged control point style. public PointStyle DraggedControlPointStyle { get { return draggedControlPointStyle; } set { draggedControlPointStyle = value; } } public PointStyle SelectedControlPointStyle { get { return selectedControlPointStyle; } set { selectedControlPointStyle = value; } } //InMemoryFeatureLayer for the layer to be snapped to. public InMemoryFeatureLayer ToSnapInMemoryFeatureLayer { get { return toSnapInMemoryFeatureLayer; } set { toSnapInMemoryFeatureLayer = value; } } public ToleranceCoordinates ToleranceType { get { return toleranceType; } set { toleranceType = value; } } public float Tolerance { get { return tolerance; } set { tolerance = value; } } public DistanceUnit ToleranceUnit { get { return toleranceUnit; } set { toleranceUnit = value; } } public bool LabelDisplay { get {return labelDisplay;} set { labelDisplay = value; } } public Dictionary PolygonesCut { get { return polygonesCut; } set { polygonesCut = value; } } protected override Feature MoveVertexCore(Feature sourceFeature, PointShape sourceControlPoint, PointShape targetControlPoint) { VertexMovingEditInteractiveOverlayEventArgs vertexMovingEditInteractiveOverlayEventArgs = new VertexMovingEditInteractiveOverlayEventArgs(false, sourceFeature, new Vertex(targetControlPoint)); if (Keyboard.Modifiers != ModifierKeys.Shift) { PointShape snapPointShape = null; if (toleranceType == ToleranceCoordinates.Screen) { snapPointShape = FindNearestSnappingPointPixel(targetControlPoint); } else { snapPointShape = FindNearestSnappingPoint(targetControlPoint); } if (snapPointShape != null) { vertexMovingEditInteractiveOverlayEventArgs.MovingVertex = new Vertex(snapPointShape); } } return base.MoveVertexCore(sourceFeature, sourceControlPoint, new PointShape(vertexMovingEditInteractiveOverlayEventArgs.MovingVertex)); } //Function to find if dragged control point is within the tolerance of a vertex of layer in screen (pixels) coordinates. private PointShape FindNearestSnappingPointPixel(PointShape targetPointShape) { toSnapInMemoryFeatureLayer.Open(); Collection toSnapInMemoryFeatures = toSnapInMemoryFeatureLayer.FeatureSource.GetFeaturesNearestTo(targetPointShape, GeographyUnit.Meter, 3, ReturningColumnsType.AllColumns); toSnapInMemoryFeatureLayer.Close(); if (toSnapInMemoryFeatures.Any()) { foreach (Feature f in toSnapInMemoryFeatures) { PolygonShape polygonShape = (PolygonShape)f.GetShape(); foreach (Vertex vertex in polygonShape.OuterRing.Vertices) { PointShape toSnapPointShape = new PointShape(vertex); float screenDistance = ExtentHelper.GetScreenDistanceBetweenTwoWorldPoints(currentWorldExtent, toSnapPointShape, targetPointShape, mapWidth, mapHeight); if (screenDistance <= tolerance) { return new PointShape(toSnapPointShape.X, toSnapPointShape.Y); } } } } return null; } //Function to find if dragged control point is within the tolerance of a vertex of layer in world coordinates. private PointShape FindNearestSnappingPoint(PointShape targetPointShape) { toSnapInMemoryFeatureLayer.Open(); Collection toSnapInMemoryFeatures = toSnapInMemoryFeatureLayer.FeatureSource.GetFeaturesNearestTo(targetPointShape, GeographyUnit.Meter, 3, ReturningColumnsType.AllColumns); toSnapInMemoryFeatureLayer.Close(); if (toSnapInMemoryFeatures.Any()) { foreach (Feature f in toSnapInMemoryFeatures) { PolygonShape polygonShape = new PolygonShape(); switch (f.GetWellKnownType()) { case WellKnownType.Polygon: polygonShape = (PolygonShape)f.GetShape(); break; case WellKnownType.Multipolygon: double area = 0.0; foreach (PolygonShape p in ((MultipolygonShape)f.GetShape()).Polygons) { if (area < p.GetArea(OutilsOvLyr.MapGeographyUnit, OutilsOvLyr.MapUniteSurface)) { polygonShape = p; area = p.GetArea(OutilsOvLyr.MapGeographyUnit, OutilsOvLyr.MapUniteSurface); } } break; } foreach (Vertex vertex in polygonShape.OuterRing.Vertices) { PointShape toSnapPointShape = new PointShape(vertex); double Distance = toSnapPointShape.GetDistanceTo(targetPointShape, geographyUnit, toleranceUnit); if (Distance <= tolerance) { return new PointShape(toSnapPointShape.X, toSnapPointShape.Y); } } } } return null; } protected override InteractiveResult MouseClickCore(InteractionArguments interactionArguments) { InteractiveResult result = base.MouseClickCore(interactionArguments); if (ExistingControlPointsLayer.InternalFeatures.Any()) { if (result.DrawThisOverlay != InteractiveOverlayDrawType.Draw) { RectangleShape searchingArea = new RectangleShape(interactionArguments.WorldX - interactionArguments.SearchingTolerance, interactionArguments.WorldY + interactionArguments.SearchingTolerance, interactionArguments.WorldX + interactionArguments.SearchingTolerance, interactionArguments.WorldY - interactionArguments.SearchingTolerance); ExistingControlPointsLayer.InternalFeatures.ToList().ForEach(p => p.ColumnValues["IsSelected"] = ""); foreach (Feature feature in ExistingControlPointsLayer.InternalFeatures) { BaseShape shape = feature.GetShape(); if (shape.IsWithin(searchingArea)) { if (feature.ColumnValues.ContainsKey("IsSelected") && (feature.ColumnValues["IsSelected"] == "true")) { feature.ColumnValues["IsSelected"] = string.Empty; result.DrawThisOverlay = InteractiveOverlayDrawType.Draw; result.ProcessOtherOverlaysMode = ProcessOtherOverlaysMode.DoNotProcessOtherOverlays; break; } else { feature.ColumnValues["IsSelected"] = "true"; result.DrawThisOverlay = InteractiveOverlayDrawType.Draw; result.ProcessOtherOverlaysMode = ProcessOtherOverlaysMode.DoNotProcessOtherOverlays; break; } } } } } return result; } protected override void DrawTileCore(GeoCanvas geoCanvas) { //Sets the geography Unit used in FindNearestSnappingPoint function geographyUnit = geoCanvas.MapUnit; currentWorldExtent = geoCanvas.CurrentWorldExtent; mapWidth = geoCanvas.Width; mapHeight = geoCanvas.Height; //Draws the Edit Shapes as default. Collection labelsInAllLayers = new Collection(); EditShapesLayer.Open(); EditShapesLayer.Draw(geoCanvas, labelsInAllLayers); geoCanvas.Flush(); //Draws the control points. ExistingControlPointsLayer.Open(); Collection controlPoints = ExistingControlPointsLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns); //Loops thru the control points. foreach (Feature feature in controlPoints) { if (feature.ColumnValues.ContainsKey("IsSelected") && feature.ColumnValues["IsSelected"] == "true") { Feature[] features = new Feature[1] { feature }; selectedControlPointStyle.Draw(features, geoCanvas, labelsInAllLayers, labelsInAllLayers); } else if (feature.ColumnValues["state"] != "selected") { Feature[] features = new Feature[1] { feature }; controlPointStyle.Draw(features, geoCanvas, labelsInAllLayers, labelsInAllLayers); } else { Feature[] features = new Feature[1] { feature }; draggedControlPointStyle.Draw(features, geoCanvas, labelsInAllLayers, labelsInAllLayers); } } if (labelDisplay) { if (polygonesCut != null) { foreach (KeyValuePair d in polygonesCut) { ScreenPointF screenPoint = ExtentHelper.ToScreenCoordinate(geoCanvas.CurrentWorldExtent, new PointShape(((PolygonShape)d.Key).OuterRing.GetCenterPoint().X, ((PolygonShape)d.Key).OuterRing.GetCenterPoint().Y), geoCanvas.Width, geoCanvas.Height); geoCanvas.DrawTextWithScreenCoordinate(System.Convert.ToString(d.Value), new GeoFont("Arial", 12, DrawingFontStyles.Bold), new GeoSolidBrush(GeoColor.StandardColors.Black), screenPoint.X, screenPoint.Y, DrawingLevel.LabelLevel); } } } } } }