diff --git a/DemoApp/FormMain.cs b/DemoApp/FormMain.cs index d53971c..b9a7809 100644 --- a/DemoApp/FormMain.cs +++ b/DemoApp/FormMain.cs @@ -137,7 +137,7 @@ private ICollection ReadPointsFromResource(string resourceName) private void UpdateWindowTitle() { GeoPoint g = mapControl.Mouse; - this.Text = $"Longitude = {DegreeToString(g.Longitude, "W", "E")} / Latitude = {DegreeToString(g.Latitude, "S", "N")} / Zoom = {mapControl.ZoomLevel}"; + this.Text = $"Mouse = {g} / Zoom = {mapControl.ZoomLevel} / Bounding Box = TL:{mapControl.TopLeft}, TR:{mapControl.TopRight}, BR:{mapControl.BottomRight}, BL:{mapControl.BottomLeft}"; } private void mapControl_MouseMove(object sender, MouseEventArgs e) @@ -184,26 +184,8 @@ private void mapControl_DoubleClick(object sender, EventArgs e) { var coord = mapControl.Mouse; StringBuilder sb = new StringBuilder(); - sb.AppendLine($"Latitude: {DegreeToString(coord.Latitude, "S", "N")}"); - sb.AppendLine($"Longitude: {DegreeToString(coord.Longitude, "W", "E")}"); + sb.AppendLine($"Location: {coord}"); MessageBox.Show(sb.ToString(), "Info"); } - - private string DegreeToString(double coordinate, string negativeSym, string positiveSym) - { - string sym = coordinate < 0d ? negativeSym : positiveSym; - coordinate = Math.Abs(coordinate); - double d = Math.Floor(coordinate); - coordinate -= d; - coordinate *= 60; - double m = Math.Floor(coordinate); - coordinate -= m; - coordinate *= 60; - double s = coordinate; - string dd = d.ToString(); - string mm = m.ToString().PadLeft(2, '0'); - string ss = s.ToString("00.00", CultureInfo.InvariantCulture); - return $"{dd}° {mm}' {ss}\" {sym}"; - } } } diff --git a/MapControl/GeoPoint.cs b/MapControl/GeoPoint.cs index 79fcbde..61e9d28 100644 --- a/MapControl/GeoPoint.cs +++ b/MapControl/GeoPoint.cs @@ -1,4 +1,6 @@ -namespace System.Windows.Forms +using System.Globalization; + +namespace System.Windows.Forms { /// /// Represents point on the Earth surface with geographical coordinates @@ -25,5 +27,28 @@ public GeoPoint(float longitude, float latitude) Longitude = longitude; Latitude = latitude; } + + /// + public override string ToString() + { + return $"{DegreeToString(Longitude, "W", "E")}, {DegreeToString(Latitude, "S", "N")}"; + } + + private static string DegreeToString(double coordinate, string negativeSym, string positiveSym) + { + string sym = coordinate < 0d ? negativeSym : positiveSym; + coordinate = Math.Abs(coordinate); + double d = Math.Floor(coordinate); + coordinate -= d; + coordinate *= 60; + double m = Math.Floor(coordinate); + coordinate -= m; + coordinate *= 60; + double s = coordinate; + string dd = d.ToString(); + string mm = m.ToString().PadLeft(2, '0'); + string ss = s.ToString("00.00", CultureInfo.InvariantCulture); + return $"{dd}° {mm}' {ss}\" {sym}"; + } } } diff --git a/MapControl/MapControl.cs b/MapControl/MapControl.cs index da63658..f61c51e 100644 --- a/MapControl/MapControl.cs +++ b/MapControl/MapControl.cs @@ -4,6 +4,7 @@ using System.Diagnostics; using System.Drawing; using System.Drawing.Drawing2D; +using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Threading; @@ -93,7 +94,8 @@ public int ZoomLevel if (value < 0 || value > 19) throw new ArgumentException($"{value} is an incorrect value for {nameof(ZoomLevel)} property. Value should be in range from 0 to 19."); - SetZoomLevel(value, new Point(Width / 2, Height / 2)); + SetZoomLevel(value, new Point(Width / 2, Height / 2)); + CenterChanged?.Invoke(this, EventArgs.Empty); } } @@ -205,7 +207,8 @@ public ITileServer TileServer ZoomLevel = TileServer.MinZoomLevel; } - Invalidate(); + Invalidate(); + TileServerChanged?.Invoke(this, EventArgs.Empty); } } @@ -218,8 +221,8 @@ public GeoPoint Center { get { - float x = NormalizeTileNumber(-(_Offset.X - Width / 2) / TILE_SIZE); - float y = -(_Offset.Y - Height / 2) / TILE_SIZE; + float x = NormalizeTileNumber(-(float)(_Offset.X - Width / 2) / TILE_SIZE); + float y = -(float)(_Offset.Y - Height / 2) / TILE_SIZE; return TileToWorldPos(x, y); } set @@ -228,11 +231,11 @@ public GeoPoint Center _Offset.X = -(int)(center.X * TILE_SIZE) + Width / 2; _Offset.Y = -(int)(center.Y * TILE_SIZE) + Height / 2; _Offset.X = (int)(_Offset.X % FullMapSizeInPixels); - Invalidate(); + Invalidate(); + CenterChanged?.Invoke(this, EventArgs.Empty); } } - /// /// Gets geographical coordinates of the current position of mouse. /// @@ -248,6 +251,66 @@ public GeoPoint Mouse } } + /// + /// Gets geographical coordinates of the top left point of the map + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public GeoPoint TopLeft + { + get + { + float x = NormalizeTileNumber(-(float)(_Offset.X) / TILE_SIZE); + float y = -(float)(_Offset.Y) / TILE_SIZE; + return TileToWorldPos(x, y); + } + } + + /// + /// Gets geographical coordinates of the top right point of the map + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public GeoPoint TopRight + { + get + { + float x = NormalizeTileNumber(-(float)(_Offset.X - Width) / TILE_SIZE); + float y = -(float)(_Offset.Y) / TILE_SIZE; + return TileToWorldPos(x, y); + } + } + + /// + /// Gets geographical coordinates of the bottom left point of the map + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public GeoPoint BottomLeft + { + get + { + float x = NormalizeTileNumber(-(float)(_Offset.X) / TILE_SIZE); + float y = -(float)(_Offset.Y - Height) / TILE_SIZE; + return TileToWorldPos(x, y); + } + } + + /// + /// Gets geographical coordinates of the bottom right point of the map + /// + [Browsable(false)] + [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] + public GeoPoint BottomRight + { + get + { + float x = NormalizeTileNumber(-(float)(_Offset.X - Width) / TILE_SIZE); + float y = -(float)(_Offset.Y - Height) / TILE_SIZE; + return TileToWorldPos(x, y); + } + } + /// /// Gets collection of markers to be displayed on the map. /// @@ -332,6 +395,12 @@ public override Color ForeColor } } + /// + /// Image attributes to be applied to a tile image when drawing. + /// + [Description("Image attributes to be applied to a tile image when drawing."), Category("Appearance")] + public ImageAttributes TileImageAttributes { get; set; } = null; + /// /// Raised when marker is drawn on the map. /// @@ -346,6 +415,21 @@ public override Color ForeColor /// Raised when polygon is drawn on the map. /// public event EventHandler DrawPolygon; + + /// + /// Raised when property value is changed. + /// + public event EventHandler CenterChanged; + + /// + /// Raised when property value is changed. + /// + public event EventHandler MouseChanged; + + /// + /// Raised when property value is changed. + /// + public event EventHandler TileServerChanged; /// /// Creates new control. @@ -439,7 +523,8 @@ protected override void OnSizeChanged(EventArgs e) _LinkLabel.Top = Height - _LinkLabel.Height; AdjustMapBounds(); - Invalidate(); + Invalidate(); + CenterChanged?.Invoke(this, EventArgs.Empty); } /// @@ -487,12 +572,14 @@ protected override void OnMouseMove(MouseEventArgs e) _Offset.Y = Height; AdjustMapBounds(); - - Invalidate(); + Invalidate(); + CenterChanged?.Invoke(this, EventArgs.Empty); } _LastMouse.X = e.X; _LastMouse.Y = e.Y; + + MouseChanged?.Invoke(this, EventArgs.Empty); base.OnMouseMove(e); } @@ -513,8 +600,8 @@ protected override void OnMouseWheel(MouseEventArgs e) SetZoomLevel(z, new Point(e.X, e.Y)); AdjustMapBounds(); - - base.OnMouseWheel(e); + base.OnMouseWheel(e); + CenterChanged?.Invoke(this, EventArgs.Empty); } /// @@ -744,7 +831,6 @@ private void DrawPolygons(Graphics gr) using (GraphicsPath gp = new GraphicsPath()) { gp.StartFigure(); - for (int i = 0; i < polygon.Count; i++) { GeoPoint g = polygon.ElementAt(i); @@ -754,9 +840,12 @@ private void DrawPolygons(Graphics gr) p = p0.Nearest(p, new PointF(p.X - FullMapSizeInPixels, p.Y), new PointF(p.X + FullMapSizeInPixels, p.Y)); gp.AddLine(p0, p); } + p0 = p; } + gp.CloseFigure(); + var eventArgs = new DrawPolygonEventArgs() { Graphics = gr, @@ -812,8 +901,15 @@ private void DrawTilePart(Graphics gr, int x, int y, int xRemainder, int yRemain Rectangle srcRect = new Rectangle(TILE_SIZE / frac * xRemainder, TILE_SIZE / frac * yRemainder, TILE_SIZE / frac, TILE_SIZE / frac); // Destination rectangle - Rectangle destRect = new Rectangle(p.X, p.Y, TILE_SIZE, TILE_SIZE); - gr.DrawImage(image, destRect, srcRect, GraphicsUnit.Pixel); + Rectangle destRect = new Rectangle(p.X - frac, p.Y - frac, TILE_SIZE + 2 * frac, TILE_SIZE + 2 * frac); + + var state = gr.Save(); + gr.SmoothingMode = SmoothingMode.HighSpeed; + gr.InterpolationMode = InterpolationMode.NearestNeighbor; + gr.PixelOffsetMode = PixelOffsetMode.HighSpeed; + gr.CompositingQuality = CompositingQuality.HighSpeed; + gr.DrawImage(image, destRect, srcRect.X, srcRect.Y, srcRect.Width, srcRect.Height, GraphicsUnit.Pixel, TileImageAttributes); + gr.Restore(state); } /// @@ -828,7 +924,8 @@ private void DrawTile(Graphics gr, int x, int y, Image image) Point p = new Point(); p.X = _Offset.X + x * TILE_SIZE; p.Y = _Offset.Y + y * TILE_SIZE; - gr.DrawImageUnscaled(image, p); + + gr.DrawImage(image, new Rectangle(p, new Drawing.Size(TILE_SIZE, TILE_SIZE)), 0, 0, TILE_SIZE, TILE_SIZE, GraphicsUnit.Pixel, TileImageAttributes); } /// diff --git a/MapControl/MapControl.csproj b/MapControl/MapControl.csproj index cba0858..016c861 100644 --- a/MapControl/MapControl.csproj +++ b/MapControl/MapControl.csproj @@ -1,7 +1,7 @@  net451 - 1.0.1 + 1.0.2 System.Windows.Forms.MapControl Map control for WindowsForms © Alexander Krutov 2020 diff --git a/MapControl/System.Windows.Forms.MapControl.xml b/MapControl/System.Windows.Forms.MapControl.xml index 241298b..3d3bba3 100644 --- a/MapControl/System.Windows.Forms.MapControl.xml +++ b/MapControl/System.Windows.Forms.MapControl.xml @@ -96,6 +96,9 @@ Longitude of the point, in degrees, from 0 to ±180, positive East, negative West. 0 is a point on prime meridian. Latitude of the point, in degrees, from +90 (North pole) to -90 (South Pole). 0 is a point on equator. + + + Set of useful graphics extensions @@ -306,6 +309,26 @@ Gets geographical coordinates of the current position of mouse. + + + Gets geographical coordinates of the top left point of the map + + + + + Gets geographical coordinates of the top right point of the map + + + + + Gets geographical coordinates of the bottom left point of the map + + + + + Gets geographical coordinates of the bottom right point of the map + + Gets collection of markers to be displayed on the map. @@ -361,6 +384,11 @@ Gets or sets the foreground color of the map. + + + Image attributes to be applied to a tile image when drawing. + + Raised when marker is drawn on the map. @@ -376,6 +404,21 @@ Raised when polygon is drawn on the map. + + + Raised when property value is changed. + + + + + Raised when property value is changed. + + + + + Raised when property value is changed. + + Creates new control.