Version 1.3.0: Added class MapImageLayer for WMS based map overlays. Plus plenty of cleanup.

This commit is contained in:
ClemensF 2013-05-07 18:12:25 +02:00
parent 5342a27559
commit ba9edb14cc
89 changed files with 545 additions and 638 deletions

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using Windows.UI.Xaml;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows.Media;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
namespace MapControl

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,14 +1,16 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Windows;
using System.Windows.Input;
namespace MapControl
{
public partial class Map
/// <summary>
/// Default input event handling.
/// </summary>
public class Map : MapBase
{
private Point? mousePosition;
@ -19,17 +21,16 @@ namespace MapControl
MouseLeftButtonDown += OnMouseLeftButtonDown;
MouseLeftButtonUp += OnMouseLeftButtonUp;
MouseMove += OnMouseMove;
#if !SILVERLIGHT
ManipulationDelta += (o, e) => TransformMap(
e.ManipulationOrigin, (Point)e.DeltaManipulation.Translation, e.DeltaManipulation.Rotation,
(e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2d); ;
#endif
}
/// <summary>
/// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
/// </summary>
public double MouseWheelZoomChange { get; set; }
private void OnMouseWheel(object sender, MouseWheelEventArgs e)
{
var zoomChange = MouseWheelZoomChange * (double)e.Delta / MouseWheelDelta;
var zoomChange = MouseWheelZoomChange * (double)e.Delta / 120d;
ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomChange);
}

77
MapControl/Map.WPF.cs Normal file
View file

@ -0,0 +1,77 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;
using System.Windows.Input;
namespace MapControl
{
/// <summary>
/// Default input event handling.
/// </summary>
public class Map : MapBase
{
private Point? mousePosition;
public Map()
{
MouseWheelZoomChange = 1d;
}
/// <summary>
/// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
/// </summary>
public double MouseWheelZoomChange { get; set; }
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
base.OnMouseWheel(e);
var zoomChange = MouseWheelZoomChange * (double)e.Delta / 120d;
ZoomMap(e.GetPosition(this), TargetZoomLevel + zoomChange);
}
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
if (CaptureMouse())
{
mousePosition = e.GetPosition(this);
}
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (mousePosition.HasValue)
{
mousePosition = null;
ReleaseMouseCapture();
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
base.OnMouseMove(e);
if (mousePosition.HasValue)
{
var position = e.GetPosition(this);
TranslateMap((Point)(position - mousePosition));
mousePosition = position;
}
}
protected override void OnManipulationDelta(ManipulationDeltaEventArgs e)
{
base.OnManipulationDelta(e);
TransformMap(e.ManipulationOrigin,
(Point)e.DeltaManipulation.Translation, e.DeltaManipulation.Rotation,
(e.DeltaManipulation.Scale.X + e.DeltaManipulation.Scale.Y) / 2d);
}
}
}

View file

@ -1,15 +1,17 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using Windows.Devices.Input;
using Windows.Foundation;
using Windows.UI.Xaml.Input;
namespace MapControl
{
public partial class Map
/// <summary>
/// Default input event handling.
/// </summary>
public class Map : MapBase
{
private Point? mousePosition;
@ -26,18 +28,15 @@ namespace MapControl
PointerMoved += OnPointerMoved;
}
private void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (e.PointerDeviceType != PointerDeviceType.Mouse)
{
TransformMap(e.Position, e.Delta.Translation, e.Delta.Rotation, e.Delta.Scale);
}
}
/// <summary>
/// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
/// </summary>
public double MouseWheelZoomChange { get; set; }
private void OnPointerWheelChanged(object sender, PointerRoutedEventArgs e)
{
var point = e.GetCurrentPoint(this);
var zoomChange = MouseWheelZoomChange * (double)point.Properties.MouseWheelDelta / MouseWheelDelta;
var zoomChange = MouseWheelZoomChange * (double)point.Properties.MouseWheelDelta / 120d;
ZoomMap(point.Position, TargetZoomLevel + zoomChange);
}
@ -68,5 +67,13 @@ namespace MapControl
mousePosition = position;
}
}
private void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
if (e.PointerDeviceType != PointerDeviceType.Mouse)
{
TransformMap(e.Position, e.Delta.Translation, e.Delta.Rotation, e.Delta.Scale);
}
}
}
}

View file

