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>
|
|
|
|
|
|
/// Defines the URI of a map tile.
|
|
|
|
|
|
/// </summary>
|
2012-04-25 22:02:53 +02:00
|
|
|
|
[TypeConverter(typeof(TileSourceTypeConverter))]
|
|
|
|
|
|
public class TileSource
|
|
|
|
|
|
{
|
|
|
|
|
|
public string UriFormat { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
public virtual Uri GetUri(int x, int y, int zoomLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
return new Uri(UriFormat.
|
|
|
|
|
|
Replace("{x}", x.ToString()).
|
|
|
|
|
|
Replace("{y}", y.ToString()).
|
|
|
|
|
|
Replace("{z}", zoomLevel.ToString()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class OpenStreetMapTileSource : TileSource
|
|
|
|
|
|
{
|
|
|
|
|
|
private static string[] hostChars = { "a", "b", "c" };
|
|
|
|
|
|
private int hostChar = -1;
|
|
|
|
|
|
|
|
|
|
|
|
public override Uri GetUri(int x, int y, int zoomLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
hostChar = (hostChar + 1) % 3;
|
|
|
|
|
|
|
|
|
|
|
|
return new Uri(UriFormat.
|
|
|
|
|
|
Replace("{c}", hostChars[hostChar]).
|
|
|
|
|
|
Replace("{x}", x.ToString()).
|
|
|
|
|
|
Replace("{y}", y.ToString()).
|
|
|
|
|
|
Replace("{z}", zoomLevel.ToString()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class GoogleMapsTileSource : TileSource
|
|
|
|
|
|
{
|
|
|
|
|
|
private int hostIndex = -1;
|
|
|
|
|
|
|
|
|
|
|
|
public override Uri GetUri(int x, int y, int zoomLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
hostIndex = (hostIndex + 1) % 4;
|
|
|
|
|
|
|
|
|
|
|
|
return new Uri(UriFormat.
|
|
|
|
|
|
Replace("{i}", hostIndex.ToString()).
|
|
|
|
|
|
Replace("{x}", x.ToString()).
|
|
|
|
|
|
Replace("{y}", y.ToString()).
|
|
|
|
|
|
Replace("{z}", zoomLevel.ToString()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class MapQuestTileSource : TileSource
|
|
|
|
|
|
{
|
|
|
|
|
|
private int hostNumber;
|
|
|
|
|
|
|
|
|
|
|
|
public override Uri GetUri(int x, int y, int zoomLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
hostNumber = (hostNumber % 4) + 1;
|
|
|
|
|
|
|
|
|
|
|
|
return new Uri(UriFormat.
|
|
|
|
|
|
Replace("{n}", hostNumber.ToString()).
|
|
|
|
|
|
Replace("{x}", x.ToString()).
|
|
|
|
|
|
Replace("{y}", y.ToString()).
|
|
|
|
|
|
Replace("{z}", zoomLevel.ToString()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class QuadKeyTileSource : TileSource
|
|
|
|
|
|
{
|
|
|
|
|
|
public override Uri GetUri(int x, int y, int zoomLevel)
|
|
|
|
|
|
{
|
|
|
|
|
|
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()));
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class BoundingBoxTileSource : TileSource
|
|
|
|
|
|
{
|
|
|
|
|
|
public override Uri GetUri(int x, int y, int zoomLevel)
|
|
|
|
|
|
{
|
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
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public class TileSourceTypeConverter : TypeConverter
|
|
|
|
|
|
{
|
|
|
|
|
|
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
|
|
|
|
|
{
|
|
|
|
|
|
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
|
|
|
|
|
{
|
|
|
|
|
|
string uriFormat = value as string;
|
|
|
|
|
|
|
|
|
|
|
|
if (uriFormat != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
TileSource tileSource = null;
|
|
|
|
|
|
|
|
|
|
|
|
if (uriFormat.Contains("{x}") && uriFormat.Contains("{y}") && uriFormat.Contains("{z}"))
|
|
|
|
|
|
{
|
|
|
|
|
|
if (uriFormat.Contains("{c}"))
|
|
|
|
|
|
{
|
|
|
|
|
|
tileSource = new OpenStreetMapTileSource();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (uriFormat.Contains("{i}"))
|
|
|
|
|
|
{
|
|
|
|
|
|
tileSource = new GoogleMapsTileSource();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (uriFormat.Contains("{n}"))
|
|
|
|
|
|
{
|
|
|
|
|
|
tileSource = new MapQuestTileSource();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
tileSource = new TileSource();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (uriFormat.Contains("{q}"))
|
|
|
|
|
|
{
|
|
|
|
|
|
tileSource = new QuadKeyTileSource();
|
|
|
|
|
|
}
|
|
|
|
|
|
else if (uriFormat.Contains("{w}") && uriFormat.Contains("{s}") && uriFormat.Contains("{e}") && uriFormat.Contains("{n}"))
|
|
|
|
|
|
{
|
|
|
|
|
|
tileSource = new BoundingBoxTileSource();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (tileSource != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
tileSource.UriFormat = uriFormat;
|
|
|
|
|
|
return tileSource;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return base.ConvertFrom(context, culture, value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|