Version 2.14. Added ViewportChangedEventArgs, fixed default MapItem Style

This commit is contained in:
ClemensF 2017-02-05 18:35:30 +01:00
parent aa8b68cd08
commit e85f1472ed
37 changed files with 174 additions and 105 deletions

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -36,7 +36,7 @@ namespace MapControl
private void OnMouseWheel(object sender, MouseWheelEventArgs e) private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{ {
var zoomChange = MouseWheelZoomDelta * (double)e.Delta / 120d; var zoomChange = MouseWheelZoomDelta * e.Delta / 120d;
ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomChange); ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomChange);
} }

View file

@ -47,7 +47,7 @@ namespace MapControl
{ {
base.OnMouseWheel(e); base.OnMouseWheel(e);
var zoomDelta = MouseWheelZoomDelta * (double)e.Delta / 120d; var zoomDelta = MouseWheelZoomDelta * e.Delta / 120d;
ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomDelta); ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomDelta);
} }

View file

@ -71,7 +71,7 @@ namespace MapControl
private void SetViewportTransform(Location origin) private void SetViewportTransform(Location origin)
{ {
MapOrigin = mapTransform.Transform(origin); MapOrigin = mapTransform.Transform(origin);
ViewportScale = Math.Pow(2d, ZoomLevel) * (double)TileSource.TileSize / 360d; ViewportScale = Math.Pow(2d, ZoomLevel) * TileSource.TileSize / 360d;
var transform = new Matrix(1d, 0d, 0d, 1d, -MapOrigin.X, -MapOrigin.Y) var transform = new Matrix(1d, 0d, 0d, 1d, -MapOrigin.X, -MapOrigin.Y)
.Rotate(-Heading) .Rotate(-Heading)

View file

@ -87,7 +87,7 @@ namespace MapControl
private void SetViewportTransform(Location origin) private void SetViewportTransform(Location origin)
{ {
MapOrigin = mapTransform.Transform(origin); MapOrigin = mapTransform.Transform(origin);
ViewportScale = Math.Pow(2d, ZoomLevel) * (double)TileSource.TileSize / 360d; ViewportScale = Math.Pow(2d, ZoomLevel) * TileSource.TileSize / 360d;
var transform = new Matrix(1d, 0d, 0d, 1d, -MapOrigin.X, -MapOrigin.Y); var transform = new Matrix(1d, 0d, 0d, 1d, -MapOrigin.X, -MapOrigin.Y);
transform.Rotate(-Heading); transform.Rotate(-Heading);

View file

@ -92,7 +92,7 @@ namespace MapControl
/// <summary> /// <summary>
/// Raised when the current viewport has changed. /// Raised when the current viewport has changed.
/// </summary> /// </summary>
public event EventHandler ViewportChanged; public event EventHandler<ViewportChangedEventArgs> ViewportChanged;
/// <summary> /// <summary>
/// Gets or sets the map foreground Brush. /// Gets or sets the map foreground Brush.
@ -278,17 +278,17 @@ namespace MapControl
public double ViewportScale { get; private set; } public double ViewportScale { get; private set; }
/// <summary> /// <summary>
/// Gets the scaling factor from meters to viewport coordinate units at the Center location. /// Gets the scaling factor from meters to viewport coordinate units at the Center location (px/m).
/// </summary> /// </summary>
public double CenterScale { get; private set; } public double CenterScale { get; private set; }
/// <summary> /// <summary>
/// Gets the map scale at the specified location as viewport coordinate units per meter. /// Gets the map scale at the specified location as viewport coordinate units per meter (px/m).
/// </summary> /// </summary>
public double GetMapScale(Location location) public double GetMapScale(Location location)
{ {
return mapTransform.RelativeScale(location) * return mapTransform.RelativeScale(location) *
Math.Pow(2d, ZoomLevel) * (double)TileSource.TileSize / (TileSource.MetersPerDegree * 360d); Math.Pow(2d, ZoomLevel) * TileSource.TileSize / (TileSource.MetersPerDegree * 360d);
} }
/// <summary> /// <summary>
@ -821,6 +821,7 @@ namespace MapControl
private void UpdateTransform(bool resetOrigin = false) private void UpdateTransform(bool resetOrigin = false)
{ {
var mapOriginX = MapOrigin.X;
var center = transformOrigin ?? Center; var center = transformOrigin ?? Center;
SetViewportTransform(center); SetViewportTransform(center);
@ -856,14 +857,14 @@ namespace MapControl
scaleTransform.ScaleY = CenterScale; scaleTransform.ScaleY = CenterScale;
rotateTransform.Angle = Heading; rotateTransform.Angle = Heading;
OnViewportChanged(); OnViewportChanged(new ViewportChangedEventArgs(MapOrigin.X - mapOriginX));
} }
protected override void OnViewportChanged() protected override void OnViewportChanged(ViewportChangedEventArgs e)
{ {
base.OnViewportChanged(); base.OnViewportChanged(e);
ViewportChanged?.Invoke(this, EventArgs.Empty); ViewportChanged?.Invoke(this, e);
} }
} }
} }

