ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
ThinkGeo Cloud
ThinkGeo UI Controls
ThinkGeo Open Source
Help and Support
External Resources
using System; using System.Collections.Generic; using System.Linq; using System.Text; using ThinkGeo.MapSuite.Core; namespace GreatCircleOnPacificRim { //This class, inheriting from Projection, applies the very simple projection of offsetting all the points //360 degrees to the left. class OffsetProjection: Projection, IDisposable { protected override Vertex[] ConvertToExternalProjectionCore(double[] x, double[] y) { Vertex[] vertices = new Vertex[x.Length]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = new Vertex(x[i] - 360, y[i]); } return vertices; } protected override Vertex[] ConvertToInternalProjectionCore(double[] x, double[] y) { Vertex[] vertices = new Vertex[x.Length]; for (int i = 0; i < vertices.Length; i++) { vertices[i] = new Vertex(x[i] + 360, y[i]); } return vertices; } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { Close(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; namespace GreatCircleOnPacificRim { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new TestForm()); } } }
using System; using System.Collections.ObjectModel; using System.Drawing; using System.Windows.Forms; using ThinkGeo.MapSuite.Core; namespace GreatCircleOnPacificRim { 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) { mapEngine.BackgroundFillBrush = new GeoSolidBrush(GeoColor.GeographicColors.ShallowOcean); //We are loading the same ShapeFile twice: Once unprojected and a second time projecting //all the features 360 degrees to the left. ShapeFileFeatureLayer worldLayer = new ShapeFileFeatureLayer(@"..\..\Data\countries02.shp"); worldLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1; worldLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.StaticLayers.Add("WorldLayer", worldLayer); OffsetProjection offsetProj = new OffsetProjection(); //Loads the country layer with the Projection offsetting all the features 360 degrees to the left. ShapeFileFeatureLayer worldLayerOffset = new ShapeFileFeatureLayer(@"..\..\Data\countries02.shp", @"..\..\Data\countries_offset.idx"); worldLayerOffset.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1; worldLayerOffset.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; worldLayerOffset.FeatureSource.Projection = offsetProj; mapEngine.StaticLayers.Add("World Offset", worldLayerOffset); //InMemoryFeatureLayer for the cities. InMemoryFeatureLayer cityPoints = new InMemoryFeatureLayer(); cityPoints.Open(); cityPoints.Columns.Add(new FeatureSourceColumn("LabelName")); cityPoints.Close(); cityPoints.ZoomLevelSet.ZoomLevel01.DefaultPointStyle = PointStyles.City1; cityPoints.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = new TextStyle("LabelName", new GeoFont("Arial", 10), new GeoSolidBrush(GeoColor.SimpleColors.Black)); cityPoints.ZoomLevelSet.ZoomLevel01.DefaultTextStyle.XOffsetInPixel = 15; cityPoints.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.DynamicLayers.Add("City Points", cityPoints); //Display the feature for Los Angeles as is (without projection) because it is on the unprojected layer. PointShape LA_Point = new PointShape(-118.55, 34.08); Feature LA_feature = new Feature(LA_Point); LA_feature.ColumnValues.Add("LabelName", "Los Angeles"); cityPoints.InternalFeatures.Add("LA", LA_feature); //Apply the projection to the feature representing Shanghai because it on the projected layer. offsetProj.Open(); PointShape Shanghai_Point = new PointShape(offsetProj.ConvertToExternalProjection(121.78, 31.01)); offsetProj.Close(); Feature Shanghai_feature = new Feature(Shanghai_Point); Shanghai_feature.ColumnValues.Add("LabelName", "Shanghai"); cityPoints.InternalFeatures.Add("Shanghai", Shanghai_feature); //InMemoryFeatureLayer for the Great Circle. InMemoryFeatureLayer GreatCircle = new InMemoryFeatureLayer(); GreatCircle.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.CreateSimpleLineStyle(GeoColor.SimpleColors.Red, 3, true); GreatCircle.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; mapEngine.DynamicLayers.Add("Great Circle", GreatCircle); //The great circle requires to have the part being in the eastern hemisphere to be offset 360 to the left // so that it display on the projected layer. MultilineShape greatCircleMultiLineShape = GetGreatCircle(LA_Point, Shanghai_Point, offsetProj); Feature GreatCirclefeature = new Feature(greatCircleMultiLineShape); GreatCircle.InternalFeatures.Add("Great Circle", GreatCirclefeature); //Notice that the upper left of the current extent has to be expressed in the projected values to have the map //centered on the Pacific. RectangleShape extentRectangleShape = new RectangleShape(new PointShape(offsetProj.ConvertToExternalProjection(80, 58)), new PointShape(-70, -20)); mapEngine.CurrentExtent = ExtentHelper.GetDrawingExtent(extentRectangleShape, Map.Width, Map.Height); DrawImage(); } private MultilineShape GetGreatCircle(PointShape pointShape1, PointShape pointShape2, OffsetProjection offsetProj) { offsetProj.Open(); if (pointShape1.X < -180) { pointShape1 = new PointShape(offsetProj.ConvertToInternalProjection(pointShape1.X, pointShape1.Y)); } if (pointShape2.X < -180) { pointShape2 = new PointShape(offsetProj.ConvertToInternalProjection(pointShape2.X, pointShape2.Y)); } MultilineShape greatCircleMultiLineShape = pointShape1.GetShortestLineTo(pointShape2, GeographyUnit.DecimalDegree); MultilineShape resultGreatMultiLineShape = new MultilineShape(); foreach (LineShape lineShape in greatCircleMultiLineShape.Lines) { if (lineShape.Vertices[0].X < 0) { resultGreatMultiLineShape.Lines.Add(lineShape); } else { LineShape resultLineShape = new LineShape(); foreach (Vertex vertex in lineShape.Vertices) { Vertex projVertex = offsetProj.ConvertToExternalProjection(vertex.X, vertex.Y); resultLineShape.Vertices.Add(projVertex); } resultGreatMultiLineShape.Lines.Add(resultLineShape); } } return resultGreatMultiLineShape; } 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); } } }