@ -1,19 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
namespace MapControl
{
/// <summary>
/// MapBase with input event handling.
/// </summary>
public partial class Map : MapBase
{
private const double MouseWheelDelta = 120;
/// <summary>
/// Gets or sets the amount by which the ZoomLevel property changes during a MouseWheel event.
/// </summary>
public double MouseWheelZoomChange { get; set; }
}
}

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
@ -20,7 +20,7 @@ namespace MapControl
{
// Set FillBehavior.HoldEnd to prevent animation from returning
// to local value before invoking the Completed handler
private const FillBehavior AnimationFillBehavior = FillBehavior.HoldEnd;
private const FillBehavior animationFillBehavior = FillBehavior.HoldEnd;
public static readonly DependencyProperty ForegroundProperty = DependencyProperty.Register(
"Foreground", typeof(Brush), typeof(MapBase), new PropertyMetadata(new SolidColorBrush(Colors.Black)));

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;
@ -12,7 +12,7 @@ namespace MapControl
public partial class MapBase
{
// FillBehavior must be set to Stop to re-enable local property values
private const FillBehavior AnimationFillBehavior = FillBehavior.Stop;
private const FillBehavior animationFillBehavior = FillBehavior.Stop;
public static readonly DependencyProperty ForegroundProperty =
System.Windows.Controls.Control.ForegroundProperty.AddOwner(typeof(MapBase));

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
@ -26,7 +26,6 @@ namespace MapControl
/// </summary>
public partial class MapBase : MapPanel
{
public const double MeterPerDegree = 1852d * 60d;
public static TimeSpan AnimationDuration = TimeSpan.FromSeconds(0.5);
public static EasingFunctionBase AnimationEasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseOut };
@ -272,12 +271,24 @@ namespace MapControl
get { return scaleRotateTransform; }
}
/// <summary>
/// Gets the conversion factor from longitude degrees to meters, at latitude = 0.
/// </summary>
public double MetersPerDegree
{
get
{
return (TileLayer != null && TileLayer.TileSource != null) ?
TileLayer.TileSource.MetersPerDegree : (TileSource.EarthRadius * Math.PI / 180d);
}
}
/// <summary>
/// Gets the map scale at the specified location as viewport coordinate units (pixels) per meter.
/// </summary>
public double GetMapScale(Location location)
{
return mapTransform.RelativeScale(location) * Math.Pow(2d, ZoomLevel) * 256d / (MeterPerDegree * 360d);
return mapTransform.RelativeScale(location) * Math.Pow(2d, ZoomLevel) * TileSource.TileSize / (MetersPerDegree * 360d);
}
/// <summary>
@ -591,8 +602,8 @@ namespace MapControl
From = new Point(Center.Longitude, Center.Latitude),
To = new Point(targetCenter.Longitude, targetCenter.Latitude),
Duration = AnimationDuration,
FillBehavior = AnimationFillBehavior,
EasingFunction = AnimationEasingFunction
EasingFunction = AnimationEasingFunction,
FillBehavior = animationFillBehavior
};
centerAnimation.Completed += CenterAnimationCompleted;
@ -695,8 +706,8 @@ namespace MapControl
{
To = targetZoomLevel,
Duration = AnimationDuration,
FillBehavior = AnimationFillBehavior,
EasingFunction = AnimationEasingFunction
EasingFunction = AnimationEasingFunction,
FillBehavior = animationFillBehavior
};
zoomLevelAnimation.Completed += ZoomLevelAnimationCompleted;
@ -719,7 +730,8 @@ namespace MapControl
private void CoerceHeadingProperty(DependencyProperty property, ref double heading)
{
var coercedValue = (heading >= -180d && heading <= 360d) ? heading : (((heading % 360d) + 360d) % 360d);
var coercedValue = (heading >= -180d && heading <= 360d) ?
heading : (((heading % 360d) + 360d) % 360d);
if (coercedValue != heading)
{
@ -769,8 +781,8 @@ namespace MapControl
{
By = delta,
Duration = AnimationDuration,
FillBehavior = AnimationFillBehavior,
EasingFunction = AnimationEasingFunction
EasingFunction = AnimationEasingFunction,
FillBehavior = animationFillBehavior
};
headingAnimation.Completed += HeadingAnimationCompleted;
@ -811,7 +823,7 @@ namespace MapControl
}
}
scale *= mapTransform.RelativeScale(center) / MeterPerDegree; // Pixels per meter at center latitude
scale *= mapTransform.RelativeScale(center) / MetersPerDegree; // Pixels per meter at center latitude
CenterScale = scale;
SetTransformMatrixes(scale);

