====== 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));
}
}
}