View file

@ -113,6 +113,7 @@
<Compile Include="TileLayerCollection.cs" /> <Compile Include="TileLayerCollection.cs" />
<Compile Include="TileSource.cs" /> <Compile Include="TileSource.cs" />
<Compile Include="TileSourceConverter.cs" /> <Compile Include="TileSourceConverter.cs" />
<Compile Include="ViewportChangedEventArgs.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Themes\Generic.xaml"> <Page Include="Themes\Generic.xaml">

View file

@ -98,6 +98,7 @@
<Compile Include="TileLayerCollection.cs" /> <Compile Include="TileLayerCollection.cs" />
<Compile Include="TileSource.cs" /> <Compile Include="TileSource.cs" />
<Compile Include="TileSourceConverter.cs" /> <Compile Include="TileSourceConverter.cs" />
<Compile Include="ViewportChangedEventArgs.cs" />
<Compile Include="WmsImageLayer.cs" /> <Compile Include="WmsImageLayer.cs" />
<Compile Include="WmsImageLayer.WPF.cs" /> <Compile Include="WmsImageLayer.WPF.cs" />
</ItemGroup> </ItemGroup>

View file

@ -32,7 +32,7 @@ namespace MapControl
StrokeThickness = 0.5; StrokeThickness = 0.5;
} }
protected override void OnViewportChanged() protected override void OnViewportChanged(ViewportChangedEventArgs e)
{ {
if (path == null) if (path == null)
{ {
@ -199,7 +199,7 @@ namespace MapControl
viewportTransform.Y = viewportPosition.Y; viewportTransform.Y = viewportPosition.Y;
} }
base.OnViewportChanged(); base.OnViewportChanged(e);
} }
} }
} }

View file

@ -33,7 +33,7 @@ namespace MapControl
typeof(MapGraticule), new FrameworkPropertyMetadata(0.5)); typeof(MapGraticule), new FrameworkPropertyMetadata(0.5));
} }
protected override void OnViewportChanged() protected override void OnViewportChanged(ViewportChangedEventArgs e)
{ {
InvalidateVisual(); InvalidateVisual();
} }

View file

@ -30,7 +30,7 @@ namespace MapControl
private double GetLineDistance() private double GetLineDistance()
{ {
var minDistance = MinLineDistance * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * (double)TileSource.TileSize); var minDistance = MinLineDistance * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * TileSource.TileSize);
var scale = 1d; var scale = 1d;
if (minDistance < 1d) if (minDistance < 1d)

View file