View file

@ -69,14 +69,12 @@
<Compile Include="LocationCollection.cs" />
<Compile Include="LocationCollectionConverter.cs" />
<Compile Include="LocationConverter.cs" />
<Compile Include="Map.cs" />
<Compile Include="Map.Silverlight.WPF.cs" />
<Compile Include="Map.Silverlight.cs" />
<Compile Include="MapBase.cs" />
<Compile Include="MapBase.Silverlight.WinRT.cs" />
<Compile Include="MapGraticule.cs" />
<Compile Include="MapGraticule.Silverlight.WinRT.cs" />
<Compile Include="MapImage.cs" />
<Compile Include="MapImage.Silverlight.WinRT.cs" />
<Compile Include="MapItem.Silverlight.WinRT.cs" />
<Compile Include="MapItemsControl.cs" />
<Compile Include="MapItemsControl.Silverlight.WinRT.cs" />

View file

@ -45,18 +45,17 @@
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Map.WPF.cs" />
<Compile Include="MapGraticule.WPF.cs" />
<Compile Include="Location.cs" />
<Compile Include="LocationCollection.cs" />
<Compile Include="LocationCollectionConverter.cs" />
<Compile Include="LocationConverter.cs" />
<Compile Include="Map.cs" />
<Compile Include="Map.Silverlight.WPF.cs" />
<Compile Include="MapBase.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="MapBase.WPF.cs" />
<Compile Include="MapImage.WPF.cs" />
<Compile Include="MapImageLayer.cs" />
<Compile Include="MapItem.WPF.cs" />
<Compile Include="MapItemsControl.cs" />
<Compile Include="MapItemsControl.WPF.cs" />

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
@ -32,7 +32,7 @@ namespace MapControl
var bounds = ParentMap.ViewportTransform.Inverse.TransformBounds(new Rect(ParentMap.RenderSize));
var start = ParentMap.MapTransform.Transform(new Point(bounds.X, bounds.Y));
var end = ParentMap.MapTransform.Transform(new Point(bounds.X + bounds.Width, bounds.Y + bounds.Height));
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * 256d);
var minSpacing = MinLineSpacing * 360d / (Math.Pow(2d, ParentMap.ZoomLevel) * TileSource.TileSize);
var spacing = LineSpacings[LineSpacings.Length - 1];
if (spacing >= minSpacing)

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,49 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
#else
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
#endif
namespace MapControl
{
public partial class MapImage
{
private void BeginOpacityAnimation(ImageSource image)
{
var bitmapImage = image as BitmapImage;
if (bitmapImage != null)
{
bitmapImage.ImageOpened += BitmapImageOpened;
bitmapImage.ImageFailed += BitmapImageFailed;
}
else
{
BeginOpacityAnimation();
}
}
private void BitmapImageOpened(object sender, RoutedEventArgs e)
{
((BitmapImage)sender).ImageOpened -= BitmapImageOpened;
((BitmapImage)sender).ImageFailed -= BitmapImageFailed;
BeginOpacityAnimation();
}
private void BitmapImageFailed(object sender, ExceptionRoutedEventArgs e)
{
((BitmapImage)sender).ImageOpened -= BitmapImageOpened;
((BitmapImage)sender).ImageFailed -= BitmapImageFailed;
((ImageBrush)Fill).ImageSource = null;
}
}
}

View file

@ -1,42 +0,0 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace MapControl
{
public partial class MapImage
{
private void BeginOpacityAnimation(ImageSource image)
{
var bitmapImage = image as BitmapImage;
if (bitmapImage != null && bitmapImage.IsDownloading)
{
bitmapImage.DownloadCompleted += BitmapDownloadCompleted;
bitmapImage.DownloadFailed += BitmapDownloadFailed;
}
else
{
BeginOpacityAnimation();
}
}
private void BitmapDownloadCompleted(object sender, EventArgs e)
{
((BitmapImage)sender).DownloadCompleted -= BitmapDownloadCompleted;
((BitmapImage)sender).DownloadFailed -= BitmapDownloadFailed;
BeginOpacityAnimation();
}
private void BitmapDownloadFailed(object sender, ExceptionEventArgs e)
{
((BitmapImage)sender).DownloadCompleted -= BitmapDownloadCompleted;
((BitmapImage)sender).DownloadFailed -= BitmapDownloadFailed;
((ImageBrush)Fill).ImageSource = null;
}
}
}

