44using System . Diagnostics ;
55using System . Drawing ;
66using System . Drawing . Drawing2D ;
7+ using System . Drawing . Imaging ;
78using System . IO ;
89using System . Linq ;
910using System . Threading ;
@@ -93,7 +94,8 @@ public int ZoomLevel
9394 if ( value < 0 || value > 19 )
9495 throw new ArgumentException ( $ "{ value } is an incorrect value for { nameof ( ZoomLevel ) } property. Value should be in range from 0 to 19.") ;
9596
96- SetZoomLevel ( value , new Point ( Width / 2 , Height / 2 ) ) ;
97+ SetZoomLevel ( value , new Point ( Width / 2 , Height / 2 ) ) ;
98+ CenterChanged ? . Invoke ( this , EventArgs . Empty ) ;
9799 }
98100 }
99101
@@ -205,7 +207,8 @@ public ITileServer TileServer
205207 ZoomLevel = TileServer . MinZoomLevel ;
206208 }
207209
208- Invalidate ( ) ;
210+ Invalidate ( ) ;
211+ TileServerChanged ? . Invoke ( this , EventArgs . Empty ) ;
209212 }
210213 }
211214
@@ -218,8 +221,8 @@ public GeoPoint Center
218221 {
219222 get
220223 {
221- float x = NormalizeTileNumber ( - ( _Offset . X - Width / 2 ) / TILE_SIZE ) ;
222- float y = - ( _Offset . Y - Height / 2 ) / TILE_SIZE ;
224+ float x = NormalizeTileNumber ( - ( float ) ( _Offset . X - Width / 2 ) / TILE_SIZE ) ;
225+ float y = - ( float ) ( _Offset . Y - Height / 2 ) / TILE_SIZE ;
223226 return TileToWorldPos ( x , y ) ;
224227 }
225228 set
@@ -228,11 +231,11 @@ public GeoPoint Center
228231 _Offset . X = - ( int ) ( center . X * TILE_SIZE ) + Width / 2 ;
229232 _Offset . Y = - ( int ) ( center . Y * TILE_SIZE ) + Height / 2 ;
230233 _Offset . X = ( int ) ( _Offset . X % FullMapSizeInPixels ) ;
231- Invalidate ( ) ;
234+ Invalidate ( ) ;
235+ CenterChanged ? . Invoke ( this , EventArgs . Empty ) ;
232236 }
233237 }
234238
235-
236239 /// <summary>
237240 /// Gets geographical coordinates of the current position of mouse.
238241 /// </summary>
@@ -248,6 +251,66 @@ public GeoPoint Mouse
248251 }
249252 }
250253
254+ /// <summary>
255+ /// Gets geographical coordinates of the top left point of the map
256+ /// </summary>
257+ [ Browsable ( false ) ]
258+ [ DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden ) ]
259+ public GeoPoint TopLeft
260+ {
261+ get
262+ {
263+ float x = NormalizeTileNumber ( - ( float ) ( _Offset . X ) / TILE_SIZE ) ;
264+ float y = - ( float ) ( _Offset . Y ) / TILE_SIZE ;
265+ return TileToWorldPos ( x , y ) ;
266+ }
267+ }
268+
269+ /// <summary>
270+ /// Gets geographical coordinates of the top right point of the map
271+ /// </summary>
272+ [ Browsable ( false ) ]
273+ [ DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden ) ]
274+ public GeoPoint TopRight
275+ {
276+ get
277+ {
278+ float x = NormalizeTileNumber ( - ( float ) ( _Offset . X - Width ) / TILE_SIZE ) ;
279+ float y = - ( float ) ( _Offset . Y ) / TILE_SIZE ;
280+ return TileToWorldPos ( x , y ) ;
281+ }
282+ }
283+
284+ /// <summary>
285+ /// Gets geographical coordinates of the bottom left point of the map
286+ /// </summary>
287+ [ Browsable ( false ) ]
288+ [ DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden ) ]
289+ public GeoPoint BottomLeft
290+ {
291+ get
292+ {
293+ float x = NormalizeTileNumber ( - ( float ) ( _Offset . X ) / TILE_SIZE ) ;
294+ float y = - ( float ) ( _Offset . Y - Height ) / TILE_SIZE ;
295+ return TileToWorldPos ( x , y ) ;
296+ }
297+ }
298+
299+ /// <summary>
300+ /// Gets geographical coordinates of the bottom right point of the map
301+ /// </summary>
302+ [ Browsable ( false ) ]
303+ [ DesignerSerializationVisibility ( DesignerSerializationVisibility . Hidden ) ]
304+ public GeoPoint BottomRight
305+ {
306+ get
307+ {
308+ float x = NormalizeTileNumber ( - ( float ) ( _Offset . X - Width ) / TILE_SIZE ) ;
309+ float y = - ( float ) ( _Offset . Y - Height ) / TILE_SIZE ;
310+ return TileToWorldPos ( x , y ) ;
311+ }
312+ }
313+
251314 /// <summary>
252315 /// Gets collection of markers to be displayed on the map.
253316 /// </summary>
@@ -332,6 +395,12 @@ public override Color ForeColor
332395 }
333396 }
334397
398+ /// <summary>
399+ /// Image attributes to be applied to a tile image when drawing.
400+ /// </summary>
401+ [ Description ( "Image attributes to be applied to a tile image when drawing." ) , Category ( "Appearance" ) ]
402+ public ImageAttributes TileImageAttributes { get ; set ; } = null ;
403+
335404 /// <summary>
336405 /// Raised when marker is drawn on the map.
337406 /// </summary>
@@ -346,6 +415,21 @@ public override Color ForeColor
346415 /// Raised when polygon is drawn on the map.
347416 /// </summary>
348417 public event EventHandler < DrawPolygonEventArgs > DrawPolygon ;
418+
419+ /// <summary>
420+ /// Raised when <see cref="Center"/> property value is changed.
421+ /// </summary>
422+ public event EventHandler < EventArgs > CenterChanged ;
423+
424+ /// <summary>
425+ /// Raised when <see cref="Mouse"/> property value is changed.
426+ /// </summary>
427+ public event EventHandler < EventArgs > MouseChanged ;
428+
429+ /// <summary>
430+ /// Raised when <see cref="TileServer"/> property value is changed.
431+ /// </summary>
432+ public event EventHandler < EventArgs > TileServerChanged ;
349433
350434 /// <summary>
351435 /// Creates new <see cref="MapControl"/> control.
@@ -439,7 +523,8 @@ protected override void OnSizeChanged(EventArgs e)
439523 _LinkLabel . Top = Height - _LinkLabel . Height ;
440524
441525 AdjustMapBounds ( ) ;
442- Invalidate ( ) ;
526+ Invalidate ( ) ;
527+ CenterChanged ? . Invoke ( this , EventArgs . Empty ) ;
443528 }
444529
445530 /// <summary>
@@ -487,12 +572,14 @@ protected override void OnMouseMove(MouseEventArgs e)
487572 _Offset . Y = Height ;
488573
489574 AdjustMapBounds ( ) ;
490-
491- Invalidate ( ) ;
575+ Invalidate ( ) ;
576+ CenterChanged ? . Invoke ( this , EventArgs . Empty ) ;
492577 }
493578
494579 _LastMouse . X = e . X ;
495580 _LastMouse . Y = e . Y ;
581+
582+ MouseChanged ? . Invoke ( this , EventArgs . Empty ) ;
496583
497584 base . OnMouseMove ( e ) ;
498585 }
@@ -513,8 +600,8 @@ protected override void OnMouseWheel(MouseEventArgs e)
513600 SetZoomLevel ( z , new Point ( e . X , e . Y ) ) ;
514601
515602 AdjustMapBounds ( ) ;
516-
517- base . OnMouseWheel ( e ) ;
603+ base . OnMouseWheel ( e ) ;
604+ CenterChanged ? . Invoke ( this , EventArgs . Empty ) ;
518605 }
519606
520607 /// <summary>
@@ -744,7 +831,6 @@ private void DrawPolygons(Graphics gr)
744831 using ( GraphicsPath gp = new GraphicsPath ( ) )
745832 {
746833 gp . StartFigure ( ) ;
747-
748834 for ( int i = 0 ; i < polygon . Count ; i ++ )
749835 {
750836 GeoPoint g = polygon . ElementAt ( i ) ;
@@ -754,9 +840,12 @@ private void DrawPolygons(Graphics gr)
754840 p = p0 . Nearest ( p , new PointF ( p . X - FullMapSizeInPixels , p . Y ) , new PointF ( p . X + FullMapSizeInPixels , p . Y ) ) ;
755841 gp . AddLine ( p0 , p ) ;
756842 }
843+
757844 p0 = p ;
758845 }
759846
847+ gp . CloseFigure ( ) ;
848+
760849 var eventArgs = new DrawPolygonEventArgs ( )
761850 {
762851 Graphics = gr ,
@@ -812,8 +901,15 @@ private void DrawTilePart(Graphics gr, int x, int y, int xRemainder, int yRemain
812901 Rectangle srcRect = new Rectangle ( TILE_SIZE / frac * xRemainder , TILE_SIZE / frac * yRemainder , TILE_SIZE / frac , TILE_SIZE / frac ) ;
813902
814903 // Destination rectangle
815- Rectangle destRect = new Rectangle ( p . X , p . Y , TILE_SIZE , TILE_SIZE ) ;
816- gr . DrawImage ( image , destRect , srcRect , GraphicsUnit . Pixel ) ;
904+ Rectangle destRect = new Rectangle ( p . X - frac , p . Y - frac , TILE_SIZE + 2 * frac , TILE_SIZE + 2 * frac ) ;
905+
906+ var state = gr . Save ( ) ;
907+ gr . SmoothingMode = SmoothingMode . HighSpeed ;
908+ gr . InterpolationMode = InterpolationMode . NearestNeighbor ;
909+ gr . PixelOffsetMode = PixelOffsetMode . HighSpeed ;
910+ gr . CompositingQuality = CompositingQuality . HighSpeed ;
911+ gr . DrawImage ( image , destRect , srcRect . X , srcRect . Y , srcRect . Width , srcRect . Height , GraphicsUnit . Pixel , TileImageAttributes ) ;
912+ gr . Restore ( state ) ;
817913 }
818914
819915 /// <summary>
@@ -828,7 +924,8 @@ private void DrawTile(Graphics gr, int x, int y, Image image)
828924 Point p = new Point ( ) ;
829925 p . X = _Offset . X + x * TILE_SIZE ;
830926 p . Y = _Offset . Y + y * TILE_SIZE ;
831- gr . DrawImageUnscaled ( image , p ) ;
927+
928+ gr . DrawImage ( image , new Rectangle ( p , new Drawing . Size ( TILE_SIZE , TILE_SIZE ) ) , 0 , 0 , TILE_SIZE , TILE_SIZE , GraphicsUnit . Pixel , TileImageAttributes ) ;
832929 }
833930
834931 /// <summary>
0 commit comments