@ -15,14 +15,14 @@ namespace MapControl
{ {
public partial class MapImageLayer public partial class MapImageLayer
{ {
protected virtual void UpdateImage(BoundingBox boundingBox, Uri uri) protected virtual void UpdateImage(Uri uri)
{ {
UpdateImage(boundingBox, new BitmapImage(uri)); UpdateImage(new BitmapImage(uri));
} }
protected void UpdateImage(BoundingBox boundingBox, BitmapSource bitmap) protected void UpdateImage(BitmapSource bitmap)
{ {
SetTopImage(boundingBox, bitmap); SetTopImage(bitmap);
var bitmapImage = bitmap as BitmapImage; var bitmapImage = bitmap as BitmapImage;

View file

@ -11,18 +11,18 @@ namespace MapControl
{ {
public partial class MapImageLayer public partial class MapImageLayer
{ {
protected virtual void UpdateImage(BoundingBox boundingBox, Uri uri) protected virtual void UpdateImage(Uri uri)
{ {
Task.Run(() => Task.Run(() =>
{ {
var image = ImageLoader.FromUri(uri); var image = ImageLoader.FromUri(uri);
Dispatcher.BeginInvoke(new Action(() => UpdateImage(boundingBox, image))); Dispatcher.BeginInvoke(new Action(() => UpdateImage(image)));
}); });
} }
protected void UpdateImage(BoundingBox boundingBox, BitmapSource bitmap) protected void UpdateImage(BitmapSource bitmap)
{ {
SetTopImage(boundingBox, bitmap); SetTopImage(bitmap);
if (bitmap != null && !bitmap.IsFrozen && bitmap.IsDownloading) if (bitmap != null && !bitmap.IsFrozen && bitmap.IsDownloading)
{ {

View file

@ -4,6 +4,7 @@
using System; using System;
using System.Globalization; using System.Globalization;
using System.Linq;
#if NETFX_CORE #if NETFX_CORE
using Windows.Foundation; using Windows.Foundation;
using Windows.UI.Xaml; using Windows.UI.Xaml;
@ -21,7 +22,7 @@ using System.Windows.Threading;
namespace MapControl namespace MapControl
{ {
/// <summary> /// <summary>
/// Map image overlay. Fills the entire viewport with map images provided by a web service, /// Map image overlay. Fills the entire viewport with a map image provided by a web service,
/// e.g. a Web Map Service (WMS). The image request Uri is specified by the UriFormat property. /// e.g. a Web Map Service (WMS). The image request Uri is specified by the UriFormat property.
/// </summary> /// </summary>
public partial class MapImageLayer : MapPanel public partial class MapImageLayer : MapPanel
@ -58,6 +59,9 @@ namespace MapControl
public static readonly DependencyProperty MaxLatitudeProperty = DependencyProperty.Register( public static readonly DependencyProperty MaxLatitudeProperty = DependencyProperty.Register(
"MaxLatitude", typeof(double), typeof(MapImageLayer), new PropertyMetadata(double.NaN)); "MaxLatitude", typeof(double), typeof(MapImageLayer), new PropertyMetadata(double.NaN));
public static readonly DependencyProperty MaxBoundingBoxWidthProperty = DependencyProperty.Register(
"MaxBoundingBoxWidth", typeof(double), typeof(MapImageLayer), new PropertyMetadata(double.NaN));
public static readonly DependencyProperty RelativeImageSizeProperty = DependencyProperty.Register( public static readonly DependencyProperty RelativeImageSizeProperty = DependencyProperty.Register(
"RelativeImageSize", typeof(double), typeof(MapImageLayer), new PropertyMetadata(1d)); "RelativeImageSize", typeof(double), typeof(MapImageLayer), new PropertyMetadata(1d));
@ -127,7 +131,16 @@ namespace MapControl
} }
/// <summary> /// <summary>
/// Relative size of the map images in relation to the current viewport size. /// Optional maximum width of the map image's bounding box. Default is NaN.
/// </summary>
public double MaxBoundingBoxWidth
{
get { return (double)GetValue(MaxBoundingBoxWidthProperty); }
set { SetValue(MaxBoundingBoxWidthProperty, value); }
}
/// <summary>
/// Relative size of the map image in relation to the current viewport size.
/// Setting a value greater than one will let MapImageLayer request images that /// Setting a value greater than one will let MapImageLayer request images that
/// are larger than the viewport, in order to support smooth panning. /// are larger than the viewport, in order to support smooth panning.
/// </summary> /// </summary>
@ -146,19 +159,36 @@ namespace MapControl
set { SetValue(UpdateIntervalProperty, value); } set { SetValue(UpdateIntervalProperty, value); }
} }
protected virtual BoundingBox ProjectBoundingBox(BoundingBox boundingBox) protected BoundingBox ImageBoundingBox { get; private set; }
protected virtual BoundingBox ProjectedBoundingBox
{ {
var p1 = ParentMap.MapTransform.Transform(new Location(boundingBox.South, boundingBox.West)); get
var p2 = ParentMap.MapTransform.Transform(new Location(boundingBox.North, boundingBox.East)); {
var p1 = ParentMap.MapTransform.Transform(new Location(ImageBoundingBox.South, ImageBoundingBox.West));
var p2 = ParentMap.MapTransform.Transform(new Location(ImageBoundingBox.North, ImageBoundingBox.East));
return new BoundingBox( return new BoundingBox(
TileSource.MetersPerDegree * p1.X, TileSource.MetersPerDegree * p2.X, TileSource.MetersPerDegree * p1.X, TileSource.MetersPerDegree * p2.X,
TileSource.MetersPerDegree * p1.Y, TileSource.MetersPerDegree * p2.Y); TileSource.MetersPerDegree * p1.Y, TileSource.MetersPerDegree * p2.Y);
} }
}
protected override void OnViewportChanged() protected override void OnViewportChanged(ViewportChangedEventArgs e)
{ {
base.OnViewportChanged(); base.OnViewportChanged(e);
if (Math.Abs(e.OriginOffset) > 180d)
{
var offset = 360d * Math.Sign(e.OriginOffset);
ImageBoundingBox = new BoundingBox(ImageBoundingBox.West + offset, ImageBoundingBox.East + offset, ImageBoundingBox.South, ImageBoundingBox.North);
foreach (var mapImage in Children.OfType<MapImage>().Where(i => i.BoundingBoxValid))
{
mapImage.SetBoundingBox(mapImage.West + offset, mapImage.East + offset, mapImage.South, mapImage.North);
}
}
updateTimer.Stop(); updateTimer.Stop();
updateTimer.Start(); updateTimer.Start();
@ -212,16 +242,24 @@ namespace MapControl
north = MaxLatitude; north = MaxLatitude;
} }
if (!double.IsNaN(MaxBoundingBoxWidth) && east - west > MaxBoundingBoxWidth)
{
var d = (east - west - MaxBoundingBoxWidth) / 2d;
west += d;
east -= d;
}
ImageBoundingBox = new BoundingBox(west, east, south, north);
var p1 = ParentMap.MapTransform.Transform(new Location(south, west)); var p1 = ParentMap.MapTransform.Transform(new Location(south, west));
var p2 = ParentMap.MapTransform.Transform(new Location(north, east)); var p2 = ParentMap.MapTransform.Transform(new Location(north, east));
UpdateImage(new BoundingBox(west, east, south, north), UpdateImage((int)Math.Round((p2.X - p1.X) * ParentMap.ViewportScale),
(int)Math.Round((p2.X - p1.X) * ParentMap.ViewportScale),
(int)Math.Round((p2.Y - p1.Y) * ParentMap.ViewportScale)); (int)Math.Round((p2.Y - p1.Y) * ParentMap.ViewportScale));
} }
} }
protected virtual void UpdateImage(BoundingBox boundingBox, int width, int height) protected virtual void UpdateImage(int width, int height)
{ {
if (UriFormat != null && width > 0 && height > 0) if (UriFormat != null && width > 0 && height > 0)
{ {
@ -231,7 +269,7 @@ namespace MapControl
if (uri.Contains("{W}") && uri.Contains("{E}") && uri.Contains("{S}") && uri.Contains("{N}")) if (uri.Contains("{W}") && uri.Contains("{E}") && uri.Contains("{S}") && uri.Contains("{N}"))
{ {
var projectedBoundingBox = ProjectBoundingBox(boundingBox); var projectedBoundingBox = ProjectedBoundingBox;
uri = uri uri = uri
.Replace("{W}", projectedBoundingBox.West.ToString(CultureInfo.InvariantCulture)) .Replace("{W}", projectedBoundingBox.West.ToString(CultureInfo.InvariantCulture))
@ -242,26 +280,26 @@ namespace MapControl
else else
{ {
uri = uri uri = uri
.Replace("{w}", boundingBox.West.ToString(CultureInfo.InvariantCulture)) .Replace("{w}", ImageBoundingBox.West.ToString(CultureInfo.InvariantCulture))
.Replace("{s}", boundingBox.South.ToString(CultureInfo.InvariantCulture)) .Replace("{s}", ImageBoundingBox.South.ToString(CultureInfo.InvariantCulture))
.Replace("{e}", boundingBox.East.ToString(CultureInfo.InvariantCulture)) .Replace("{e}", ImageBoundingBox.East.ToString(CultureInfo.InvariantCulture))
.Replace("{n}", boundingBox.North.ToString(CultureInfo.InvariantCulture)); .Replace("{n}", ImageBoundingBox.North.ToString(CultureInfo.InvariantCulture));
} }
UpdateImage(boundingBox, new Uri(uri)); UpdateImage(new Uri(uri));
} }
else else
{ {
UpdateImage(boundingBox, (BitmapSource)null); UpdateImage((BitmapSource)null);
} }
} }
private void SetTopImage(BoundingBox boundingBox, BitmapSource bitmap) private void SetTopImage(BitmapSource bitmap)
{ {
currentImageIndex = (currentImageIndex + 1) % 2; currentImageIndex = (currentImageIndex + 1) % 2;
var topImage = (MapImage)Children[currentImageIndex]; var topImage = (MapImage)Children[currentImageIndex];
topImage.SetBoundingBox(boundingBox.West, boundingBox.East, boundingBox.South, boundingBox.North); topImage.SetBoundingBox(ImageBoundingBox.West, ImageBoundingBox.East, ImageBoundingBox.South, ImageBoundingBox.North);
topImage.Source = bitmap; topImage.Source = bitmap;
} }

View file

@ -74,11 +74,11 @@ namespace MapControl
if (parentMap != null && parentMap != this) if (parentMap != null && parentMap != this)
{ {
parentMap.ViewportChanged += OnViewportChanged; parentMap.ViewportChanged += OnViewportChanged;
OnViewportChanged(); OnViewportChanged(new ViewportChangedEventArgs(0d));
} }
} }
protected virtual void OnViewportChanged() protected virtual void OnViewportChanged(ViewportChangedEventArgs e)
{ {
foreach (UIElement element in Children) foreach (UIElement element in Children)
{ {
@ -91,9 +91,9 @@ namespace MapControl
} }
} }
private void OnViewportChanged(object sender, EventArgs e) private void OnViewportChanged(object sender, ViewportChangedEventArgs e)
{ {
OnViewportChanged(); OnViewportChanged(e);
} }
private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) private static void ParentMapPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)

View file

@ -93,7 +93,7 @@ namespace MapControl
{ {
viewportTransform.Children.Insert(0, new TranslateTransform()); viewportTransform.Children.Insert(0, new TranslateTransform());
parentMap.ViewportChanged += OnViewportChanged; parentMap.ViewportChanged += OnViewportChanged;
OnViewportChanged(parentMap, EventArgs.Empty); OnViewportChanged(parentMap, null);
} }
private void DetachViewportChanged() private void DetachViewportChanged()

View file

@ -67,6 +67,16 @@ namespace MapControl
set { SetValue(NorthProperty, value); } set { SetValue(NorthProperty, value); }
} }
public bool BoundingBoxValid
{
get
{
return !double.IsNaN(South) && !double.IsNaN(North)
&& !double.IsNaN(West) && !double.IsNaN(East)
&& South < North && West < East;
}
}
public void SetBoundingBox(double west, double east, double south, double north) public void SetBoundingBox(double west, double east, double south, double north)
{ {
if (West != west || East != east || South != south || North != north) if (West != west || East != east || South != south || North != north)
@ -87,10 +97,7 @@ namespace MapControl
{ {
var geometry = (RectangleGeometry)Data; var geometry = (RectangleGeometry)Data;
if (ParentMap != null && if (ParentMap != null && BoundingBoxValid)
!double.IsNaN(South) && !double.IsNaN(North) &&
!double.IsNaN(West) && !double.IsNaN(East) &&
South < North && West < East)
{ {
var rect = new Rect(ParentMap.MapTransform.Transform(new Location(South, West)), var rect = new Rect(ParentMap.MapTransform.Transform(new Location(South, West)),
ParentMap.MapTransform.Transform(new Location(North, East))); ParentMap.MapTransform.Transform(new Location(North, East)));

View file

@ -99,7 +99,7 @@ namespace MapControl
} }
} }
protected override void OnViewportChanged() protected override void OnViewportChanged(ViewportChangedEventArgs e)
{ {
InvalidateMeasure(); InvalidateMeasure();
} }

View file

@ -14,8 +14,8 @@ using System.Windows;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -20,8 +20,8 @@
<Style TargetType="map:MapItem"> <Style TargetType="map:MapItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/> <Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="map:MapItem"> <ControlTemplate TargetType="map:MapItem">

View file

@ -24,7 +24,7 @@ namespace MapControl
private Rect GetTileIndexBounds(int zoomLevel) private Rect GetTileIndexBounds(int zoomLevel)
{ {
var scale = (double)(1 << zoomLevel) / 360d; var scale = (1 << zoomLevel) / 360d;
var transform = new MatrixTransform var transform = new MatrixTransform
{ {
Matrix = parentMap.ViewportTransform.Matrix Matrix = parentMap.ViewportTransform.Matrix

View file

@ -18,7 +18,7 @@ namespace MapControl
private Rect GetTileIndexBounds(int zoomLevel) private Rect GetTileIndexBounds(int zoomLevel)
{ {
var scale = (double)(1 << zoomLevel) / 360d; var scale = (1 << zoomLevel) / 360d;
var transform = parentMap.ViewportTransform.Matrix; var transform = parentMap.ViewportTransform.Matrix;
transform.Invert(); // view to map coordinates transform.Invert(); // view to map coordinates

View file

@ -87,7 +87,6 @@ namespace MapControl
private readonly DispatcherTimer updateTimer; private readonly DispatcherTimer updateTimer;
private MapBase parentMap; private MapBase parentMap;
private double mapOriginX;
public TileLayer() public TileLayer()
: this(new TileImageLoader()) : this(new TileImageLoader())
@ -246,18 +245,17 @@ namespace MapControl
if (parentMap != null) if (parentMap != null)
{ {
parentMap.ViewportChanged += OnViewportChanged; parentMap.ViewportChanged += OnViewportChanged;
mapOriginX = parentMap.MapOrigin.X;
} }
UpdateTileGrid(); UpdateTileGrid();
} }
} }
private void OnViewportChanged(object sender, EventArgs e) private void OnViewportChanged(object sender, ViewportChangedEventArgs e)
{ {
if (TileGrid == null || Math.Abs(parentMap.MapOrigin.X - mapOriginX) > 180d) if (TileGrid == null || Math.Abs(e.OriginOffset) > 180d)
{ {
// immediately handle map origin leap when map center moves across 180° longitude // immediate update when map center moves across 180° longitude
UpdateTileGrid(); UpdateTileGrid();
} }
else else
@ -274,8 +272,6 @@ namespace MapControl
updateTimer.Start(); updateTimer.Start();
} }
} }
mapOriginX = parentMap.MapOrigin.X;
} }
protected void UpdateTileGrid() protected void UpdateTileGrid()

View file

@ -160,11 +160,11 @@ namespace MapControl
private Uri GetBoundingBoxUri(int x, int y, int zoomLevel) private Uri GetBoundingBoxUri(int x, int y, int zoomLevel)
{ {
var tileSize = 360d / (double)(1 << zoomLevel); // tile width in degrees var tileSize = 360d / (1 << zoomLevel); // tile width in degrees
var west = MetersPerDegree * ((double)x * tileSize - 180d); var west = MetersPerDegree * (x * tileSize - 180d);
var east = MetersPerDegree * ((double)(x + 1) * tileSize - 180d); var east = MetersPerDegree * ((x + 1) * tileSize - 180d);
var south = MetersPerDegree * (180d - (double)(y + 1) * tileSize); var south = MetersPerDegree * (180d - (y + 1) * tileSize);
var north = MetersPerDegree * (180d - (double)y * tileSize); var north = MetersPerDegree * (180d - y * tileSize);
return new Uri(uriFormat return new Uri(uriFormat
.Replace("{W}", west.ToString(CultureInfo.InvariantCulture)) .Replace("{W}", west.ToString(CultureInfo.InvariantCulture))
@ -177,11 +177,11 @@ namespace MapControl
private Uri GetLatLonBoundingBoxUri(int x, int y, int zoomLevel) private Uri GetLatLonBoundingBoxUri(int x, int y, int zoomLevel)
{ {
var tileSize = 360d / (double)(1 << zoomLevel); // tile width in degrees var tileSize = 360d / (1 << zoomLevel); // tile width in degrees
var west = (double)x * tileSize - 180d; var west = x * tileSize - 180d;
var east = (double)(x + 1) * tileSize - 180d; var east = (x + 1) * tileSize - 180d;
var south = MercatorTransform.YToLatitude(180d - (double)(y + 1) * tileSize); var south = MercatorTransform.YToLatitude(180d - (y + 1) * tileSize);
var north = MercatorTransform.YToLatitude(180d - (double)y * tileSize); var north = MercatorTransform.YToLatitude(180d - y * tileSize);
return new Uri(uriFormat return new Uri(uriFormat
.Replace("{w}", west.ToString(CultureInfo.InvariantCulture)) .Replace("{w}", west.ToString(CultureInfo.InvariantCulture))

View file

@ -0,0 +1,22 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// © 2017 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
namespace MapControl
{
public class ViewportChangedEventArgs : EventArgs
{
public ViewportChangedEventArgs(double originOffset)
{
OriginOffset = originOffset;
}
/// <summary>
/// Offset of the X value of the map coordinate origin from the previous viewport.
/// Used to detect if the map center has moved across 180° longitude.
/// </summary>
public double OriginOffset { get; }
}
}

View file

@ -162,6 +162,9 @@
<Compile Include="..\TileSource.cs"> <Compile Include="..\TileSource.cs">
<Link>TileSource.cs</Link> <Link>TileSource.cs</Link>
</Compile> </Compile>
<Compile Include="..\ViewportChangedEventArgs.cs">
<Link>ViewportChangedEventArgs.cs</Link>
</Compile>
<Compile Include="..\WmsImageLayer.cs"> <Compile Include="..\WmsImageLayer.cs">
<Link>WmsImageLayer.cs</Link> <Link>WmsImageLayer.cs</Link>
</Compile> </Compile>

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -20,8 +20,8 @@
<Style TargetType="map:MapItem"> <Style TargetType="map:MapItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/> <Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Stretch"/> <Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="map:MapItem"> <ControlTemplate TargetType="map:MapItem">

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("© 2015 Clemens Fischer")] [assembly: AssemblyCopyright("© 2015 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("2.11.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.11.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -8,7 +8,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]

View file

@ -7,8 +7,8 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCompany("Clemens Fischer")] [assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("© 2016 Clemens Fischer")] [assembly: AssemblyCopyright("© 2016 Clemens Fischer")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("2.13.0")] [assembly: AssemblyVersion("2.14.0")]
[assembly: AssemblyFileVersion("2.13.0")] [assembly: AssemblyFileVersion("2.14.0")]
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: ComVisible(false)] [assembly: ComVisible(false)]