View file

@ -1,24 +1,25 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
#else
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
#endif
namespace MapControl
{
public partial class MapImage : MapRectangle
/// <summary>
/// Fills a rectangular area with an ImageBrush from the Source property.
/// </summary>
public class MapImage : MapRectangle
{
private static readonly Transform imageTransform = new MatrixTransform
{
Matrix = new Matrix(1, 0, 0, -1, 0, 1)
Matrix = new Matrix(1d, 0d, 0d, -1d, 0d, 1d)
};
public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
@ -31,36 +32,13 @@ namespace MapControl
set { SetValue(SourceProperty, value); }
}
public bool AnimateOpacity { get; set; }
private void SourceChanged(ImageSource image)
{
Fill = new ImageBrush
{
ImageSource = image,
RelativeTransform = imageTransform,
Opacity = 0d
RelativeTransform = imageTransform
};
if (AnimateOpacity)
{
BeginOpacityAnimation(image);
}
else
{
Fill.Opacity = 1d;
}
}
private void BeginOpacityAnimation()
{
Fill.BeginAnimation(Brush.OpacityProperty,
new DoubleAnimation
{
To = 1d,
Duration = Tile.AnimationDuration,
FillBehavior = FillBehavior.HoldEnd
});
}
}
}

187
MapControl/MapImageLayer.cs Normal file
View file

