예제 #1
0
        void bg_DoWork(object sender, DoWorkEventArgs e)
        {
            MapInfo info = (MapInfo)e.Argument;

            if (!info.Area.IsEmpty)
            {
                string bigImage = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + Path.DirectorySeparatorChar + "GMap at zoom " + info.Zoom + " - " + info.Type + "-" + DateTime.Now.Ticks + ".png";
                if (!string.IsNullOrEmpty(textBoxSaveAs.Text))
                {
                    bigImage = Path.Combine(Path.GetDirectoryName(textBoxSaveAs.Text), Path.GetFileName(bigImage));
                }

                var smallImage = Path.Combine(Path.GetDirectoryName(bigImage), "layer.png");
                if (!string.IsNullOrEmpty(textBoxSaveAs.Text))
                {
                    smallImage = textBoxSaveAs.Text;
                }

                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 shrinkLoop = 0;

                int padding = info.MakeWorldFile || info.MakeKmz ? 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;
                                        GMapImage tile;

                                        // tile number inversion(BottomLeft -> TopLeft) for pergo maps
                                        if (tp.InvertedAxisY)
                                        {
                                            tile = GMaps.Instance.GetImageFrom(tp, new GPoint(p.X, maxOfTiles.Height - p.Y), info.Zoom, out ex) as GMapImage;
                                        }
                                        else // ok
                                        {
                                            tile = GMaps.Instance.GetImageFrom(tp, p, info.Zoom, out ex) as GMapImage;
                                        }

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

                                        gfx.ResetTransform();
                                        gfx.TranslateTransform(-r.LocalPosition.X, -r.LocalPosition.Y);
                                        gfx.TranslateTransform((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))
                                        {
                                            var    pr = m.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(m.Offset.X, m.Offset.Y);

                                            gfx.ResetTransform();
                                            gfx.TranslateTransform(-m.LocalPosition.X, -m.LocalPosition.Y);
                                            gfx.TranslateTransform((int)px.X, (int)px.Y);

                                            m.ToolTip.OnRender(gfx);
                                        }
                                    }
                                }
                                gfx.ResetTransform();
                            }

                            // draw info
                            if (!info.MakeWorldFile)
                            {
                                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);
                                    }
                                }
                            }
                        }

                        ImageUtilities.SavePng(bigImage, bmpDestination);

                        Image shrinkImage = null;
                        try
                        {
                            shrinkImage = bmpDestination;

                            long size;
                            if (long.TryParse(textBoxSizeFile.Text, out size))
                            {
                                var fileLength = new FileInfo(bigImage).Length;
                                if (fileLength > 0 && (fileLength / 1024 / 1024) > size)
                                {
                                    while (shrinkLoop <= 100)
                                    {
                                        shrinkLoop++;

                                        int nextWidth  = shrinkImage.Width * 80 / 100;
                                        int nextHeight = shrinkImage.Height * 80 / 100;

                                        // Shrink image
                                        shrinkImage = Stuff.FixedSize(shrinkImage, nextWidth, nextHeight);
                                        ImageUtilities.SavePng(smallImage, shrinkImage);

                                        fileLength = new FileInfo(smallImage).Length;
                                        if (fileLength > 0 && (fileLength / 1024 / 1024) < size)
                                        {
                                            break;
                                        }
                                    }
                                }
                                else
                                {
                                    ImageUtilities.SavePng(smallImage, shrinkImage);
                                }
                            }
                            else
                            {
                                MessageBox.Show("Invalide size - no shrinking.", "GMap.NET - Demo.WindowsForms", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                            }
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.ToString(), "GMap.NET - Demo.WindowsForms", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        }
                        finally
                        {
                            shrinkImage.Dispose();
                        }
                    }
                }

                //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 = Path.ChangeExtension(bigImage, "pgw");
                    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();
                    }

                    wf = Path.ChangeExtension(smallImage, "pgw");
                    using (StreamWriter world = File.CreateText(wf))
                    {
                        world.WriteLine("{0:0.000000000000}", (info.Area.WidthLng / pxDelta.X) * (shrinkLoop > 0 ? Math.Pow(1.25, shrinkLoop) : 1));
                        world.WriteLine("0.0000000");
                        world.WriteLine("0.0000000");
                        world.WriteLine("{0:0.000000000000}", (-info.Area.HeightLat / pxDelta.Y) * (shrinkLoop > 0 ? Math.Pow(1.25, shrinkLoop) : 1));
                        world.WriteLine("{0:0.000000000000}", info.Area.Left);
                        world.WriteLine("{0:0.000000000000}", info.Area.Top);
                        world.Close();
                    }
                }

                if (info.MakeKmz)
                {
                    var kmzFile = Path.GetDirectoryName(bigImage) + Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(bigImage) + ".kmz";
                    e.Result = kmzFile;

                    using (ZipStorer zip = ZipStorer.Create(kmzFile, "GMap.NET"))
                    {
                        zip.AddFile(ZipStorer.Compression.Store, bigImage, "files/map.jpg", "map");

                        using (var readme = new MemoryStream(
                                   Encoding.UTF8.GetBytes(
                                       string.Format(CultureInfo.InvariantCulture, @"<?xml version=""1.0"" encoding=""UTF-8""?> 
<kml xmlns=""http://www.opengis.net/kml/2.2"" xmlns:gx=""http://www.google.com/kml/ext/2.2"" xmlns:kml=""http://www.opengis.net/kml/2.2"" xmlns:atom=""http://www.w3.org/2005/Atom"">
<GroundOverlay>
	<name>{8}</name>
	<LookAt>
		<longitude>{6}</longitude>
		<latitude>{7}</latitude>
		<altitude>0</altitude>
		<heading>0</heading>
		<tilt>0</tilt>
		<range>69327.55500845652</range>
	</LookAt>
	<color>91ffffff</color>
	<Icon>
		<href>files/map.jpg</href>
	</Icon>
	<gx:LatLonQuad>
		<coordinates>
			{0},{1},0 {2},{3},0 {4},{5},0 {6},{7},0 
		</coordinates>
	</gx:LatLonQuad>
</GroundOverlay>
</kml>", info.Area.Left, info.Area.Bottom,
                                                     info.Area.Right, info.Area.Bottom,
                                                     info.Area.Right, info.Area.Top,
                                                     info.Area.Left, info.Area.Top,
                                                     kmzFile))))
                        {
                            zip.AddStream(ZipStorer.Compression.Store, "doc.kml", readme, DateTime.Now, "kml");
                            zip.Close();
                        }
                    }
                }
            }
        }