====== Source Code DesktopEditionSample VertexTolerance CS 091210.zip ====== ====Program.cs==== using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace VertexTolerance { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new TestForm()); } } } ====TestForm.cs==== using System; using System.IO; using System.Windows.Forms; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.DesktopEdition; namespace VertexTolerance { public partial class TestForm : Form { public TestForm() { InitializeComponent(); } private void TestForm_Load(object sender, EventArgs e) { winformsMap1.MapUnit = GeographyUnit.DecimalDegree; winformsMap1.CurrentExtent = new RectangleShape(-97.7591, 30.3126, -97.7317, 30.2964); winformsMap1.BackgroundOverlay.BackgroundBrush = new GeoSolidBrush(GeoColor.FromArgb(255, 198, 255, 255)); //Displays the World Map Kit as a background. ThinkGeo.MapSuite.DesktopEdition.WorldMapKitWmsDesktopOverlay worldMapKitDesktopOverlay = new ThinkGeo.MapSuite.DesktopEdition.WorldMapKitWmsDesktopOverlay(); winformsMap1.Overlays.Add(worldMapKitDesktopOverlay); string fileName1 = @"..\..\data\polygon.txt"; StreamReader sr1 = new StreamReader(fileName1); //VertexToleranceEditInteractiveOverlay to keep a set tolerance between the dragged control point and other control points of the edit shape. VertexToleranceEditInteractiveOverlay vertexToleranceEditInteractiveOverlay = new VertexToleranceEditInteractiveOverlay(); vertexToleranceEditInteractiveOverlay.EditShapesLayer.InternalFeatures.Add("Polygon", new Feature(BaseShape.CreateShapeFromWellKnownData(sr1.ReadLine()))); //Sets the PointStyle for the non dragged control points. vertexToleranceEditInteractiveOverlay.ControlPointStyle = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.StandardColors.PaleGoldenrod), new GeoPen(GeoColor.StandardColors.Black), 8); //Sets the PointStyle for the dragged control points. vertexToleranceEditInteractiveOverlay.DraggedControlPointStyle = new PointStyle(PointSymbolType.Circle, new GeoSolidBrush(GeoColor.StandardColors.Red), new GeoPen(GeoColor.StandardColors.Orange, 2), 10); vertexToleranceEditInteractiveOverlay.CanDrag = false; vertexToleranceEditInteractiveOverlay.Tolerance = 100; vertexToleranceEditInteractiveOverlay.ToleranceUnit = DistanceUnit.Meter; vertexToleranceEditInteractiveOverlay.CalculateAllControlPoints(); winformsMap1.EditOverlay = vertexToleranceEditInteractiveOverlay; winformsMap1.Refresh(); } private void winformsMap1_MouseMove(object sender, MouseEventArgs e) { //Displays the X and Y in screen coordinates. statusStrip1.Items["toolStripStatusLabelScreen"].Text = "X:" + e.X + " Y:" + e.Y; //Gets the PointShape in world coordinates from screen coordinates. PointShape pointShape = ExtentHelper.ToWorldCoordinate(winformsMap1.CurrentExtent, new ScreenPointF(e.X, e.Y), winformsMap1.Width, winformsMap1.Height); //Displays world coordinates. statusStrip1.Items["toolStripStatusLabelWorld"].Text = "(world) X:" + Math.Round(pointShape.X, 4) + " Y:" + Math.Round(pointShape.Y, 4); } private void btnClose_Click(object sender, EventArgs e) { this.Close(); } private void winformsMap1_MouseUp(object sender, MouseEventArgs e) { //Gets the PointShape in world coordinates from screen coordinates. PointShape pointShape = ExtentHelper.ToWorldCoordinate(winformsMap1.CurrentExtent, new ScreenPointF(e.X, e.Y), winformsMap1.Width, winformsMap1.Height); System.Diagnostics.Debug.WriteLine(pointShape.X + " " + pointShape.Y); } } } ====VertexToleranceEditInteractiveOverlay.cs==== using System.Collections.ObjectModel; using System.Collections.Generic; using ThinkGeo.MapSuite.Core; using ThinkGeo.MapSuite.DesktopEdition; namespace VertexTolerance { class VertexToleranceEditInteractiveOverlay : EditInteractiveOverlay { private PointStyle controlPointStyle; private PointStyle draggedControlPointStyle; private double tolerance; private DistanceUnit toleranceUnit; private GeographyUnit geographyUnit; //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; } } //Toerance distance to keep on the control points public double Tolerance { get { return tolerance; } set { tolerance = value; } } public DistanceUnit ToleranceUnit { get { return toleranceUnit; } set { toleranceUnit = value; } } //Overrides the MoveVertexCore to have the logic to not allow dragged control within the tolerance area. protected override Feature MoveVertexCore(Feature sourceFeature, PointShape sourceControlPoint, PointShape targetControlPoint) { VertexMovingEditInteractiveOverlayEventArgs vertexMovingEditInteractiveOverlayEventArgs = new VertexMovingEditInteractiveOverlayEventArgs(false, sourceFeature, new Vertex(targetControlPoint)); ExistingControlPointsLayer.Open(); Collection controlPoints = ExistingControlPointsLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns); EllipseShape toleranceEllipse = null; //Loops thru the control points. foreach (Feature feature in controlPoints) { //Checks the distance of dragged control point to the other control points to know if within tolerance or not and //gets the tolerance ellipseShape. if (feature.ColumnValues["state"] != "selected") { PointShape pointShape = (PointShape)feature.GetShape(); double Dist = pointShape.GetDistanceTo(targetControlPoint, geographyUnit, toleranceUnit); if (Dist <= Tolerance) { toleranceEllipse = new EllipseShape(pointShape, tolerance, geographyUnit, toleranceUnit); break; } } } //If within tolerance. if (toleranceEllipse != null) { //If within tolerance gets other EllipseShapes within tolerance. EllipseShape[] neighborEllipseShapes = GetNeighborEllipseShapes(toleranceEllipse); //Unions and gets the LineShape (perimeter) of the unioned MultipolygonShape. //Then we get the closet point to mouse pointer on the lineShape to have the effect of the dragged control point //staying outside the tolerance. MultipolygonShape unionMultiPolygonShape = PolygonShape.Union(neighborEllipseShapes); LineShape ellipseLineShape = ToLineShape(unionMultiPolygonShape); PointShape onEllipsePointShape = ellipseLineShape.GetClosestPointTo(targetControlPoint, geographyUnit); vertexMovingEditInteractiveOverlayEventArgs.MovingVertex = new Vertex(onEllipsePointShape); } return base.MoveVertexCore(sourceFeature, sourceControlPoint, new PointShape(vertexMovingEditInteractiveOverlayEventArgs.MovingVertex)); } private EllipseShape[] GetNeighborEllipseShapes( EllipseShape ellipseShape) { ExistingControlPointsLayer.Open(); Collection controlPoints = ExistingControlPointsLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns); List neighborEllipseShapes = new List(); //Loops thru the control points. foreach (Feature feature in controlPoints) { //Looks at the value of "state" for the non dragged point controls. if (feature.ColumnValues["state"] != "selected") { PointShape pointShape = (PointShape)feature.GetShape(); double Dist = pointShape.GetDistanceTo(ellipseShape, geographyUnit, toleranceUnit); if (Dist <= Tolerance) { EllipseShape neighborEllipseShape = new EllipseShape(pointShape, tolerance, GeographyUnit.DecimalDegree, toleranceUnit); neighborEllipseShapes.Add(neighborEllipseShape); } } } return neighborEllipseShapes.ToArray(); } private LineShape ToLineShape(MultipolygonShape multiPolygonShape) { LineShape lineShape = new LineShape(); foreach (Vertex vertex in multiPolygonShape.Polygons[0].OuterRing.Vertices) { lineShape.Vertices.Add(vertex); } return lineShape; } //Overrides the DrawCore function to draw the Edit Layers, the vertices and tolerance ellipses, //and the control points. protected override void DrawCore(GeoCanvas canvas) { //Sets the geography Unit used in FindNearestSnappingPoint function geographyUnit = canvas.MapUnit; //Draws the Edit Shapes as default. Collection labelsInAllLayers = new Collection(); EditShapesLayer.Open(); EditShapesLayer.Draw(canvas, labelsInAllLayers); canvas.Flush(); //Draws the control points. ExistingControlPointsLayer.Open(); Collection controlPoints = ExistingControlPointsLayer.FeatureSource.GetAllFeatures(ReturningColumnsType.AllColumns); //Loops thru the control points. foreach (Feature feature in controlPoints) { //Looks at the value of "state" to draw the control point as dragged or not. if (feature.ColumnValues["state"] != "selected") { Feature[] features = new Feature[1] { feature }; controlPointStyle.Draw(features, canvas, labelsInAllLayers, labelsInAllLayers); PointShape pointShape = (PointShape)feature.GetShape(); //Draws the ellipse. EllipseShape ellipseShape = new EllipseShape(pointShape, tolerance, canvas.MapUnit, toleranceUnit); canvas.DrawArea(ellipseShape, new GeoPen(GeoColor.StandardColors.Black), DrawingLevel.LevelOne); } else { Feature[] features = new Feature[1] { feature }; draggedControlPointStyle.Draw(features, canvas, labelsInAllLayers, labelsInAllLayers); } } } } }