@ -0,0 +1,187 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Net;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace MapControl
{
/// <summary>
/// Map image overlay. Fills the entire viewport with a map image from a web request,
/// for example from a Web Map Service (WMS).
/// The request Uri is specified by the UriFormat property, which has {X} and {Y}
/// format specifiers for the map width and height in pixels, and either
/// {w},{s},{e},{n} for the bounding box in lat/lon (like for example EPSG:4326) or
/// {W},{S},{E},{N} for the bounding box in meters (like for example EPSG:3857)
/// </summary>
public class MapImageLayer : MapPanel
{
private readonly DispatcherTimer updateTimer;
private readonly WebClient webClient;
private string uriFormat;
private bool latLonBoundingBox;
private bool imageIsValid;
private bool updateInProgress;
private int currentImageIndex;
public MapImageLayer()
{
Children.Add(new MapImage { Opacity = 0d });
Children.Add(new MapImage { Opacity = 0d });
webClient = new WebClient();
webClient.Headers.Add(HttpRequestHeader.UserAgent, "XAML Map Control");
updateTimer = new DispatcherTimer { Interval = TileContainer.UpdateInterval };
updateTimer.Tick += UpdateImage;
}
public string UriFormat
{
get { return uriFormat; }
set
{
if (value != null)
{
if (!(value.Contains("{X}") && value.Contains("{Y}")))
{
throw new ArgumentException("UriFormat must specify the requested image size by {X} and {Y}.");
}
if (value.Contains("{w}") && value.Contains("{s}") && value.Contains("{e}") && value.Contains("{n}"))
{
latLonBoundingBox = true;
}
else if (!(value.Contains("{W}") && value.Contains("{S}") && value.Contains("{E}") && value.Contains("{N}")))
{
throw new ArgumentException("UriFormat must specify a bounding box in meters by {W},{S},{E},{N} or as lat/lon by {w},{s},{e},{n}.");
}
}
uriFormat = value;
if (ParentMap != null)
{
UpdateImage(this, EventArgs.Empty);
}
}
}
protected override void OnViewportChanged()
{
base.OnViewportChanged();
imageIsValid = false;
updateTimer.Stop();
updateTimer.Start();
}
private void UpdateImage(object sender, EventArgs e)
{
updateTimer.Stop();
if (updateInProgress || string.IsNullOrWhiteSpace(uriFormat))
{
return;
}
imageIsValid = true;
updateInProgress = true;
var uri = uriFormat.
Replace("{X}", ActualWidth.ToString("F0", CultureInfo.InvariantCulture)).
Replace("{Y}", ActualHeight.ToString("F0", CultureInfo.InvariantCulture));
var loc1 = ParentMap.ViewportPointToLocation(new Point(0d, 0d));
var loc2 = ParentMap.ViewportPointToLocation(new Point(ActualWidth, 0d));
var loc3 = ParentMap.ViewportPointToLocation(new Point(0d, ActualHeight));
var loc4 = ParentMap.ViewportPointToLocation(new Point(ActualWidth, ActualHeight));
ThreadPool.QueueUserWorkItem(o =>
{
var west = Math.Min(loc1.Longitude, Math.Min(loc2.Longitude, Math.Min(loc3.Longitude, loc4.Longitude)));
var east = Math.Max(loc1.Longitude, Math.Max(loc2.Longitude, Math.Max(loc3.Longitude, loc4.Longitude)));
var south = Math.Min(loc1.Latitude, Math.Min(loc2.Latitude, Math.Min(loc3.Latitude, loc4.Latitude)));
var north = Math.Max(loc1.Latitude, Math.Max(loc2.Latitude, Math.Max(loc3.Latitude, loc4.Latitude)));
if (latLonBoundingBox)
{
uri = uri.
Replace("{w}", west.ToString(CultureInfo.InvariantCulture)).
Replace("{s}", south.ToString(CultureInfo.InvariantCulture)).
Replace("{e}", east.ToString(CultureInfo.InvariantCulture)).
Replace("{n}", north.ToString(CultureInfo.InvariantCulture));
}
else
{
var p1 = ParentMap.MapTransform.Transform(new Location(south, west));
var p2 = ParentMap.MapTransform.Transform(new Location(north, east));
var arc = TileSource.EarthRadius * Math.PI / 180d;
uri = uri.
Replace("{W}", (arc * p1.X).ToString(CultureInfo.InvariantCulture)).
Replace("{S}", (arc * p1.Y).ToString(CultureInfo.InvariantCulture)).
Replace("{E}", (arc * p2.X).ToString(CultureInfo.InvariantCulture)).
Replace("{N}", (arc * p2.Y).ToString(CultureInfo.InvariantCulture));
}
try
{
var buffer = webClient.DownloadData(uri);
var bitmap = new BitmapImage();
using (var stream = new MemoryStream(buffer))
{
bitmap.BeginInit();
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.StreamSource = stream;
bitmap.EndInit();
bitmap.Freeze();
}
Dispatcher.BeginInvoke((Action)(() =>
{
var image = (MapImage)Children[currentImageIndex];
image.BeginAnimation(Image.OpacityProperty,
new DoubleAnimation(0d, Tile.AnimationDuration)
{
BeginTime = Tile.AnimationDuration
});
currentImageIndex = (currentImageIndex + 1) % 2;
image = (MapImage)Children[currentImageIndex];
image.Source = null;
image.North = double.NaN; // avoid frequent MapRectangle.UpdateGeometry() calls
image.West = west;
image.East = east;
image.South = south;
image.North = north;
image.Source = bitmap;
image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation(1d, Tile.AnimationDuration));
if (!imageIsValid)
{
UpdateImage(this, EventArgs.Empty);
}
}));
}
catch (Exception ex)
{
Trace.TraceWarning("{0}: {1}", uri, ex.Message);
}
updateInProgress = false;
});
}
}
}

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
namespace MapControl

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Linq;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Linq;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
@ -13,11 +13,11 @@ using System.Windows.Media;
namespace MapControl
{
public partial class MapRectangle : MapShape
/// <summary>
/// Fills a rectangular area defined by South, North, West and East with a Brush.
/// </summary>
public class MapRectangle : MapShape
{
private static Transform DefaultFillRelativeTransform =
Brush.RelativeTransformProperty.GetMetadata(typeof(Brush)).DefaultValue as Transform;
public static readonly DependencyProperty SouthProperty = DependencyProperty.Register(
"South", typeof(double), typeof(MapRectangle),
new PropertyMetadata(double.NaN, (o, e) => ((MapRectangle)o).UpdateGeometry()));
@ -84,17 +84,5 @@ namespace MapControl
ClearValue(RenderTransformProperty);
}
}
//#if !NETFX_CORE && !SILVERLIGHT
// protected override void OnRender(DrawingContext drawingContext)
// {
// if (ParentMap != null)
// {
// drawingContext.PushTransform(ParentMap.ViewportTransform);
// drawingContext.DrawRectangle(Fill, null, ((RectangleGeometry)Geometry).Rect);
// drawingContext.Pop();
// }
// }
//#endif
}
}

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows.Media;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
@ -54,7 +54,7 @@ namespace MapControl
else
{
var lat = location.Latitude * Math.PI / 180d;
location.Y = (Math.Log(Math.Tan(lat) + 1d / Math.Cos(lat))) / Math.PI * 180d;
location.Y = Math.Log(Math.Tan(lat) + 1d / Math.Cos(lat)) / Math.PI * 180d;
}
}

