Load custom tiles in Bing maps on WPF

与世无争的帅哥 提交于 2019-11-28 07:53:20

The central point in the Bing Maps (or Google Maps or OpenStreetMap) tiled map scheme is that each map tile is identified by three parameters. These are the zoom level (that typically ranges from 0 or 1 to about 20) and the x and y index of a tile within a zoom level. In a given zoom level z the x and y index range from 0 to 2^z-1. In zoom level 0 there is one tile, in level 1 there are 2x2 tile, in level 2 there are 4x4 tiles and so on.

Most map tile providers like OpenStreetMap or Google Maps directly reflect these three parameters in their tile URIs. OpenStreetMap for example provides map tiles by the URI http://tile.openstreetmap.org/z/x/y.png.

In a derived TileSource class you override the GetUri method to provide an URI for the three tile parameters. For OpenStreetMap alike tiles such a derived TileSource might look like this:

public class MyTileSource : Microsoft.Maps.MapControl.WPF.TileSource
{
    public override Uri GetUri(int x, int y, int zoomLevel)
    {
        return new Uri(UriFormat.
                       Replace("{x}", x.ToString()).
                       Replace("{y}", y.ToString()).
                       Replace("{z}", zoomLevel.ToString()));
    }
}

For some stupid technical detail in the Bing Maps WPF Control TileLayer class you would also have to derive your own TileLayer class to enable usage in XAML:

public class MyTileLayer : Microsoft.Maps.MapControl.WPF.MapTileLayer
{
    public MyTileLayer()
    {
        TileSource = new MyTileSource();
    }

    public string UriFormat
    {
        get { return TileSource.UriFormat; }
        set { TileSource.UriFormat = value; }
    }
}

You would then use it in the Map Control like below where the XAML namespace m references Microsoft.Maps.MapControl.WPF and local references the namespace that contains the derived TileLayer.

<m:Map>
    <m:Map.Mode>
        <!-- set empty map mode, i.e. remove default map layer -->
        <m:MercatorMode/>
    </m:Map.Mode>
    <local:MyTileLayer UriFormat="http://tile.openstreetmap.org/{z}/{x}/{y}.png"/>
</m:Map>

Instead of creating a http URI you might now also create an URI for a local file. You could for example organize the map tiles in a directory structure with a directory for the zoom level, a subdirectory for the x index and a file name for the y index. You could set the UriFormat property in a way that specifies a local path:

<local:MyTileLayer UriFormat="file:///C:/Tiles/{z}/{x}/{y}.png"/>

The overridden GetUri method might also directly create an appropriate local file URI, without using the UriFormat property:

public override Uri GetUri(int x, int y, int zoomLevel)
{
    string rootDir = ...
    string path = Path.Combine(rootDir, zoomLevel.ToString(), x.ToString(), y.ToString());
    return new Uri(path);
}

You may want to read more about how OpenStreetMap handles map tile names.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!