中国地图经纬度偏移修正算法完美解决方案
(最新批注,文中的地址,偏移接口google已经关闭,(上午写的不对)最新版本的地图不是消除了偏移而是把卫星图也偏移了,所以就关闭了那个修正的接口,因为他不需要修正了,有需要偏移数据的可以联系我哦 qq:443144476
参考/dongmeng110/archive/2010/03/26/5418678.aspx
欢迎来我的技术博客主页 查找其余有用代码
/dongmeng110
有问题也可以加我qq 443144476
添加好友请注明“行业内部沟通”
中国地图和卫星图都存则偏移量,这个是由中国规划局,确定的,一个偏移算法,实际上是没有什么特殊规律的,他的生成算法是有规律,不过这个规律你我都很难拿到,那我们怎么解决这个偏差呢,毕竟做地图开发的都存在卫星图和地图的切换,谁不想让切换以后的地图对上呢!后来我发现google的地图服务,ditu.gogle开始的都没有偏差,maps.google开头的服务就有偏差,我就开始查找google的取偏移量算法,事前我还是图破解google手机版本的数据,没有成功,估计是使用了自己的压缩或加密算法,最后也没有找到规律,后来才尝试破解web版本的不过web版本的接口我对于js不是特别熟悉,所以本次破解放弃了分析源代码的步骤,而是直接采用排除法那就是把地图部分访问的全部地址,一个接一个封杀掉,查找那个气偏移做用的网址 /maps/vp?spn=0.0,0.0&z=18&vp=39.111195,117.148067 最后找到了就是这个,记住每次测试用清理浏览器缓存哦,使用fixfox的fildder和adblock就够了 然后就是 分析每次返回内容的规律,黄天不负有心人啊,我总算是搞定了,下面是我整理的接口
Google 中国地图偏移接口
1. 接口地址:/maps/vp?spn=0.0,0.0&z=18&vp=39.111195,117.148067
(注:.cn和.com都可以,我用国内服务器就会选择.cn用美国服务器就会选择.com)
2. 返回内容中的有效部分:
3. (39.111195, 117.148067, 18, [9, -2, 18, -4, 37, -8, 74, -16, 149, -33, 298, -67, 596, -135, 1193, -270])4. Spn参数暂时未知实际意义,但是需要上发spn参数,任意两个小数用逗号分开
Vp参数纬经度值,用逗号分隔,z参数为地图缩放级别,无实际意义
5. 取回的部分中有效数字为[9, -2, 18, -4, 37, -8, 74, -16, 149, -33, 298, -67, 596, -134, 1192, -268]这个数组总共有8组数字,每两个为一组,分为别从11级到18级的地图和卫星图的偏移像素数量,我们前一组数字精确的等于后一组数字除二,我们为了得到最精确的偏移,故选择第18级的偏移量1193,-270,1193为x方向上精度的偏移像素,-270为y方向上维度偏移像素
6. 经
纬度的偏移转换我们需要江经纬度39.111195,117.148067转化为18级像素值25620917 和 55392414,然后分别加上偏移量-270,1193,然后再转化为经纬度39.11231854918217 和117.15446412563324,即位偏移后的经纬度
(很多朋友问我 经纬度 和像素值如何转换)
/dongmeng110/archive/2009/12/13/4997634.aspx
我的这篇文章做了详细论述,有需要的可以看看
以上是我花了2个小时完成的google偏移接口的破解,后来公司要求,把google的偏移数据全部弄下来,以防止gogle更换服务接口,我现在采用的是每隔0.01个经纬度,取一次偏移量,数据存入bdb,中国的总数据量 千万条级别,我用了两天的时间已经完成了三分之一中国的爬取,当然我用了三台服务器,总数据量估计在1个G以下,是可以接受的范围,精度可以保证最大级别18级地图,偏差小于5个像素
public static boolean getOffset(HttpClient httpClient, int lat, int lng) {
StringBuilder url = new StringBuilder();
url.append("/maps/vp?");
url.append("spn=0.0,0.0&z=18&vp=");
url.append(lat / 100D);
url.append(",");
url.append(lng / 100D);
String urlStr = url.toString();
GetMethod method = new GetMethod(urlStr);
try {
int status = httpClient.executeMethod(method);
if (status == 200) {
byte[] bs = method.getResponseBody();
String js = new String(bs, "utf-8");
int x = stIndexOf("[");
int y = stIndexOf("]");
if (x > 0 && y > 0) {
String text = js.substring(x + 1, y);
int b = stIndexOf(",");
int a = stIndexOf(",", b - 1);
if (a > 0 && b > 0) {
String offsetPixX = text.substring(a + 2, b);
String offsetPixY = text.substring(b + 2);
OffsetBean offset = new OffsetBean();
offset.setLng(lng);
offset.setLat(lat);
offset.setOffset_x(Integer.parseInt(offsetPixX));
offset.setOffset_y(Integer.parseInt(offsetPixY));
OffsetBDB offsetBDB = OffsetBDB.getInstance();
offsetBDB.putOffset(offset);
return true;
}
} else {
logger.error("error 1: lat:" + lat + "\tlng:" + lng);
}
} else {
logger.error("error 2: lat:" + lat + "\tlng:" + lng);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
method.releaseConnection();
}
return false;
}
附:
最近接到了很多热心朋友的问题,下面整理部分内容
第一我们从GPS模块得到的经纬度信息如何验证他的准确性呢,你可以找一个真实的位置,你熟悉的,在google earth软件上面查看那个位置的警卫度,尤其是大城市 地图分辨率较高,那个经纬度是很准确的,我们就可以认为那个就是真实经纬度,这时候你就可以知道你的GPS得到的数据是有多大偏移了
第二说说国内偏移的问题,国内的偏移只的是在国内发行
的地图是必须进行偏移操作的,也就是说其实地图上的那个点并不对应真实的点,说白了就是地图发生了形变了,由于它的形变在相近的地方是 差不多一样的 所以我们很难发现,具体偏移算法按照现行法律规定是不可以公布的,据我所知目前掌握这个算法的公司有很多,很多有资质的公司都有,那我们根据 以上的算法就可以找到这个偏移值
第三偏移值的意义这个偏移值用来修订真实经纬度和地图经纬度之间的偏移,并不能解决你GPS信号经纬度和真实经纬度之间的偏移