View file

@ -3,19 +3,20 @@ using System.Runtime.InteropServices;
using System.Windows;
#if SILVERLIGHT
[assembly: AssemblyTitle("MapControl.Silverlight")]
[assembly: AssemblyDescription("XAML Map Control for Silverlight")]
[assembly: AssemblyTitle("Silverlight Map Control")]
[assembly: AssemblyDescription("XAML Map Control Library for Silverlight")]
#else
[assembly: AssemblyTitle("MapControl.WPF")]
[assembly: AssemblyDescription("XAML Map Control for WPF")]
[assembly: AssemblyTitle("WPF Map Control")]
[assembly: AssemblyDescription("XAML Map Control Library for WPF")]
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]
#endif
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyProduct("XAML Map Control")]
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.3.0")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.2.2")]
[assembly: AssemblyFileVersion("1.2.2")]
[assembly: ComVisible(false)]

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE
@ -42,7 +42,7 @@ namespace MapControl
}
else
{
BeginOpacityAnimation();
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation { To = 1d, Duration = AnimationDuration });
}
}
else
@ -59,7 +59,7 @@ namespace MapControl
{
((BitmapImage)sender).ImageOpened -= BitmapImageOpened;
((BitmapImage)sender).ImageFailed -= BitmapImageFailed;
BeginOpacityAnimation();
Image.BeginAnimation(Image.OpacityProperty, new DoubleAnimation { To = 1d, Duration = AnimationDuration });
}
private void BitmapImageFailed(object sender, ExceptionRoutedEventArgs e)
@ -68,16 +68,5 @@ namespace MapControl
((BitmapImage)sender).ImageFailed -= BitmapImageFailed;
Image.Source = null;
}
private void BeginOpacityAnimation()
{
Image.BeginAnimation(Image.OpacityProperty,
new DoubleAnimation
{
To = 1d,
Duration = AnimationDuration,
FillBehavior = FillBehavior.HoldEnd
});
}
}
}

View file

