using System; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.IO; using System.Windows.Forms; using GMap.NET; using GMap.NET.WindowsForms; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using GMap.NET.MapProviders; namespace Demo.WindowsForms { public partial class StaticImage : Form { MainForm Main; BackgroundWorker bg = new BackgroundWorker(); readonly List tileArea = new List(); public StaticImage(MainForm main) { InitializeComponent(); Main = main; numericUpDown1.Maximum = Main.MainMap.MaxZoom; numericUpDown1.Minimum = Main.MainMap.MinZoom; numericUpDown1.Value = new decimal(Main.MainMap.Zoom); bg.WorkerReportsProgress = true; bg.WorkerSupportsCancellation = true; bg.DoWork += new DoWorkEventHandler(bg_DoWork); bg.ProgressChanged += new ProgressChangedEventHandler(bg_ProgressChanged); bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted); } void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if(!e.Cancelled) { if(e.Error != null) { MessageBox.Show("Error:" + e.Error.ToString(), "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Error); } else if(e.Result != null) { try { Process.Start(e.Result as string); } catch { } } } this.Text = "Static Map maker"; progressBar1.Value = 0; button1.Enabled = true; numericUpDown1.Enabled = true; } void bg_ProgressChanged(object sender, ProgressChangedEventArgs e) { progressBar1.Value = e.ProgressPercentage; GPoint p = (GPoint)e.UserState; this.Text = "Static Map maker: Downloading[" + p + "]: " + tileArea.IndexOf(p) + " of " + tileArea.Count; } void bg_DoWork(object sender, DoWorkEventArgs e) { MapInfo info = (MapInfo)e.Argument; if(!info.Area.IsEmpty) { //var types = GMaps.Instance.GetAllLayersOfType(info.Type); string bigImage = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + Path.DirectorySeparatorChar + "GMap at zoom " + info.Zoom + " - " + info.Type + "-" + DateTime.Now.Ticks + ".png"; e.Result = bigImage; // current area GPoint topLeftPx = info.Type.Projection.FromLatLngToPixel(info.Area.LocationTopLeft, info.Zoom); GPoint rightButtomPx = info.Type.Projection.FromLatLngToPixel(info.Area.Bottom, info.Area.Right, info.Zoom); GPoint pxDelta = new GPoint(rightButtomPx.X - topLeftPx.X, rightButtomPx.Y - topLeftPx.Y); GMap.NET.GSize maxOfTiles = info.Type.Projection.GetTileMatrixMaxXY(info.Zoom); int padding = info.MakeWorldFile ? 0 : 22; { using(Bitmap bmpDestination = new Bitmap((int)(pxDelta.X + padding * 2), (int)(pxDelta.Y + padding * 2))) { using(Graphics gfx = Graphics.FromImage(bmpDestination)) { gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; gfx.SmoothingMode = SmoothingMode.HighQuality; int i = 0; // get tiles & combine into one lock(tileArea) { foreach(var p in tileArea) { if(bg.CancellationPending) { e.Cancel = true; return; } int pc = (int)(((double)++i / tileArea.Count) * 100); bg.ReportProgress(pc, p); foreach(var tp in info.Type.Overlays) { Exception ex; WindowsFormsImage tile; // tile number inversion(BottomLeft -> TopLeft) for pergo maps //if(tp == MapType.PergoTurkeyMap) //{ // tile = GMaps.Instance.GetImageFrom(tp, new GPoint(p.X, maxOfTiles.Height - p.Y), info.Zoom, out ex) as WindowsFormsImage; //} //else // ok { tile = GMaps.Instance.GetImageFrom(tp, p, info.Zoom, out ex) as WindowsFormsImage; } if(tile != null) { using(tile) { long x = p.X * info.Type.Projection.TileSize.Width - topLeftPx.X + padding; long y = p.Y * info.Type.Projection.TileSize.Width - topLeftPx.Y + padding; { gfx.DrawImage(tile.Img, x, y, info.Type.Projection.TileSize.Width, info.Type.Projection.TileSize.Height); } } } } } } // draw routes { foreach(GMapRoute r in Main.routes.Routes) { if(r.IsVisible) { using(GraphicsPath rp = new GraphicsPath()) { for(int j = 0; j < r.Points.Count; j++) { var pr = r.Points[j]; GPoint px = info.Type.Projection.FromLatLngToPixel(pr.Lat, pr.Lng, info.Zoom); px.Offset(padding, padding); px.Offset(-topLeftPx.X, -topLeftPx.Y); GPoint p2 = px; if(j == 0) { rp.AddLine(p2.X, p2.Y, p2.X, p2.Y); } else { System.Drawing.PointF p = rp.GetLastPoint(); rp.AddLine(p.X, p.Y, p2.X, p2.Y); } } if(rp.PointCount > 0) { gfx.DrawPath(r.Stroke, rp); } } } } } // draw polygons //{ // foreach(GMapPolygon r in Main.polygons.Polygons) // { // if(r.IsVisible) // { // using(GraphicsPath rp = new GraphicsPath()) // { // for(int j = 0; j < r.Points.Count; j++) // { // var pr = r.Points[j]; // GPoint px = info.Type.Projection.FromLatLngToPixel(pr.Lat, pr.Lng, info.Zoom); // px.Offset(padding, padding); // px.Offset(-topLeftPx.X, -topLeftPx.Y); // GPoint p2 = px; // if(j == 0) // { // rp.AddLine(p2.X, p2.Y, p2.X, p2.Y); // } // else // { // System.Drawing.PointF p = rp.GetLastPoint(); // rp.AddLine(p.X, p.Y, p2.X, p2.Y); // } // } // if(rp.PointCount > 0) // { // rp.CloseFigure(); // gfx.FillPath(r.Fill, rp); // gfx.DrawPath(r.Stroke, rp); // } // } // } // } //} // draw markers { foreach(GMapMarker r in Main.objects.Markers) { if(r.IsVisible) { var pr = r.Position; GPoint px = info.Type.Projection.FromLatLngToPixel(pr.Lat, pr.Lng, info.Zoom); px.Offset(padding, padding); px.Offset(-topLeftPx.X, -topLeftPx.Y); px.Offset(r.Offset.X, r.Offset.Y); r.LocalPosition = new System.Drawing.Point((int)px.X, (int)px.Y); r.OnRender(gfx); } } // tooltips above foreach(GMapMarker m in Main.objects.Markers) { if(m.IsVisible && m.ToolTip != null && m.IsVisible) { if(!string.IsNullOrEmpty(m.ToolTipText)) { m.ToolTip.OnRender(gfx); } } } } // draw info { System.Drawing.Rectangle rect = new System.Drawing.Rectangle(); { rect.Location = new System.Drawing.Point(padding, padding); rect.Size = new System.Drawing.Size((int)pxDelta.X, (int)pxDelta.Y); } using(Font f = new Font(FontFamily.GenericSansSerif, 9, FontStyle.Bold)) { // draw bounds & coordinates using(Pen p = new Pen(Brushes.DimGray, 3)) { p.DashStyle = System.Drawing.Drawing2D.DashStyle.DashDot; gfx.DrawRectangle(p, rect); string topleft = info.Area.LocationTopLeft.ToString(); SizeF s = gfx.MeasureString(topleft, f); gfx.DrawString(topleft, f, p.Brush, rect.X + s.Height / 2, rect.Y + s.Height / 2); string rightBottom = new PointLatLng(info.Area.Bottom, info.Area.Right).ToString(); SizeF s2 = gfx.MeasureString(rightBottom, f); gfx.DrawString(rightBottom, f, p.Brush, rect.Right - s2.Width - s2.Height / 2, rect.Bottom - s2.Height - s2.Height / 2); } // draw scale using(Pen p = new Pen(Brushes.Blue, 1)) { double rez = info.Type.Projection.GetGroundResolution(info.Zoom, info.Area.Bottom); int px100 = (int)(100.0 / rez); // 100 meters int px1000 = (int)(1000.0 / rez); // 1km gfx.DrawRectangle(p, rect.X + 10, rect.Bottom - 20, px1000, 10); gfx.DrawRectangle(p, rect.X + 10, rect.Bottom - 20, px100, 10); string leftBottom = "scale: 100m | 1Km"; SizeF s = gfx.MeasureString(leftBottom, f); gfx.DrawString(leftBottom, f, p.Brush, rect.X + 10, rect.Bottom - s.Height - 20); } } } } bmpDestination.Save(bigImage, ImageFormat.Png); } } //The worldfile for the original image is: //0.000067897543 // the horizontal size of a pixel in coordinate units (longitude degrees in this case); //0.0000000 //0.0000000 //-0.0000554613012 // the comparable vertical pixel size in latitude degrees, negative because latitude decreases as you go from top to bottom in the image. //-111.743323868834 // longitude of the pixel in the upper-left-hand corner. //35.1254392635083 // latitude of the pixel in the upper-left-hand corner. // generate world file if(info.MakeWorldFile) { string wf = bigImage + "w"; using(StreamWriter world = File.CreateText(wf)) { world.WriteLine("{0:0.000000000000}", (info.Area.WidthLng / pxDelta.X)); world.WriteLine("0.0000000"); world.WriteLine("0.0000000"); world.WriteLine("{0:0.000000000000}", (-info.Area.HeightLat / pxDelta.Y)); world.WriteLine("{0:0.000000000000}", info.Area.Left); world.WriteLine("{0:0.000000000000}", info.Area.Top); world.Close(); } } } } readonly List GpxRoute = new List(); RectLatLng AreaGpx = RectLatLng.Empty; private void button1_Click(object sender, EventArgs e) { RectLatLng? area = null; if(checkBoxRoutes.Checked) { area = Main.MainMap.GetRectOfAllRoutes(null); if(!area.HasValue) { MessageBox.Show("No routes in map", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } } else { area = Main.MainMap.SelectedArea; if(area.Value.IsEmpty) { MessageBox.Show("Select map area holding ALT", "GMap.NET", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } } if(!bg.IsBusy) { lock(tileArea) { tileArea.Clear(); tileArea.AddRange(Main.MainMap.MapProvider.Projection.GetAreaTileList(area.Value, (int)numericUpDown1.Value, 1)); tileArea.TrimExcess(); } numericUpDown1.Enabled = false; progressBar1.Value = 0; button1.Enabled = false; bg.RunWorkerAsync(new MapInfo(area.Value, (int)numericUpDown1.Value, Main.MainMap.MapProvider, checkBoxWorldFile.Checked)); } } private void button2_Click(object sender, EventArgs e) { if(bg.IsBusy) { bg.CancelAsync(); } } } public struct MapInfo { public RectLatLng Area; public int Zoom; public GMapProvider Type; public bool MakeWorldFile; public MapInfo(RectLatLng Area, int Zoom, GMapProvider Type, bool makeWorldFile) { this.Area = Area; this.Zoom = Zoom; this.Type = Type; this.MakeWorldFile = makeWorldFile; } } }