====== Source Code ServicesEditionSample SplitPolygon CS 091121.zip ====== ====Program.cs==== using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace SplitPolygon { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new TestForm()); } } } ====Splitter.cs==== using System; using System.Collections.ObjectModel; using ThinkGeo.MapSuite.Core; namespace SplitPolygon { public static class Splitter { public static Collection GetPerpendicularLines(LineShape lineShape, Collection interceptedPoints, double length) { Collection returnFeatures = new Collection(); double halfLength = length / 2; double pi2 = Math.PI / 2; double searchingTolerance = 0.000001; foreach (PointShape interceptedPoint in interceptedPoints) { RectangleShape searchingArea = new RectangleShape(interceptedPoint.X - searchingTolerance, interceptedPoint.Y + searchingTolerance, interceptedPoint.X + searchingTolerance, interceptedPoint.Y - searchingTolerance); // Check if the intercepted point is the vertex will be ignore, because we can not create perpendicular line crosses vertex. foreach (Vertex vertex in lineShape.Vertices) { if (new PointShape(vertex).IsWithin(searchingArea)) { continue; } } double middleX = interceptedPoint.X; double middleY = interceptedPoint.Y; Vertex vertex1 = new Vertex(); Vertex vertex2 = new Vertex(); // Find the crossing point is between which two vertices for (int i = 0; i < lineShape.Vertices.Count - 1; i++) { vertex1 = lineShape.Vertices[i]; vertex2 = lineShape.Vertices[i|+ 1]; LineShape currentLine = new LineShape(new Vertex[] { vertex1, vertex2 }); if (searchingArea.Intersects(currentLine)) { break; } } double angle = Math.Atan((vertex1.Y - vertex2.Y) / (vertex1.X - vertex2.X)); double x = 0; double y = 0; if (angle > 0 && angle < pi2) { if (vertex1.X > vertex2.X) { x = middleX + Math.Sin(angle) * halfLength; y = middleY - Math.Cos(angle) * halfLength; } else { x = middleX - Math.Sin(angle) * halfLength; y = middleY + Math.Cos(angle) * halfLength; } } else { if (vertex1.X > vertex2.X) { x = middleX + Math.Sin(angle) * halfLength; y = middleY - Math.Cos(angle) * halfLength; } else { x = middleX - Math.Sin(angle) * halfLength; y = middleY + Math.Cos(angle) * halfLength; } } Vertex anotherVertex = new Vertex(middleX * 2 - x, middleY * 2 - y); LineShape line = new LineShape(new Vertex[] { anotherVertex, new Vertex(x, y) }); returnFeatures.Add(line); } return returnFeatures; } public static PolygonShape SplitPolygonWithTwoLines(PolygonShape processedPolygon, LineShape lineShape1, LineShape lineShape2) { MultipolygonShape resultMultipolygon = Split(processedPolygon, lineShape1); PolygonShape resultShape = new PolygonShape(); foreach (PolygonShape polygonShape in resultMultipolygon.Polygons) { MultipointShape intersectionMultiPoint = lineShape2.GetCrossing(polygonShape.OuterRing); if (intersectionMultiPoint.Points.Count == 2) { MultipolygonShape resultMultipolygon1 = Split(polygonShape, lineShape2); foreach (PolygonShape polygonShape1 in resultMultipolygon1.Polygons) { MultipointShape intersectionMultiPoint1 = lineShape2.GetCrossing(polygonShape.OuterRing); if (intersectionMultiPoint1.Points.Count == 2) { resultShape = polygonShape1; break; } } } } return resultShape; } public static MultipolygonShape Split(PolygonShape processedPolygon, LineShape lineShape) { MultipolygonShape resultShape = new MultipolygonShape(); MultipointShape intersectionMultiPoint = lineShape.GetCrossing(processedPolygon.OuterRing); if (intersectionMultiPoint.Points.Count == 2) { PolygonShape polygonShape1 = GetPolygonForSplit(processedPolygon, lineShape, false); PolygonShape polygonShape2 = GetPolygonForSplit(processedPolygon, lineShape, true); resultShape.Polygons.Add(polygonShape1); resultShape.Polygons.Add(polygonShape2); } return resultShape; } private static PolygonShape GetPolygonForSplit(PolygonShape processedPolygon, LineShape lineShape, bool changeOrder) { MultipointShape intersectionMultiPoint = lineShape.GetCrossing(processedPolygon.OuterRing); if (changeOrder) { PointShape tempPointShape = intersectionMultiPoint.Points[0]; intersectionMultiPoint.Points[0] = intersectionMultiPoint.Points[1]; intersectionMultiPoint.Points[1] = tempPointShape; } if (intersectionMultiPoint.Points.Count == 2) { PolygonShape resultPolygonShape = new PolygonShape(); RingShape resultOuterRing = SplitRing(processedPolygon.OuterRing, intersectionMultiPoint.Points[0], intersectionMultiPoint.Points[1]); resultPolygonShape.OuterRing = resultOuterRing; foreach (RingShape innerRing in processedPolygon.InnerRings) { MultipointShape innerIntersectionMultiPoint = lineShape.GetCrossing(innerRing); if (innerIntersectionMultiPoint.Points.Count == 2) { RingShape resultInnerRing = SplitRing(innerRing, innerIntersectionMultiPoint.Points[0], innerIntersectionMultiPoint.Points[1]); if (resultPolygonShape.Contains(resultInnerRing)) { resultPolygonShape.InnerRings.Add(resultInnerRing); } } else { if (resultPolygonShape.Contains(innerRing)) { resultPolygonShape.InnerRings.Add(innerRing); } } } return resultPolygonShape; } return null; } public static bool DoesPointShapeBelongToLineSegment(PointShape pointShape, PointShape linePointShape1, PointShape linePointShape2) { bool result = false; double a = 0; double b = 0; if ((pointShape.X == linePointShape1.X & pointShape.Y == linePointShape1.Y) | (pointShape.X == linePointShape2.X & pointShape.Y == linePointShape2.Y)) { result = true; } else { if (linePointShape1.X != linePointShape2.X) { a = (linePointShape2.Y - linePointShape1.Y) / (linePointShape2.X - linePointShape1.X); b = linePointShape1.Y - (a * linePointShape1.X); if (Math.Round(pointShape.Y, 5) == Math.Round((a * pointShape.X) + b, 5) & pointShape.X >= Math.Min(linePointShape1.X, linePointShape2.X) & pointShape.X <= Math.Max(linePointShape1.X, linePointShape2.X)) { result = true; } else { result = false; } } else { if (pointShape.X == linePointShape1.X & (pointShape.Y >= Math.Min(linePointShape1.Y, linePointShape2.Y) & pointShape.Y <= Math.Max(linePointShape1.Y, linePointShape2.Y))) { result = true; } else { result = false; } } } return result; } public static RingShape SplitRing(RingShape processedRing, PointShape intersectionPointShape1, PointShape intersectionPointShape2) { RingShape resultRingShape = new RingShape(); int i = 0; int totalPointNumber = processedRing.Vertices.Count; while (i < totalPointNumber - 1) { int indexA = i + 1; if (DoesPointShapeBelongToLineSegment(intersectionPointShape1, new PointShape(processedRing.Vertices[i]), new PointShape(processedRing.Vertices[indexA]))) { resultRingShape.Vertices.Add(new Vertex(intersectionPointShape1)); if (DoesPointShapeBelongToLineSegment(intersectionPointShape2, new PointShape(processedRing.Vertices[i]), new PointShape(processedRing.Vertices[indexA]))) { resultRingShape.Vertices.Add(new Vertex(intersectionPointShape2)); resultRingShape.Vertices.Add(new Vertex(intersectionPointShape1)); } else { for (int j = i + 1; j <= processedRing.Vertices.Count - 1; j++) { //- 1 int indexB = j + 1; if (j < processedRing.Vertices.Count - 1) { if (DoesPointShapeBelongToLineSegment(intersectionPointShape2, new PointShape(processedRing.Vertices[j]), new PointShape(processedRing.Vertices[indexB]))) { resultRingShape.Vertices.Add(processedRing.Vertices[j]); resultRingShape.Vertices.Add(new Vertex(intersectionPointShape2)); resultRingShape.Vertices.Add(new Vertex(intersectionPointShape1)); break; // TODO: might not be correct. Was : Exit For } else { resultRingShape.Vertices.Add(processedRing.Vertices[j]); } } else { for (int k = 0; k < i; k++) { if (DoesPointShapeBelongToLineSegment(intersectionPointShape2, new PointShape(processedRing.Vertices[k]), new PointShape(processedRing.Vertices[(k|+ 1)]))) { resultRingShape.Vertices.Add(processedRing.Vertices[k]); resultRingShape.Vertices.Add(new Vertex(intersectionPointShape2)); resultRingShape.Vertices.Add(new Vertex(intersectionPointShape1)); break; // TODO: might not be correct. Was : Exit For } else { resultRingShape.Vertices.Add(processedRing.Vertices[k]); } } break; // TODO: might not be correct. Was : Exit For } } } return resultRingShape; } i = i + 1; } return null; } } } ====TestForm.cs==== using System; using System.Collections.ObjectModel; using System.Drawing; using System.Windows.Forms; using ThinkGeo.MapSuite.Core; namespace SplitPolygon { public partial class TestForm : Form { private MapEngine mapEngine = new MapEngine(); private Bitmap bitmap = null; public TestForm() { InitializeComponent(); } private void TestForm_Load(object sender, EventArgs e) { // Set the extent and the background color mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-97.7521,30.3097,-97.7396,30.3025), Map.Width, Map.Height); mapEngine.BackgroundFillBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean); //Displays the World Map Kit as a background. ThinkGeo.MapSuite.Core.WorldMapKitLayer worldMapKitLayer = new ThinkGeo.MapSuite.Core.WorldMapKitLayer(); mapEngine.StaticLayers.Add(worldMapKitLayer); //LineShape for the street center line. LineShape lineShape = new LineShape(); lineShape.Vertices.Add(new Vertex(-97.7441,30.3057)); lineShape.Vertices.Add(new Vertex(-97.7457 ,30.3064)); lineShape.Vertices.Add(new Vertex(-97.7464 ,30.3067)); lineShape.Vertices.Add(new Vertex(-97.7475 ,30.3071)); lineShape.Vertices.Add(new Vertex(-97.7481 ,30.3073)); lineShape.Vertices.Add(new Vertex(-97.7487 ,30.3073)); lineShape.Vertices.Add(new Vertex(-97.7491 ,30.3073)); lineShape.Vertices.Add(new Vertex(-97.7495 ,30.3072)); lineShape.Vertices.Add(new Vertex(-97.7497 ,30.3068)); lineShape.Vertices.Add(new Vertex(-97.7499 ,30.3065)); lineShape.Vertices.Add(new Vertex(-97.7495 ,30.3061)); lineShape.Vertices.Add(new Vertex(-97.7492 ,30.3058)); lineShape.Vertices.Add(new Vertex(-97.7493 ,30.3056)); lineShape.Vertices.Add(new Vertex(-97.7493 ,30.3053)); lineShape.Vertices.Add(new Vertex(-97.7493 ,30.305)); lineShape.Vertices.Add(new Vertex(-97.7488 ,30.3048)); lineShape.Vertices.Add(new Vertex(-97.7486 ,30.3046)); lineShape.Vertices.Add(new Vertex(-97.7473 ,30.304)); lineShape.Vertices.Add(new Vertex(-97.7469 ,30.3037)); lineShape.Vertices.Add(new Vertex(-97.7471 ,30.3034)); //Buffers the street center line to get a polygon representing the street. MultipolygonShape bufferMultiPolygonShape = lineShape.Buffer(10, GeographyUnit.DecimalDegree, DistanceUnit.Meter); PolygonShape polygonShape = new PolygonShape(bufferMultiPolygonShape.Polygons[0].OuterRing); //Gets the two points on the center line. PointShape pointShape1 = lineShape.GetPointOnALine(StartingPoint.FirstPoint, 200, GeographyUnit.DecimalDegree, DistanceUnit.Meter); PointShape pointShape2 = lineShape.GetPointOnALine(StartingPoint.FirstPoint, 850, GeographyUnit.DecimalDegree, DistanceUnit.Meter); Collection interceptedPointShapes = new Collection(); interceptedPointShapes.Add(pointShape1); interceptedPointShapes.Add(pointShape2); //Gets the lines perpenticular to the center line. Collection perpendicularLines = Splitter.GetPerpendicularLines(lineShape, interceptedPointShapes, 0.0005); //Splits the street polygon. PolygonShape splitPolygonShape = Splitter.SplitPolygonWithTwoLines(polygonShape, perpendicularLines[1], perpendicularLines[0]); //InMemoryFeatureLayers for displaying the center line, the points on line, the perpenticular lines, the street polygon //and the split street polygon. InMemoryFeatureLayer centerLineInMemoryFeatureLayer = new InMemoryFeatureLayer(); centerLineInMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.StandardColors.Red, 2, true); centerLineInMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; centerLineInMemoryFeatureLayer.InternalFeatures.Add(new Feature(lineShape)); mapEngine.DynamicLayers.Add("CenterLineLayer", centerLineInMemoryFeatureLayer); InMemoryFeatureLayer inMemoryFeatureLayer = new InMemoryFeatureLayer(); inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(80, GeoColor.StandardColors.Red), GeoColor.StandardColors.Black); inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.CreateSimpleCircleStyle(GeoColor.StandardColors.Green, 10); inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.StandardColors.DarkCyan, 2, true); inMemoryFeatureLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; inMemoryFeatureLayer.InternalFeatures.Add("Area", new Feature(polygonShape)); inMemoryFeatureLayer.InternalFeatures.Add("Point1", new Feature(pointShape1)); inMemoryFeatureLayer.InternalFeatures.Add("Point2", new Feature(pointShape2)); foreach (LineShape perpendicularLineShape in perpendicularLines) { inMemoryFeatureLayer.InternalFeatures.Add(new Feature(perpendicularLineShape)); } mapEngine.DynamicLayers.Add("AreaLayer", inMemoryFeatureLayer); InMemoryFeatureLayer inMemoryFeatureLayer2 = new InMemoryFeatureLayer(); inMemoryFeatureLayer2.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.FromArgb(150, GeoColor.StandardColors.Yellow), GeoColor.StandardColors.Black); inMemoryFeatureLayer2.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; inMemoryFeatureLayer2.InternalFeatures.Add("Result", new Feature(splitPolygonShape)); //ellipseShape1)); //polygonShape)); mapEngine.DynamicLayers.Add("ResultLayer", inMemoryFeatureLayer2); DrawImage(); } private void DrawImage() { if (bitmap != null) { bitmap.Dispose(); } bitmap = new Bitmap(Map.Width, Map.Height); mapEngine.OpenAllLayers(); mapEngine.DrawStaticLayers(bitmap, GeographyUnit.DecimalDegree); mapEngine.DrawDynamicLayers(bitmap, GeographyUnit.DecimalDegree); mapEngine.CloseAllLayers(); Map.Image = bitmap; } private void ToolBar_ButtonClick(object sender, ToolBarButtonClickEventArgs e) { switch (e.Button.Tag.ToString()) { case "Zoom In": mapEngine.CurrentExtent.ScaleDown(50); break; case "Zoom Out": mapEngine.CurrentExtent.ScaleUp(50); break; case "Full Extent": mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(new RectangleShape(-180.0, 83.0, 180.0, -90.0), Map.Width, Map.Height); break; case "Pan Left": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Left, 20); break; case "Pan Right": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Right, 20); break; case "Pan Up": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Up, 20); break; case "Pan Down": mapEngine.CurrentExtent = ExtentHelper.Pan(mapEngine.CurrentExtent, PanDirection.Down, 20); break; default: break; } DrawImage(); } private void btnClose_Click(object sender, EventArgs e) { this.Close(); } private void Map_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(mapEngine.CurrentExtent, new ScreenPointF(e.X, e.Y), Map.Width, Map.Height); //Displays world coordinates. statusStrip1.Items["toolStripStatusLabelWorld"].Text = "(world) X:" + Math.Round(pointShape.X, 4) + " Y:" + Math.Round(pointShape.Y, 4); } private void Map_MouseUp(object sender, MouseEventArgs e) { //Gets the PointShape in world coordinates from screen coordinates. PointShape pointShape = ExtentHelper.ToWorldCoordinate(mapEngine.CurrentExtent, new ScreenPointF(e.X, e.Y), Map.Width, Map.Height); //Displays world coordinates. System.Diagnostics.Debug.WriteLine(" X:" + Math.Round(pointShape.X, 4) + " Y:" + Math.Round(pointShape.Y, 4)); } } }