第11章 - 瓦片图层与地图服务
第11章:瓦片图层与地图服务
11.1 瓦片地图概述
11.1.1 瓦片金字塔结构
┌───┐
Level 0 │ 0 │ 1 个瓦片 (全球)
└───┘
┌───┬───┐
Level 1 │ 0 │ 1 │ 4 个瓦片
├───┼───┤
│ 2 │ 3 │
└───┴───┘
┌───┬───┬───┬───┐
│ 0 │ 1 │ 2 │ 3 │
Level 2 ├───┼───┼───┼───┤ 16 个瓦片
│ 4 │ 5 │ 6 │ 7 │
├───┼───┼───┼───┤
│...│...│...│...│
└───┴───┴───┴───┘
瓦片总数 = 4^n (n 为缩放级别)
11.1.2 瓦片编址方式
| 编址方式 | 描述 | URL 示例 |
|---|---|---|
| ZXY (OSM/Google) | z/x/y 格式 | /{z}/{x}/{y}.png |
| TMS | 翻转 Y 轴 | /{z}/{x}/{-y}.png |
| QuadKey (Bing) | 四叉树编码 | /{quadkey}.png |
11.2 OpenStreetMap 瓦片
11.2.1 基本使用
using Mapsui.Tiling;
// 创建 OSM 瓦片图层
var osmLayer = OpenStreetMap.CreateTileLayer();
map.Layers.Add(osmLayer);
11.2.2 自定义 OSM 服务器
// 使用自定义 OSM 服务器
var customOsmSource = new HttpTileSource(
new GlobalSphericalMercator(),
"https://your-osm-server/{z}/{x}/{y}.png",
name: "CustomOSM",
attribution: new Attribution("© OpenStreetMap contributors")
);
var customOsmLayer = new TileLayer(customOsmSource)
{
Name = "Custom OSM"
};
11.2.3 OSM 变体服务
public static class OsmVariants
{
// Humanitarian OSM
public static TileLayer CreateHotLayer()
{
return new TileLayer(new HttpTileSource(
new GlobalSphericalMercator(),
"https://tile-{s}.openstreetmap.fr/hot/{z}/{x}/{y}.png",
new[] { "a", "b", "c" },
name: "HOT"
));
}
// OpenTopoMap
public static TileLayer CreateOpenTopoLayer()
{
return new TileLayer(new HttpTileSource(
new GlobalSphericalMercator(),
"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
new[] { "a", "b", "c" },
name: "OpenTopoMap"
));
}
// Stamen Terrain
public static TileLayer CreateStamenTerrainLayer()
{
return new TileLayer(new HttpTileSource(
new GlobalSphericalMercator(),
"http://tile.stamen.com/terrain/{z}/{x}/{y}.png",
name: "Stamen Terrain"
));
}
}
11.3 自定义瓦片源
11.3.1 HttpTileSource
using BruTile;
using BruTile.Web;
// 创建自定义 HTTP 瓦片源
var tileSource = new HttpTileSource(
new GlobalSphericalMercator(minZoomLevel: 0, maxZoomLevel: 18),
"https://tiles.example.com/{z}/{x}/{y}.png",
name: "CustomTiles",
attribution: new Attribution("© Custom Provider")
);
var tileLayer = new TileLayer(tileSource)
{
Name = "Custom Tiles"
};
11.3.2 带请求头的瓦片源
// 自定义请求配置
var httpTileSource = new HttpTileSource(
new GlobalSphericalMercator(),
"https://api.example.com/tiles/{z}/{x}/{y}.png",
configureHttpRequestMessage: message =>
{
message.Headers.Add("Authorization", "Bearer your-token");
message.Headers.Add("Referer", "https://your-app.com");
}
);
11.3.3 天地图服务
public static class TiandituLayers
{
private const string Token = "YOUR_TIANDITU_TOKEN";
// 矢量底图
public static TileLayer CreateVectorLayer()
{
var url = $"http://t{{s}}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={{x}}&TILEROW={{y}}&TILEMATRIX={{z}}&tk={Token}";
return new TileLayer(new HttpTileSource(
new GlobalSphericalMercator(),
url,
new[] { "0", "1", "2", "3", "4", "5", "6", "7" },
name: "天地图矢量"
));
}
// 矢量注记
public static TileLayer CreateVectorAnnotationLayer()
{
var url = $"http://t{{s}}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={{x}}&TILEROW={{y}}&TILEMATRIX={{z}}&tk={Token}";
return new TileLayer(new HttpTileSource(
new GlobalSphericalMercator(),
url,
new[] { "0", "1", "2", "3", "4", "5", "6", "7" },
name: "天地图注记"
));
}
// 影像底图
public static TileLayer CreateImageryLayer()
{
var url = $"http://t{{s}}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={{x}}&TILEROW={{y}}&TILEMATRIX={{z}}&tk={Token}";
return new TileLayer(new HttpTileSource(
new GlobalSphericalMercator(),
url,
new[] { "0", "1", "2", "3", "4", "5", "6", "7" },
name: "天地图影像"
));
}
}
11.4 离线瓦片 (MBTiles)
11.4.1 使用 MBTiles 文件
using BruTile.MbTiles;
using SQLite;
// 从 MBTiles 文件创建瓦片源
var mbtilesPath = "maps/offline.mbtiles";
var mbTilesTileSource = new MbTilesTileSource(
new SQLiteConnectionString(mbtilesPath, false)
);
var offlineLayer = new TileLayer(mbTilesTileSource)
{
Name = "Offline Map"
};
map.Layers.Add(offlineLayer);
11.4.2 MBTiles 信息查询
public class MbTilesInfo
{
public static void PrintInfo(string mbtilesPath)
{
using var connection = new SQLiteConnection(mbtilesPath);
// 查询元数据
var metadata = connection.Query<MbTilesMetadata>(
"SELECT name, value FROM metadata"
);
Console.WriteLine("MBTiles Metadata:");
foreach (var item in metadata)
{
Console.WriteLine($" {item.Name}: {item.Value}");
}
// 查询瓦片数量
var count = connection.ExecuteScalar<int>(
"SELECT COUNT(*) FROM tiles"
);
Console.WriteLine($"Total tiles: {count}");
// 查询缩放级别范围
var minZoom = connection.ExecuteScalar<int>(
"SELECT MIN(zoom_level) FROM tiles"
);
var maxZoom = connection.ExecuteScalar<int>(
"SELECT MAX(zoom_level) FROM tiles"
);
Console.WriteLine($"Zoom levels: {minZoom} - {maxZoom}");
}
private class MbTilesMetadata
{
public string Name { get; set; }
public string Value { get; set; }
}
}
11.4.3 瓦片缓存
// 创建带文件缓存的瓦片源
var cacheDir = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"MapsuiCache"
);
var cachedTileSource = new HttpTileSource(
new GlobalSphericalMercator(),
"https://tile.openstreetmap.org/{z}/{x}/{y}.png",
name: "CachedOSM",
persistentCache: new FileCache(cacheDir, "png")
);
var cachedLayer = new TileLayer(cachedTileSource)
{
Name = "Cached OSM"
};
11.5 WMS 服务
11.5.1 基本 WMS 图层
using Mapsui.Providers.Wms;
// 创建 WMS 提供者
var wmsUrl = "https://example.com/wms";
var wmsProvider = new WmsProvider(new Uri(wmsUrl));
wmsProvider.LayerNames = new[] { "roads", "buildings" };
wmsProvider.CRS = "EPSG:3857";
wmsProvider.Version = "1.3.0";
wmsProvider.ImageFormat = "image/png";
// 创建 WMS 图层
var wmsLayer = new ImageLayer
{
Name = "WMS Layer",
DataSource = wmsProvider
};
map.Layers.Add(wmsLayer);
11.5.2 WMS GetCapabilities
public static async Task<WmsCapabilities> GetWmsCapabilitiesAsync(string wmsUrl)
{
using var client = new HttpClient();
var capabilitiesUrl = $"{wmsUrl}?SERVICE=WMS&REQUEST=GetCapabilities";
var xml = await client.GetStringAsync(capabilitiesUrl);
return ParseWmsCapabilities(xml);
}
public class WmsCapabilities
{
public string Title { get; set; }
public List<WmsLayer> Layers { get; set; }
public List<string> SupportedCrs { get; set; }
public List<string> SupportedFormats { get; set; }
}
11.6 WMTS 服务
11.6.1 使用 WMTS
using BruTile.Wmts;
// 从 WMTS Capabilities 创建瓦片源
var wmtsUrl = "https://example.com/wmts/1.0.0/WMTSCapabilities.xml";
var wmtsTileSource = await CreateWmtsTileSourceAsync(
wmtsUrl,
"layerIdentifier"
);
var wmtsLayer = new TileLayer(wmtsTileSource)
{
Name = "WMTS Layer"
};
private static async Task<ITileSource> CreateWmtsTileSourceAsync(
string capabilitiesUrl,
string layerIdentifier)
{
using var client = new HttpClient();
using var stream = await client.GetStreamAsync(capabilitiesUrl);
var tileSources = WmtsParser.Parse(stream);
return tileSources.First(ts =>
ts.Name.Equals(layerIdentifier, StringComparison.OrdinalIgnoreCase)
);
}
11.7 ArcGIS 服务
11.7.1 ArcGIS REST 服务
using Mapsui.ArcGIS;
// ArcGIS 动态地图服务
var dynamicServiceUrl = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer";
var dynamicProvider = new ArcGISDynamicProvider(new Uri(dynamicServiceUrl));
var dynamicLayer = new ImageLayer
{
Name = "ArcGIS Dynamic",
DataSource = dynamicProvider
};
// ArcGIS 瓦片服务
var tileServiceUrl = "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer";
var tileLayer = CreateArcGisTileLayer(tileServiceUrl, "World Imagery");
private static TileLayer CreateArcGisTileLayer(string url, string name)
{
var tileSource = new ArcGISTileSource(
url,
new GlobalSphericalMercator()
);
return new TileLayer(tileSource) { Name = name };
}
11.7.2 Esri 底图服务
public static class EsriBasemaps
{
private const string BaseUrl = "https://services.arcgisonline.com/ArcGIS/rest/services";
public static TileLayer CreateStreetMap() =>
CreateEsriLayer($"{BaseUrl}/World_Street_Map/MapServer", "Esri Street");
public static TileLayer CreateTopographic() =>
CreateEsriLayer($"{BaseUrl}/World_Topo_Map/MapServer", "Esri Topo");
public static TileLayer CreateImagery() =>
CreateEsriLayer($"{BaseUrl}/World_Imagery/MapServer", "Esri Imagery");
public static TileLayer CreateOceans() =>
CreateEsriLayer($"{BaseUrl}/Ocean_Basemap/MapServer", "Esri Oceans");
public static TileLayer CreateGray() =>
CreateEsriLayer($"{BaseUrl}/Canvas/World_Light_Gray_Base/MapServer", "Esri Gray");
private static TileLayer CreateEsriLayer(string url, string name)
{
// 使用标准 XYZ 格式的 Esri 服务
var tileUrl = $"{url}/tile/{{z}}/{{y}}/{{x}}";
var tileSource = new HttpTileSource(
new GlobalSphericalMercator(),
tileUrl,
name: name
);
return new TileLayer(tileSource) { Name = name };
}
}
11.8 底图切换
11.8.1 底图管理器
public class BasemapManager
{
private readonly Map _map;
private readonly Dictionary<string, Func<ILayer>> _basemapFactories;
private string _currentBasemap;
public BasemapManager(Map map)
{
_map = map;
_basemapFactories = new Dictionary<string, Func<ILayer>>
{
["OSM"] = () => OpenStreetMap.CreateTileLayer(),
["Esri Street"] = () => EsriBasemaps.CreateStreetMap(),
["Esri Imagery"] = () => EsriBasemaps.CreateImagery(),
["Esri Topo"] = () => EsriBasemaps.CreateTopographic(),
["天地图矢量"] = () => TiandituLayers.CreateVectorLayer(),
["天地图影像"] = () => TiandituLayers.CreateImageryLayer()
};
}
public IEnumerable<string> AvailableBasemaps => _basemapFactories.Keys;
public string CurrentBasemap => _currentBasemap;
public void SetBasemap(string basemapName)
{
if (!_basemapFactories.ContainsKey(basemapName))
throw new ArgumentException($"Unknown basemap: {basemapName}");
// 移除现有底图
var existingBasemap = _map.Layers.FirstOrDefault(l => l.Name == "Basemap");
if (existingBasemap != null)
_map.Layers.Remove(existingBasemap);
// 添加新底图
var newBasemap = _basemapFactories[basemapName]();
newBasemap.Name = "Basemap";
_map.Layers.Insert(0, newBasemap);
_currentBasemap = basemapName;
}
}
11.9 本章小结
本章详细介绍了 Mapsui 的瓦片图层与地图服务:
- 瓦片地图概述:金字塔结构和编址方式
- OpenStreetMap 瓦片:基本使用和变体服务
- 自定义瓦片源:HttpTileSource 和天地图
- 离线瓦片:MBTiles 文件和瓦片缓存
- WMS 服务:Web Map Service 的使用
- WMTS 服务:Web Map Tile Service 的使用
- ArcGIS 服务:动态服务和瓦片服务
- 底图切换:底图管理器实现
在下一章中,我们将学习 NTS 几何处理集成。
11.10 思考与练习
- 实现一个支持多种底图切换的控件。
- 创建一个瓦片下载工具,将在线瓦片保存为 MBTiles。
- 实现 WMS GetFeatureInfo 功能,获取要素属性。
- 创建一个混合图层,叠加影像底图和矢量注记。
- 实现瓦片预加载功能,提前加载相邻区域的瓦片。

浙公网安备 33010602011771号