XAML-Map-Control/MapControl/TileSource.cs

173 lines
5.6 KiB
C#
Raw Normal View History

2012-05-04 12:52:20 +02:00
// WPF MapControl - http://wpfmapcontrol.codeplex.com/
// Copyright © 2012 Clemens Fischer
// Licensed under the Microsoft Public License (Ms-PL)
using System;
2012-04-25 22:02:53 +02:00
using System.ComponentModel;
using System.Globalization;
using System.Text;
using System.Windows;
namespace MapControl
{
2012-05-04 12:52:20 +02:00
/// <summary>
/// Provides the URI of a map tile.
2012-05-04 12:52:20 +02:00
/// </summary>
[TypeConverter(typeof(TileSourceConverter))]
2012-04-25 22:02:53 +02:00
public class TileSource
{
private Func<int, int, int, Uri> getUri;
private string uriFormat = string.Empty;
private int hostIndex = -1;
public TileSource()
{
}
public TileSource(string uriFormat)
{
UriFormat = uriFormat;
}
public string UriFormat
{
get { return uriFormat; }
set
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("The value of the UriFormat property must not be null or empty or white-space only.");
}
if (value.Contains("{x}") && value.Contains("{y}") && value.Contains("{z}"))
{
if (value.Contains("{c}"))
{
getUri = GetOpenStreetMapUri;
}
else if (value.Contains("{i}"))
{
getUri = GetGoogleMapsUri;
}
else if (value.Contains("{n}"))
{
getUri = GetMapQuestUri;
}
else
{
getUri = GetDefaultUri;
}
}
else if (value.Contains("{q}")) // {i} is optional
{
getUri = GetQuadKeyUri;
}
else if (value.Contains("{w}") && value.Contains("{s}") && value.Contains("{e}") && value.Contains("{n}"))
{
getUri = GetBoundingBoxUri;
}
else
{
throw new ArgumentException("The specified UriFormat is not supported.");
}
uriFormat = value;
}
}
2012-04-25 22:02:53 +02:00
public virtual Uri GetUri(int x, int y, int zoomLevel)
{
return getUri != null ? getUri(x, y, zoomLevel) : null;
}
private Uri GetDefaultUri(int x, int y, int zoomLevel)
2012-04-25 22:02:53 +02:00
{
return new Uri(UriFormat.
Replace("{x}", x.ToString()).
Replace("{y}", y.ToString()).
Replace("{z}", zoomLevel.ToString()));
}
private Uri GetOpenStreetMapUri(int x, int y, int zoomLevel)
2012-04-25 22:02:53 +02:00
{
hostIndex = (hostIndex + 1) % 3;
2012-04-25 22:02:53 +02:00
return new Uri(UriFormat.
Replace("{c}", "abc".Substring(hostIndex, 1)).
2012-04-25 22:02:53 +02:00
Replace("{x}", x.ToString()).
Replace("{y}", y.ToString()).
Replace("{z}", zoomLevel.ToString()));
}
private Uri GetGoogleMapsUri(int x, int y, int zoomLevel)
2012-04-25 22:02:53 +02:00
{
hostIndex = (hostIndex + 1) % 4;
return new Uri(UriFormat.
Replace("{i}", hostIndex.ToString()).
Replace("{x}", x.ToString()).
Replace("{y}", y.ToString()).
Replace("{z}", zoomLevel.ToString()));
}
private Uri GetMapQuestUri(int x, int y, int zoomLevel)
2012-04-25 22:02:53 +02:00
{
hostIndex = (hostIndex % 4) + 1;
2012-04-25 22:02:53 +02:00
return new Uri(UriFormat.
Replace("{n}", hostIndex.ToString()).
2012-04-25 22:02:53 +02:00
Replace("{x}", x.ToString()).
Replace("{y}", y.ToString()).
Replace("{z}", zoomLevel.ToString()));
}
private Uri GetQuadKeyUri(int x, int y, int zoomLevel)
2012-04-25 22:02:53 +02:00
{
StringBuilder key = new StringBuilder { Length = zoomLevel };
for (int z = zoomLevel - 1; z >= 0; z--, x /= 2, y /= 2)
{
key[z] = (char)('0' + 2 * (y % 2) + (x % 2));
}
return new Uri(UriFormat.
Replace("{i}", key.ToString(key.Length - 1, 1)).
Replace("{q}", key.ToString()));
}
private Uri GetBoundingBoxUri(int x, int y, int zoomLevel)
2012-04-25 22:02:53 +02:00
{
2012-05-04 12:52:20 +02:00
MercatorTransform t = new MercatorTransform();
2012-04-25 22:02:53 +02:00
double n = 1 << zoomLevel;
double x1 = (double)x * 360d / n - 180d;
double x2 = (double)(x + 1) * 360d / n - 180d;
double y1 = 180d - (double)(y + 1) * 360d / n;
double y2 = 180d - (double)y * 360d / n;
2012-05-04 12:52:20 +02:00
Location p1 = t.TransformBack(new Point(x1, y1));
Location p2 = t.TransformBack(new Point(x2, y2));
2012-04-25 22:02:53 +02:00
return new Uri(UriFormat.
2012-05-04 12:52:20 +02:00
Replace("{w}", p1.Longitude.ToString(CultureInfo.InvariantCulture)).
Replace("{s}", p1.Latitude.ToString(CultureInfo.InvariantCulture)).
Replace("{e}", p2.Longitude.ToString(CultureInfo.InvariantCulture)).
Replace("{n}", p2.Latitude.ToString(CultureInfo.InvariantCulture)));
2012-04-25 22:02:53 +02:00
}
}
/// <summary>
/// Converts from string to TileSource.
/// </summary>
public class TileSourceConverter : TypeConverter
2012-04-25 22:02:53 +02:00
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
2012-04-25 22:02:53 +02:00
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return new TileSource(value as string);
2012-04-25 22:02:53 +02:00
}
}
}