FreeOZ论坛
标题:
Google等离线地图下载方法解析
[打印本页]
作者:
trisun
时间:
23-6-2010 15:03
标题:
Google等离线地图下载方法解析
在使用Google Map, Microsoft Map 等在线地图时,常常想知道这些地图在服务器上是如何存放的,目前大部分地图服务器都是将地图以图片存储以提高响应速度。 一般大小为256X256个像素。
地图分片原理
http://msdn.microsoft.com/en-us/library/bb259689.aspx
如果知道每个图片的URL,自己写个地图下载软件并不困难。从而做成离线地图。
下面程序片段给出了常用地图服务器上地图图片存取的URL计算方法。
using System.Collections.Generic;
using System.Text;
namespace MapTileURL
{
class Program
{
private static Dictionary<string, string> MapTypeURLs = new Dictionary<string, string>
{
{ "GoogleSatURL", "http://khm{GOOG_DIGIT}.google.com/kh/v=58&x={X}&y={Y}&z={ZOOM}&s={GALILEO}" },
{ "GoogleMapURL", "http://mt{GOOG_DIGIT}.google.com/vt/lyrs=m@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO}" },
{ "GoogleHybURL", "http://mt{GOOG_DIGIT}.google.com/vt/lyrs=h@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO}" },
{ "GoogleTerURL", "http://mt{GOOG_DIGIT}.google.com/vt/lyrs=t@108,r@121&hl=en&x={X}&y={Y}&z={ZOOM}&s={GALILEO}" },
{ "GoogleChinaURL", "http://mt{GOOG_DIGIT}.google.cn/vt/lyrs=m@121&hl=en&gl=cn&x={X}&y={Y}&z={ZOOM}&s={GALILEO}" },
{ "YahooMapURL", "http://maps{Y_DIGIT}.yimg.com/hx/tl?v=4.3&.intl=en&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM}&r=1" },
{ "YahooSatURL", "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" },
{ "YahooInMapURL", "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}" },
{ "YahooInHybURL", "http://maps.yimg.com/hw/tile?imgtype=png&yimgv=0.95&t=h&x={X}&y={YAHOO_Y}&z={YAHOO_ZOOM_2}" },
{ "YahooHybURL", "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" },
{ "MicrosoftBrMapURL", "http://imakm{MS_DIGITBR}.maplink3.com.br/maps.ashx?v={QUAD}|t&call=2.2.4" },
{ "MicrosoftHybURL", "http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/h{QUAD}.png?g=441&mkt=en-us&n=z" },
{ "MicrosoftSatURL", "http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/a{QUAD}.png?g=441&mkt=en-us&n=z" },
{ "MicrosoftMapURL", "http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&n=z" },
{ "MicrosoftTerURL", "http://ecn.t{MS_DIGIT}.tiles.virtualearth.net/tiles/r{QUAD}.png?g=441&mkt=en-us&shading=hill&n=z" },
{ "OpenStreetMapURL", "http://tile.openstreetmap.org/{ZOOM}/{X}/{Y}.png" },
{ "OSMARenderURL", "http://tah.openstreetmap.org/Tiles/tile/{ZOOM}/{X}/{Y}.png" },
{ "OpenAerialMapURL", "http://tile.openaerialmap.org/tiles/?v=mgm&layer=openaerialmap-900913&x={X}&y={Y}&zoom={OAM_ZOOM}" },
{ "OpenCycleMapURL", "http://andy.sandbox.cloudmade.com/tiles/cycle/{ZOOM}/{X}/{Y}.png" }
};
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 = "";
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;
}
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 http://mt2.google.com/vt/lyrs=m@121&hl=en&x=1&y=1&z=1&s=Gali
}
}
}
复制代码
例子中取出 google map ,在 zoom=1 及 x=1,y=1是的图片。
http://mt2.google.com/vt/lyrs=m@ ... &z=1&s=Gali
登录/注册后可看大图
[
本帖最后由 trisun 于 23-6-2010 15:07 编辑
]
作者:
ubuntuhk
时间:
23-6-2010 19:52
标题:
回复 #1 trisun 的帖子
把gmap地图搬到本地,这想法太有才了
作者:
GPS
时间:
23-6-2010 21:25
LZ算过如果保存悉尼的所有level,到底要多大存储吗? 有哪位下载了,共享一下。呵呵。
作者:
trisun
时间:
24-6-2010 12:47
180 M 左右。几万片到几十万片,下载很费时间的, 下载的Level 越多,片数几何级数增加。
[
本帖最后由 trisun 于 24-6-2010 12:55 编辑
]
作者:
trisun
时间:
24-6-2010 13:09
标题:
GNavigator lite
http://store.ovi.com/content/21464
Guidebee Navigatior Lite
by: Guidebee
City guides & Maps - 0.67 MB
Mobile World Map, GPS Compass, MSN Messenger, IP Search, Find address, Get Direction
这个支持离线地图。
作者:
trisun
时间:
25-6-2010 00:09
有需要下载工具的请到
http://www.mapdigit.com/forum/vi ... &extra=page%3D1
下载
这个地图可以直接用于 Gnavigator lite
作者:
sundaliang
时间:
25-6-2010 01:02
感觉是个好资源,
可是貌似不太容易上手,
我能把地图下到电脑上,然后很容易的看我的路线吗?
作者:
ubuntuhk
时间:
25-6-2010 01:16
标题:
回复 #7 sundaliang 的帖子
呵呵,这个地图可以供有兴趣研究地图的同学用,如果要用来查找新路,还是得用online的方式或者装个tomtom之类的。
作者:
GPS
时间:
25-6-2010 13:43
这个思想挺有意思。比如,要搞个显示位置的东西,可以把一个区域的各个level的tiles都下载,然后根据经纬度按照LZ给的链接里的方法,显示附近的tiles和位置。应该可行吧。
作者:
ubuntuhk
时间:
25-6-2010 14:57
标题:
回复 #9 GPS 的帖子
当然可行,绝大部分地图软件都是这么干的
作者:
熊猫阿三
时间:
25-6-2010 15:53
牛啊...
作者:
羡慕嫉妒恨
时间:
25-6-2010 16:12
itouch 上就可以装离线地图,用googledownloadtool工具
欢迎光临 FreeOZ论坛 (https://www.freeoz.org/ibbs/)
Powered by Discuz! X3.2