在使用Google Map, Microsoft Map 等在线地图时,常常想知道这些地图在服务器上是如何存放的,目前大部分地图服务器都是将地图以图片存储以提高响应速度。 一般大小为256X256个像素。
如果知道每个图片的URL,自己写个地图下载软件并不困难。从而做成离线地图。
下面程序片段给出了常用地图服务器上地图图片存取的URL计算方法。
using System.Collections.Generic; using System.Text; namespace MapTileURL { class Program { private static Dictionary<string, string> MapTypeURLs = new Dictionary<string, string> { { "GoogleSatURL", "<a href="http://khm{GOOG_DIGIT}.google.com/kh/v=58&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://khm{GOOG_DIGIT}.google.com/kh/v=58&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" }, { "GoogleMapURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=m@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=m@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" }, { "GoogleHybURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=h@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=h@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" }, { "GoogleTerURL", "<a href="http://mt{GOOG_DIGIT}.google.com/vt/lyrs=t@108,r@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.com/vt/lyrs=t@108,r@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" }, { "GoogleChinaURL", "<a href="http://mt{GOOG_DIGIT}.google.cn/vt/lyrs=m@121&hl=en&gl=cn&x={X}&y={Y}&z={ZOOM}&s={GALILEO">http://mt{GOOG_DIGIT}.google.cn/vt/lyrs=m@121&hl=en&gl=cn&x={X}&y={Y}&z={ZOOM}&s={GALILEO</a>}" }, { "YahooMapURL", "<a href="http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" }, { "YahooSatURL", "<a href="http://maps{Y_DIGIT}.yimg.com/ae/ximg?v=1.9&t=a&s=256&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/ae/ximg?v=1.9&t=a&s=256&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" }, { "YahooInMapURL", "<a href="http://maps.yimg.com/hw/tile?locale=en&imgtype=png&yimgv=1.2&v=4.1&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2">http://maps.yimg.com/hw/tile?locale=en&imgtype=png&yimgv=1.2&v=4.1&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2</a>}" }, { "YahooInHybURL", "<a href="http://maps.yimg.com/hw/tile?imgtype=png&yimgv=0.95&t=h&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2">http://maps.yimg.com/hw/tile?imgtype=png&yimgv=0.95&t=h&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2</a>}" }, { "YahooHybURL", "<a href="http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&t=h&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1">http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&t=h&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1</a>" }, { "MicrosoftBrMapURL", "<a href="http://imakm{MS_DIGITBR}.maplink3.com.br/maps.ashx?v={QUAD}|t&call=2.2.4">http://imakm{MS_DIGITBR}.maplink3.com.br/maps.ashx?v={QUAD}|t&call=2.2.4</a>" }, { "MicrosoftHybURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/h{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/h{QUAD}.png?g=441&mkt=en-us&n=z</a>" }, { "MicrosoftSatURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/a{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/a{QUAD}.png?g=441&mkt=en-us&n=z</a>" }, { "MicrosoftMapURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&n=z</a>" }, { "MicrosoftTerURL", "<a href="http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&shading=hill&n=z">http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&shading=hill&n=z</a>" }, { "OpenStreetMapURL", "<a href="http://tile.openstreetmap.org/{ZOOM}/{X}/{Y}.png">http://tile.openstreetmap.org/{ZOOM}/{X}/{Y}.png</a>" }, { "OSMARenderURL", "<a href="http://tah.openstreetmap.org/Tiles/tile/{ZOOM}/{X}/{Y}.png">http://tah.openstreetmap.org/Tiles/tile/{ZOOM}/{X}/{Y}.png</a>" }, { "OpenAerialMapURL", "<a href="http://tile.openaerialmap.org/tiles/?v=mgm&layer=openaerialmap-900913&x={X}&y={Y}&zoom={OAM_ZOOM">http://tile.openaerialmap.org/tiles/?v=mgm&layer=openaerialmap-900913&x={X}&y={Y}&zoom={OAM_ZOOM</a>}" }, { "OpenCycleMapURL", "<a href="http://andy.sandbox.cloudmade.com/tiles/cycle/{ZOOM}/{X}/{Y}.png">http://andy.sandbox.cloudmade.com/tiles/cycle/{ZOOM}/{X}/{Y}.png</a>" } }; readonly static char[] Lookup = new[] { 'q', 't', 'r', 's' }; public static string GetQuadtreeFromXYZoom(int x, int y, int zoom) { var quad = new StringBuilder(); for (int i = 0; i < zoom; i++) { int rx = x % 2; int ry = y % 2; x /= 2; y /= 2; quad.Insert(0, Lookup[rx * 2 + ry]); } quad.Insert(0, 't'); return quad.ToString(); } public static string BuildUrl(string tileType, int x,int y,int zoom) { string url = ""; // Edited by Shustrik - compacted the switch statement switch (tileType) { case "GoogleSat": case "GoogleSatH": url = MapTypeURLs["GoogleSatURL"]; break; case "GoogleMap": url = MapTypeURLs["GoogleMapURL"]; break; case "GoogleHyb": url = MapTypeURLs["GoogleHybURL"]; break; case "GoogleTer": url = MapTypeURLs["GoogleTerURL"]; break; case "GoogleChina": url = MapTypeURLs["GoogleChinaURL"]; break; case "MicrosoftMap": url = MapTypeURLs["MicrosoftMapURL"]; break; case "MicrosoftSat": url = MapTypeURLs["MicrosoftSatURL"]; break; case "MicrosoftHyb": url = MapTypeURLs["MicrosoftHybURL"]; break; case "MicrosoftTer": url = MapTypeURLs["MicrosoftTerURL"]; break; case "MicrosoftBrMap": if (zoom <= 10) url = MapTypeURLs["MicrosoftMapURL"]; else url = MapTypeURLs["MicrosoftBrMapURL"]; break; case "YahooMap": url = MapTypeURLs["YahooMapURL"]; break; case "YahooSat": case "YahooSatH": case "YahooSatH2": url = MapTypeURLs["YahooSatURL"]; break; case "YahooHyb": url = MapTypeURLs["YahooHybURL"]; break; case "YahooInMap": url = MapTypeURLs["YahooInMapURL"]; break; case "YahooInHyb": url = MapTypeURLs["YahooInHybURL"]; break; case "OpenStreetMap": url = MapTypeURLs["OpenStreetMapURL"]; break; case "OSMARender": url = MapTypeURLs["OSMARenderURL"]; break; case "OpenAerialMap": url = MapTypeURLs["OpenAerialMapURL"]; break; case "OpenCycleMap": url = MapTypeURLs["OpenCycleMapURL"]; break; } // Edited by Shustrik - added variables for configuration settings other than Google string quadcode = ""; for (int i = (int)zoom - 1; i >= 0; i--) quadcode = quadcode + (((((y >> i) & 1) << 1) + ((x >> i) & 1))); url = url.Replace("{X}", x.ToString()); url = url.Replace("{Y}", y.ToString()); url = url.Replace("{Z}", ((int)zoom).ToString()); url = url.Replace("{ZOOM}", ((int)zoom).ToString()); url = url.Replace("{QUAD}", quadcode); url = url.Replace("{YAHOO_Y}", (((1 << ((int)zoom)) >> 1) - 1 - y).ToString()); url = url.Replace("{YAHOO_ZOOM}", ((int)zoom + 1).ToString()); url = url.Replace("{YAHOO_ZOOM_2}", (17 - (int)zoom + 1).ToString()); url = url.Replace("{OAM_ZOOM}", (17 - (int)zoom).ToString()); url = url.Replace("{GOOG_DIGIT}", ((x + y) & 3).ToString()); url = url.Replace("{GOOG_QUAD}", GetQuadtreeFromXYZoom(x, y, zoom)); url = url.Replace("{MS_DIGITBR}", ((((y & 1) << 1) + (x & 1)) + 1).ToString()); url = url.Replace("{MS_DIGIT}", ((((y & 3) << 1) + (x & 1))).ToString()); url = url.Replace("{Y_DIGIT}", ((x + y + zoom) % 3 +1).ToString()); url = url.Replace("{GALILEO}", "Galileo".Substring(0, ((3 * x + y) & 7))); // support old style {} vars url = url.Replace("QQQQ", GetQuadtreeFromXYZoom(x,y,zoom)); url = url.Replace("XXXX", x.ToString()); url = url.Replace("YYYY", y.ToString()); url = url.Replace("ZZZZ", (17 - (int)zoom).ToString()); url = url.Replace("{OSM_ZOOM}", ((int)zoom).ToString()); url = url.Replace("{MS_QUADCODE}", quadcode); url = url.Replace("*", ((x+y+zoom) %4).ToString()); return url; } static void Main(string[] args) { string url = BuildUrl("GoogleMap", 1, 1, 1); //return <a href="http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali">http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali</a> } } }
例子中取出 google map ,在 zoom=1 及 x=1,y=1是的图片。
http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali
下载工具 http://www.mapdigit.com/forum/viewthread.php?tid=43&extra=page%3D1 中文说明参见离线地图生成工具结构图和离线地图生成工具使用方法