在WPF上的Bing地图中加载自定义图块

Seb*_*Seb 2 .net wpf bing-maps

我正在尝试使用Bing地图的自定义tileset.我想要做的是类似于这里的问题,但我试图理解如何格式化URI,以便我可以在应用程序中托管切片.我试图在本地托管这个的原因是因为我想尽可能地限制网络流量从我的应用程序中流出.

是否有关于在本地托管地图图块的任何教程,或者有关如何使URI指向本地存储路径的更深入的教程?

提前感谢任何建议.

Cle*_*ens 22

Bing Maps(或Google Maps或OpenStreetMap)平铺地图方案的中心点是每个地图图块由三个参数标识.这些是缩放级别(通常范围从0或1到大约20)以及缩放级别内的图块的x和y索引.在给定的缩放级别z中,x和y索引的范围从0到2 ^ z-1.在缩放级别0中有一个图块,在级别1中有2x2图块,在级别2中有4x4图块,依此类推.

大多数地图图块提供程序(如OpenStreetMap或Google Maps)直接在其图块URI中反映这三个参数.例如,OpenStreetMap通过URI http://tile.openstreetmap.org/z/x/y.png提供地图图块.

在派生的TileSource类中,您重写GetUri方法以为三个tile参数提供URI.对于OpenStreetMap,类似派生的TileSource可能如下所示:

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()));
    }
}
Run Code Online (Sandbox Code Playgroud)

对于Bing Maps WPF Control TileLayer类中的一些愚蠢的技术细节,您还必须派生自己的TileLayer类以在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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,您将在地图控件中使用它,如下所示,XAML名称空间m引用Microsoft.Maps.MapControl.WPFlocal引用包含派生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>
Run Code Online (Sandbox Code Playgroud)

您现在也可以为本地文件创建URI,而不是创建http URI.例如,您可以在目录结构中组织地图图块,其中包含缩放级别的目录,x索引的子目录和y索引的文件名.您可以UriFormat以指定本地路径的方式设置属性:

<local:MyTileLayer UriFormat="file:///C:/Tiles/{z}/{x}/{y}.png"/>
Run Code Online (Sandbox Code Playgroud)

重写的GetUri方法也可以直接创建适当的本地文件URI,而不使用该UriFormat属性:

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);
}
Run Code Online (Sandbox Code Playgroud)

您可能想要了解有关OpenStreetMap如何处理地图图块名称的更多信息.