@ -1,12 +1,11 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace MapControl
{
@ -34,7 +33,7 @@ namespace MapControl
}
else
{
BeginOpacityAnimation();
Brush.BeginAnimation(ImageBrush.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
}
}
else
@ -51,7 +50,7 @@ namespace MapControl
{
((BitmapImage)sender).DownloadCompleted -= BitmapDownloadCompleted;
((BitmapImage)sender).DownloadFailed -= BitmapDownloadFailed;
BeginOpacityAnimation();
Brush.BeginAnimation(ImageBrush.OpacityProperty, new DoubleAnimation(1d, AnimationDuration));
}
private void BitmapDownloadFailed(object sender, ExceptionEventArgs e)
@ -60,16 +59,5 @@ namespace MapControl
((BitmapImage)sender).DownloadFailed -= BitmapDownloadFailed;
Brush.ImageSource = null;
}
private void BeginOpacityAnimation()
{
Brush.BeginAnimation(ImageBrush.OpacityProperty,
new DoubleAnimation
{
To = 1d,
Duration = AnimationDuration,
FillBehavior = FillBehavior.HoldEnd
});
}
}
}

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows.Media;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
@ -19,8 +19,11 @@ namespace MapControl
internal partial class TileContainer
{
private const double maxScaledTileSize = 400d; // scaled tile size 200..400 units
private static double zoomLevelSwitchOffset = Math.Log(maxScaledTileSize / 256d, 2d);
private static double zoomLevelSwitchOffset = Math.Log(maxScaledTileSize / TileSource.TileSize, 2d);
internal static TimeSpan UpdateInterval = TimeSpan.FromSeconds(0.5);
private readonly DispatcherTimer updateTimer;
private Size size;
private Point origin;
private Point offset;
@ -28,13 +31,12 @@ namespace MapControl
private double zoomLevel;
private int tileZoomLevel;
private Int32Rect tileGrid;
private readonly DispatcherTimer updateTimer;
public readonly MatrixTransform ViewportTransform = new MatrixTransform();
public TileContainer()
{
updateTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(0.5) };
updateTimer = new DispatcherTimer { Interval = UpdateInterval };
updateTimer.Tick += UpdateTiles;
}
@ -80,13 +82,13 @@ namespace MapControl
public double SetViewportTransform(double mapZoomLevel, double mapRotation, Point mapOrigin, Point viewportOrigin, Size viewportSize)
{
var scale = Math.Pow(2d, zoomLevel) * 256d / 360d;
var scale = Math.Pow(2d, zoomLevel) * TileSource.TileSize / 360d;
var oldMapOriginX = (origin.X - offset.X) / scale - 180d;
if (zoomLevel != mapZoomLevel)
{
zoomLevel = mapZoomLevel;
scale = Math.Pow(2d, zoomLevel) * 256d / 360d;
scale = Math.Pow(2d, zoomLevel) * TileSource.TileSize / 360d;
}
rotation = mapRotation;
@ -124,7 +126,7 @@ namespace MapControl
// with origin at tileGrid.X and tileGrid.Y to minimize rounding errors.
return GetTransformMatrix(
new Matrix(1d, 0d, 0d, 1d, tileGrid.X * 256d, tileGrid.Y * 256d),
new Matrix(1d, 0d, 0d, 1d, tileGrid.X * TileSource.TileSize, tileGrid.Y * TileSource.TileSize),
Math.Pow(2d, zoomLevel - tileZoomLevel));
}

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Collections.Generic;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
@ -121,7 +121,7 @@ namespace MapControl
(Action<Tile, ImageSource>)((t, i) => t.SetImageSource(i, true)),
DispatcherPriority.Background, tile, image);
var creationTime = BitConverter.ToInt64(buffer, 0);
long creationTime = BitConverter.ToInt64(buffer, 0);
if (DateTime.FromBinary(creationTime) + CacheUpdateAge < DateTime.UtcNow)
{
@ -268,11 +268,12 @@ namespace MapControl
using (var response = (HttpWebResponse)request.GetResponse())
using (var responseStream = response.GetResponseStream())
{
var creationTime = DateTime.UtcNow.ToBinary();
var length = (int)response.ContentLength;
using (var memoryStream = length > 0 ? new MemoryStream(length + sizeof(long)) : new MemoryStream())
{
long creationTime = DateTime.UtcNow.ToBinary();
memoryStream.Write(BitConverter.GetBytes(creationTime), 0, sizeof(long));
responseStream.CopyTo(memoryStream);

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
#if NETFX_CORE

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Windows;
@ -26,8 +26,11 @@ namespace MapControl
{
foreach (var tile in tiles)
{
var tileSize = 256 << (zoomLevel - tile.ZoomLevel);
var tileRect = new Rect(tileSize * tile.X - 256 * grid.X, tileSize * tile.Y - 256 * grid.Y, tileSize, tileSize);
var tileSize = TileSource.TileSize << (zoomLevel - tile.ZoomLevel);
var tileRect = new Rect(
tileSize * tile.X - TileSource.TileSize * grid.X,
tileSize * tile.Y - TileSource.TileSize * grid.Y,
tileSize, tileSize);
drawingContext.DrawRectangle(tile.Brush, null, tileRect);

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System.Collections.ObjectModel;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;
@ -18,6 +18,9 @@ namespace MapControl
/// </summary>
public partial class TileSource
{
public const int TileSize = 256;
public const double EarthRadius = 6378137d; // WGS 84 semi major axis
private Func<int, int, int, Uri> getUri;
private string uriFormat = string.Empty;
private int hostIndex = -1;
@ -31,6 +34,11 @@ namespace MapControl
UriFormat = uriFormat;
}
public virtual double MetersPerDegree
{
get { return EarthRadius * Math.PI / 180d; }
}
public string UriFormat
{
get { return uriFormat; }
@ -43,8 +51,6 @@ namespace MapControl
uriFormat = value;
getUri = GetDefaultUri;
if (uriFormat.Contains("{x}") && uriFormat.Contains("{y}") && uriFormat.Contains("{z}"))
{
if (uriFormat.Contains("{c}"))
@ -59,15 +65,23 @@ namespace MapControl
{
getUri = GetMapQuestUri;
}
else
{
getUri = GetBasicUri;
}
}
else if (uriFormat.Contains("{q}")) // {i} is optional
{
getUri = GetQuadKeyUri;
}
else if (uriFormat.Contains("{w}") && uriFormat.Contains("{s}") && uriFormat.Contains("{e}") && uriFormat.Contains("{n}"))
else if (uriFormat.Contains("{W}") && uriFormat.Contains("{S}") && uriFormat.Contains("{E}") && uriFormat.Contains("{N}"))
{
getUri = GetBoundingBoxUri;
}
else if (uriFormat.Contains("{w}") && uriFormat.Contains("{s}") && uriFormat.Contains("{e}") && uriFormat.Contains("{n}"))
{
getUri = GetLatLonBoundingBoxUri;
}
else if (uriFormat.Contains("{x}") && uriFormat.Contains("{v}") && uriFormat.Contains("{z}"))
{
getUri = GetTmsUri;
@ -80,7 +94,7 @@ namespace MapControl
return getUri != null ? getUri(x, y, zoomLevel) : null;
}
private Uri GetDefaultUri(int x, int y, int zoomLevel)
private Uri GetBasicUri(int x, int y, int zoomLevel)
{
return new Uri(UriFormat.
Replace("{x}", x.ToString()).
@ -147,12 +161,28 @@ namespace MapControl
private Uri GetBoundingBoxUri(int x, int y, int zoomLevel)
{
var t = new MercatorTransform();
var n = (double)(1 << zoomLevel);
var x1 = MetersPerDegree * ((double)x * 360d / n - 180d);
var x2 = MetersPerDegree * ((double)(x + 1) * 360d / n - 180d);
var y1 = MetersPerDegree * (180d - (double)(y + 1) * 360d / n);
var y2 = MetersPerDegree * (180d - (double)y * 360d / n);
return new Uri(UriFormat.
Replace("{W}", x1.ToString(CultureInfo.InvariantCulture)).
Replace("{S}", y1.ToString(CultureInfo.InvariantCulture)).
Replace("{E}", x2.ToString(CultureInfo.InvariantCulture)).
Replace("{N}", y2.ToString(CultureInfo.InvariantCulture)));
}
private Uri GetLatLonBoundingBoxUri(int x, int y, int zoomLevel)
{
var n = (double)(1 << zoomLevel);
var x1 = (double)x * 360d / n - 180d;
var x2 = (double)(x + 1) * 360d / n - 180d;
var y1 = 180d - (double)(y + 1) * 360d / n;
var y2 = 180d - (double)y * 360d / n;
var t = new MercatorTransform();
var p1 = t.Transform(new Point(x1, y1));
var p2 = t.Transform(new Point(x2, y2));

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using System;

View file

@ -1,5 +1,5 @@
// XAML Map Control - http://xamlmapcontrol.codeplex.com/
// Copyright © 2013 Clemens Fischer
// Copyright © Clemens Fischer 2012-2013
// Licensed under the Microsoft Public License (Ms-PL)
using Windows.Foundation;

View file

@ -45,9 +45,6 @@
<Compile Include="..\LocationCollection.cs">
<Link>LocationCollection.cs</Link>
</Compile>
<Compile Include="..\Map.cs">
<Link>Map.cs</Link>
</Compile>
<Compile Include="..\Map.WinRT.cs">
<Link>Map.WinRT.cs</Link>
</Compile>
@ -66,9 +63,6 @@
<Compile Include="..\MapImage.cs">
<Link>MapImage.cs</Link>
</Compile>
<Compile Include="..\MapImage.Silverlight.WinRT.cs">
<Link>MapImage.Silverlight.WinRT.cs</Link>
</Compile>
<Compile Include="..\MapItem.Silverlight.WinRT.cs">
<Link>MapItem.Silverlight.WinRT.cs</Link>
</Compile>

View file

@ -1,14 +1,15 @@
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: AssemblyTitle("MapControl.WinRT")]
[assembly: AssemblyDescription("XAML Map Control for Windows Runtime")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyTitle("WinRT Map Control")]
[assembly: AssemblyDescription("XAML Map Control Library for Windows Runtime")]
[assembly: AssemblyProduct("XAML Map Control")]
[assembly: AssemblyCopyright("Copyright © 2013 Clemens Fischer")]
[assembly: AssemblyCompany("Clemens Fischer")]
[assembly: AssemblyCopyright("Copyright © Clemens Fischer 2012-2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyVersion("1.3.0")]
[assembly: AssemblyFileVersion("1.3.0")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCulture("")]
[assembly: AssemblyVersion("1.2.2")]
[assembly: AssemblyFileVersion("1.2.2")]
[assembly: ComVisible(false)]