
2008-06-18 22:04:47
|
Post #1
说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现(附程序,免费 ...
|
之翼
|
最近爬山的时候想弄个卫星地图给我的手机导航,就在网上东找西找,也发现几个取GOOGLE卫星图片的工具软件,不过用起来总是不顺,主要是如下这几个问题:取的图片精度太低,不能取100米或50米的卫星图片;或者拼接出来的最终地图尺寸太小,难以做超过10000*10000的大图;或者就是取一会儿就会被GOOGLE识别出而封堵了IP;再就是无法取GOOGLE TERRAIN的等高线图;还有就是有些不能自动生成MAP文件,这个要手工用OZI校准也是个繁重的工作;还有就是要收费的 所以就萌生了自己研究一下并写个小程序的念头。 借用磨房的宝地,将相关的技术问题和程序实现与大家交流和讨论一下。 这里仅做GPS地图方面的程序学习和技术研究的交流,请大家使用我提供的代码或程序之前,认真阅读MAPS.GOOGLE.COM的《使用条款》。对于我提供的代码、程序,或者是GOOGLE的卫星地图的不正当使用,可能导致的一切问题,本人概不负责^-^ 下面要提供的一些技术文档或代码,都是在写这个小程序中用到的,很多来自网上的文章或者网友提供的代码,这里就不一一指出了,先行谢过。 还有就是我时间有限,只能晚上有空的时候慢慢整理逐贴贴出来,请XDJM谅解了
之翼 于 2008-06-20 14:17:23 编辑
|
2008-06-18 22:12:48
|
Post #2
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
我第一次在磨房混在磨房发贴,不知道转贴一些其他地方来的文字行不行。 不过,都是与这个主题有关的技术文字了。 首先要自动生成OZI/SMARTCOMGPS可以用的已经校准的.MAP文件,就得知道该文件的格式定义,下面的这个说明是不可以不看的。 OZI MAP文件格式详解 Map File Format In the text below the lines in the map file are marked with a dot. Only those parameters which can be modified/created by the user are described, parameters which are used for special cases are not described. The lines in green are optional The Map File The lines are in the order they are in the map file. -------------------------------------------------------------------------------- Header and Version of File OziExplorer Map Data File Version 2.1 -------------------------------------------------------------------------------- Title of Map - any text string Brisbane Region -------------------------------------------------------------------------------- Link to map image file D:OziMapsregionalsouth.ozf2 Can be 1 of 2 things 1 TIFF scale factor - redundant, no longer used and has been replaced by line below 1 ,Map Code, - only used for special types of maps - Note - cannot be modified by the user but must be there. -------------------------------------------------------------------------------- Datum settings WGS 84,, 0.0000, 0.0000,WGS 84 - Note - for normal maps only the datum in the first field is used the rest of the parameters are for datum shifts and there is normally no need for these to be modified by the user. -------------------------------------------------------------------------------- Reserved fields, the lines must be there Reserved 1 Reserved 2 -------------------------------------------------------------------------------- Magnetic Variation entry - degrees,minutes Magnetic Variation,,,E -------------------------------------------------------------------------------- Map Projection Map Projection,Lambert Conformal Conic,PolyCal,No,AutoCalOnly,No,BSBUseWPX,Yes Parameters Map Projection - must match the projection name used in OziExplorer PolyCal - the next parameter is Yes if Polynomial calibration is used and No if not AutoCalOnly - Yes if calibration cannot be adjusted by the user No if it can BSBUseWPX - For BSB images only, Yes if the calibration equations contained in the BSB file are used. -------------------------------------------------------------------------------- Calibration points, there are always 30 Only 9 points can be modified from within OziExplorer but OziExplorer will use the full 30 if they exist in the .map file. Point01,xy, 494, 235,in, deg, 24, 0,S, 148, 0,E, grid, , , ,S Point02,xy, 4076, 238,in, deg, 24, 0,S, 154, 0,E, grid, , , ,S Point03,xy, 4011, 2854,in, deg, 28, 0,S, 154, 0,E, grid, , , ,S Point04,xy, 550, 2851,in, deg, 28, 0,S, 148, 0,E, grid, , , ,S Point05,xy, , ,in, deg, , ,S, , ,E, grid, , , ,S Point06,xy, , ,in, deg, , ,S, , ,E, grid, , , ,S ... Point30,xy, , ,in, deg, , ,N, , ,W, grid, , , ,N -------------------------------------------------------------------------------- Projection setup parmeters, all on one line. Projection Setup, 0.000000000, 152.000000000, 1.000000000, 2500000.00, 100000.00, -24.666667000, -27.333333000,,, Parameters Latitude Origin Longitude Origin K Factor False Easting False Northing Latitude 1 Latitude 2 Height - used in the Vertical Near-Sided Perspective Projection Sat - not used Path - not used -------------------------------------------------------------------------------- A marker line, it contains no information but is used as a file marker, must be there Map Feature = MF ; Map Comment = MC These follow if they exist Map Features, there are 3 lines per feature Line 1 Parameters Number Name Latitude Longitude Show Format - not used Fore Color Back Color Symbol Name Create Waypoint Waypoint Name Format Type - internal use Line 2 - the link to the picture, if there is no picture a blank line must be there Line 3 - the description of the feature, if no description the blank line must be there MF, 1,MF 1 , -26.557302, 152.679007, 0, 16777215, 16711680, ,1,MF1 c:picturesphoto5.jpg This is a good camping spot MF, 2,MF 7 , -26.713354, 153.249176, 0, 16777215, 16711680,Asterisk.bmp ,1,MF7 Map Comments, there are 2 lines per comment Line 1 Parameters Number Latitude Longitude Show Format - not used Fore Color Back Color Width Height Font Size Font Style Line 2 - The text for the comment MC, 1, -26.572626, 152.512726, 0, 0, 65280, 68,20,6,0 Map Comment 1 MC, 2, -26.661532, 152.633450, 0, 0, 13158342, 182,82,13,1 Map Comment 2 This is a large map comment MC, 3, -26.659946, 152.634492, 0, 0, 13158342, 182,82,13,1 Map Comment 3 Attached file marker, .plt, .wpt, .evt, .pnt files can be included Track File = TF These follow if they exist The attached files - not limited to just track files TF,e:GpsMapData 0_2.plt TF,e:GpsMapDataaa_demo1.plt TF,e:GpsMapData 0_test.plt TF,e:GpsMapData 1_test.plt TF,e:GpsMapDataaaa.pnt TF,e:GpsMapDatanames.pnt -------------------------------------------------------------------------------- The Moving Map section marker Moving Map Parameters = MM? These follow if they exist Use in Moving Map, if this parameter is set to No then the map will be excluded when looking for a new map to change to when using moving map mode. It does not affect other map find functions. MM0,Yes Number of Map border points (corner markers) Only 4 points can be set graphically in OziExplorer but up to 100 points can be used when derived from other sources, such as importing BSB charts. MMPNUM,4 The x, y pixel location of each border point, there must be an entry for each border point. These are used by OziExplorer as the map loads to determine the map border points. MMPXY,1,494,234 MMPXY,2,4076,238 MMPXY,3,4012,2855 MMPXY,4,549,2852 The lat, lon position of each border point, there must be an entry for each border point. These values are used in the map find and moving map functions when looking for maps. If these values are not there then the map will never be found. If these values do not agree with the MMPXY points (after map calibration is applied) then map finding in moving map will not function correctly. These values will be overwritten by the calculated value from the above x, y points every time the map is saved. MMPLL,1, 147.999332, -23.998496 MMPLL,2, 154.000701, -23.999946 MMPLL,3, 154.001025, -28.001546 MMPLL,4, 147.998983, -28.001469 The scale of the image meters/pixel, its calculated in the left / right image direction. It is calculated each time OziExplorer is run, the value in the file is used when searching for maps of "more detailed" scale. MM1B,170.352987 -------------------------------------------------------------------------------- The lat/lon grid setup LL Grid Setup LLGRID,No,10 Min,Yes,8421504,255,16711935,10 Min,16777215,8421504,9,1,Yes,x Parameters LLGRID - identifier Grid On - Yes = display grid Grid spacing - number and unit Autoscale - Yes = autoscale on Degree line color Minute line color second line color label spacing - number and unit label fore color label back color label size label - show on all screens x - ignore The Other grid setup Other Grid Setup GRGRID,No,10 Km,Yes,255,16711680,10 Km,16711680,16777215,9,1,Yes,Yes,No,x GRGRID - identifier Grid On - Yes = display grid Grid spacing - number and unit Autoscale - Yes = autoscale on Km line color Meter line color label spacing - number and unit label fore color label back color label size label - show on all screens Clip to neat line No meters shown in label ?? Show last 3 digits in label ?? x - ignore The position the map will display when it is opened MOP,Map Open Position,3008,2324 The map image width and height - not used, just for information IWH,Map Image Width/Height,4440,3590 |
2008-06-18 22:22:35
|
Post #3
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
首先看看行: The scale of the image meters/pixel, its calculated in the left / right image direction. It is calculated each time OziExplorer is run, the value in the file is used when searching for maps of "more detailed" scale. MM1B,170.352987 地图中每个像素多少米? 计算的方法就是:计算截取到的地图的左上角和右上角两点经纬度之间的距离,除以地图横向的像素总数,就可以得到。下面是计算两点经纬度之间距离的代码: double rad(double d) { return d * 3.1415926535897 / 180.0; } double GetDistance(double lat1, double lng1, double lat2, double lng2) { double radLat1 = rad(lat1); double radLat2 = rad(lat2); double a = radLat1 - radLat2; double b = rad(lng1) - rad(lng2); double s = 2 * asin(sqrt(pow(sin(a/2), 2) + cos(radLat1)*cos(radLat2)*pow(sin(b/2),2))); s = s * 6378.137 * 1000; //m not km return s; } |
2008-06-18 22:39:04
|
Post #4
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
GOOGLE的卫星图片,都是256*256像素的小块组成,每一个小块由一串由“qrst”的字母序列来表示。这个方面在网上搜索一下,有很多文字介绍。进入MAPS.GOOGLE.COM网站看卫星图片时,还有一个放大倍数的也很重要,决定了图片的精度。每放大倍数提升一级,原来256*256大小的图片,就会裂变为4个256*256的图片了。最大的倍数是20,缩小一级就减一。例如广州,就只提供最大级别为19的精度。 所以我们如果要截取某个地方某个放大倍数的图片的时候,就要由这些信息首先计算出“qrst”字母序列来。下面是计算的代码。返回的序列前面加上了GOOGLE MAPS服务器的URL和相关的参数。 BOOL GetQuadtreeAddress(double dlong, double dlat, int nLevel, CString& cstrAddress) { double PI = 3.1415926535897; nLevel--; // now convert to normalized square coordinates // use standard equations to map into mercator projection double x = (180.0 + dlong) / 360.0; double y = -dlat * PI / 180; // convert to radians y = 0.5 * log((1 + sin(y)) / (1 - sin(y))); y *= 1.0/(2 * PI); // scale factor from radians to normalized y += 0.5; // and make y range from 0 - 1 cstrAddress = "http://kh0.google.com/kh?v=27&t=t"; // google addresses start with t CString lookup = "qrts"; // tl tr bl br while (nLevel--) { // make sure we only look at fractional part x -= floor(x); y -= floor(y); cstrAddress = cstrAddress + lookup.GetAt((x >= 0.5 ? 1 : 0) + (y >= 0.5 ? 2 : 0)); // now descend into that square x *= 2; y *= 2; } return TRUE; } |
2008-06-18 22:40:51
|
Post #5
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
忘记说了,这里提供的代码都只考虑在北纬和东经范围内的情况。没有考虑纬度和经度为负值时的情况 |
2008-06-18 22:43:27
|
Post #6
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
这里的代码,都已经考虑地球是一个球体,进行了投影计算的 |
2008-06-18 22:52:53
|
Post #7
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
上面的代码,讲到了由经纬度计算qrst序列的方法,有了这个qrst序列,就可以让我们取到某处的256*256的卫星图片了。然而取到的这个图片,所代表的却是某个经纬度范围内的。那么,如果我们能计算出这个图片所代表的经纬度范围,就可以利用它做最终的.MAP文件的自动校准了。 计算方法如下: struct _LONGLAT_OF_QRST { char qrst[24]; double flongmin; double flongmax; double flatmin; double flatmax; double flong; double flat; }; typedef struct _LONGLAT_OF_QRST LONGLAT_OF_QRST; typedef struct _LONGLAT_OF_QRST *PLLONGLAT_OF_QRST; double NormalToMercator(double y) { double PI = 3.1415926535897; y -= 0.5; y *= 2 * PI; y = exp(y * 2); y = (y-1)/(y+1); y = asin(y); y = y * (-180.0/PI); return y; } BOOL GetCoordinatesFromAddress(CString cstrqrst, LONGLAT_OF_QRST *plloq) { // get normalized coordinate first double x = 0.0; double y = 0.0; double scale = 1.0; cstrqrst.MakeLower(); lstrcpy(plloq->qrst, (LPCTSTR) cstrqrst); cstrqrst = cstrqrst.Mid(1); // skip the first character while (cstrqrst.GetLength() > 0) { TCHAR c; scale *= 0.5; c = cstrqrst.GetAt(0); // remove first character if (c == 'r' || c == 's' ![]() { x += scale; } if (c == 't' || c == 's' ![]() { y += scale; } cstrqrst = cstrqrst.Mid(1); } plloq->flongmin = (x - 0.5) * 360; plloq->flongmax = (x + scale - 0.5) * 360; plloq->flong = (x + scale * 0.5 - 0.5) * 360; plloq->flatmax = NormalToMercator(y); plloq->flatmin = NormalToMercator(y + scale); plloq->flat = NormalToMercator(y + scale * 0.5); return TRUE; } 经纬度范围存入LONGLAT_OF_QRST结构中,记录了该256*256图片的四个边或四个点的经纬度值 |
2008-06-18 22:55:06
|
Post #8
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
晕,上面的括号竟然变成了表情符号 |
2008-06-18 23:11:37
|
Post #9
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图 ...
|
之翼
|
现在来考虑要做的GOOGLE地图的位置和范围 简单的方法就是直接给出地图的左上角和右下角的两点经纬度,取下这两点之间(经纬度做矩形处理,实际就是4点)所有的卫星图片,这样就可以做一个矩形的地图了。所以按下面的图示设计地图的范围。 其中经纬度的获得,大家可以安装一个GOOGLE EARTH,直接查看你要取的某个山脉或某个城镇的经纬度即可。GOOGLE EARTH的OPTIONS里可以更改经纬度的显示格式。 ![]() |
2008-06-18 23:19:57
|
Post #10
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
洗澡睡觉去,明天有空再继续了。 |
2008-06-19 06:45:47
|
Post #11
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
东北老哥
|
学习中 +5个好评…… |
2008-06-19 09:58:11
|
Post #12
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
工兵pro
|
大部分GIS软件都是WGS84坐标,WGS84中地球是个椭球 如果哪天在iphone上做3D的可以学习楼主的经验 楼主写代码的时候也可多考虑一下可移植性,iphone 3G这样的平台未来会比较适合这类应用,可以寄希望于google发布iphone版的google earth,如果他不发布,楼主可以自己做 ---------------------------------------- |
2008-06-19 14:14:23
|
Post #13
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图 ...
|
之翼
|
在MAPS.GOOGLE.COM上看卫星图片的时候,每一个256*256图片都是用一个qrst序列来表示其服务器上的URL地址,但是对于GOOGLE的地形地表(terrain)的图片来说,却是采取的另外一个表示方法,这个大家可以读一下这段文字描述: For Google map, the url of a tile looks like : http://mt1.google.com/mt?n=404&v=w2.12&x=130&y=93&zoom=9 using x and Y for the tile coordinates, and a zoom factor. The zoom factor goes from 17 (fully zoomed out) to 0 (maximum definition). At a factor 17, the whole earth is in one tile where x=0 and y=0. At a factor 16, the earth is divided in 2x2 parts, where 0<=x<=1 and 0<=y<=1. and at each zoom step, each tile is divided into 4 parts. So at a zoom factor Z, the number of horizontal and vertical tiles is 2^(17-z) 根据这个算法,网上也能搜索到一些根据经纬度来计算这个URL地址的代码,但是几乎见到的都是没有考虑球体投影的代码,计算出来的结果,在纬度方面偏差很大,显然不能用于GPS定位和导航。 考虑球体投影后,我修正的代码如下: BOOL GetQuadtreeAddress(double dlong, double dlat, int zoom, CString& cstrAddress) { double PI = 3.1415926535897; // now convert to normalized square coordinates // use standard equations to map into mercator projection double x = (180.0 + dlong) / 360.0; double y = -dlat * PI / 180; // convert to radians y = 0.5 * log((1 + sin(y)) / (1 - sin(y))); y *= 1.0/(2 * PI); // scale factor from radians to normalized y += 0.5; // and make y range from 0 - 1 int nx, ny; nx = (int) floor(x * pow(2, (17-zoom))); ny = (int) floor(y * pow(2, (17-zoom))); cstrAddress.Format("http://mt0.google.com/mt?n=404&v=w2p.71&x=%d&y=%d&zoom=%d", nx, ny, zoom); return TRUE; } 这里的函数名称,就直接用了计算qrst序列时的名字,以便对应着看,大家就不要直接从英文字母的意思上去理解了。 |
2008-06-19 14:28:19
|
Post #14
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图的程序实现
|
之翼
|
对应GOOGLE TERRAIN的X, Y, zoom表示方法,同样也有一个根据x, y, zoom值来计算每一个256*256像素图片的四个边(或者说四个顶点)的经纬度值的算法,代码如下: struct _LONGLAT_OF_XYZOOM { int nx; int ny; int nzoom; double flongmin; double flongmax; double flatmin; double flatmax; double flong; double flat; }; typedef struct _LONGLAT_OF_XYZOOM LONGLAT_OF_XYZOOM; typedef struct _LONGLAT_OF_XYZOOM *PLLONGLAT_OF_XYZOOM; double NormalToMercator(double y) { double PI = 3.1415926535897; y -= 0.5; y *= 2 * PI; y = exp(y * 2); y = (y-1)/(y+1); y = asin(y); y = y * (-180.0/PI); return y; } BOOL GetCoordinatesFromAddress(int nx, int ny, int nzoom, LONGLAT_OF_XYZOOM *plloq) { plloq->nx = nx; plloq->ny = ny; plloq->nzoom = nzoom; // get normalized coordinate first double x = 0.0; double y = 0.0; double scale = 1.0; scale = 1.0 / (double)pow(2, (17 - nzoom)); x = (double) nx / (double)pow(2, (17 - nzoom)); y = (double) ny / (double)pow(2, (17 - nzoom)); plloq->flongmin = (x - 0.5) * 360; plloq->flongmax = (x + scale - 0.5) * 360; plloq->flong = (x + scale * 0.5 - 0.5) * 360; plloq->flatmax = NormalToMercator(y); plloq->flatmin = NormalToMercator(y + scale); plloq->flat = NormalToMercator(y + scale * 0.5); return TRUE; } 经纬度范围存入LONGLAT_OF_XYZOOM结构中,记录了该256*256图片的四个边或四个点的经纬度值 |
2008-06-19 15:01:46
|
Post #15
Re: 说说从GOOGLE MAPS网站上截图制作GPS导航地图 ...
|
之翼
|
上面基本上将GOOGLE的卫星图片在服务器上的URL计算方法都讲到了。我的文字功底差,比较凌乱,大家感兴趣的就勉强坚持下,呵呵。现在说说怎么取到这个URL上的图片: 有了URL后,我们就可以在程序窗口上开一个WEBBROWSER的控件,连接到这个URL上取回并显示该图片。 图片取到后,WEBBROWSER得到OnDocumentComplete事件。这时,我们就可以把该控件上显示的图片截取下来,并保存到自己的电脑上。我在程序里做了另外一个窗口,用于显示从WEBBROWSER控件上截取到的256*256图片,一方面可以用于调整真实卫星图片显示在WEBBROWSER控件上的偏移位置,再者也可以看着程序在快速地存取GOOGLE卫星图片,也是一个蛮有快感的体验。 程序窗口如下: ![]() |