gis
gis
管理员
管理员
  • 注册日期2003-07-16
  • 发帖数15945
  • QQ554730525
  • 铜币25337枚
  • 威望15352点
  • 贡献值0点
  • 银元0个
  • GIS帝国居民
  • 帝国沙发管家
  • GIS帝国明星
  • GIS帝国铁杆
阅读:4443回复:0

中国地图经纬度偏移修正算法完美解决方案

楼主#
更多 发布于:2011-09-14 10:09
<table cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td id="postmessage_107" class="t_msgfont"><span class="t_tag" href="tag.php?name=%E4%B8%AD%E5%9B%BD">中国</span><span class="t_tag" href="tag.php?name=%E5%9C%B0%E5%9B%BE">地图</span>和<span class="t_tag" href="tag.php?name=%E5%8D%AB%E6%98%9F">卫星</span>图都存则偏移量,这个是由中国规划局,确定的,一个偏移算法,实际上是没有什么特殊规律的,他的生成算法是有规律,不过这个规律你我都很难拿到,那我们怎么解决这个偏差呢,毕竟做地图<span class="t_tag" href="tag.php?name=%E5%BC%80%E5%8F%91">开发</span>的都存在卫星图和地图的切换,谁不想让切换以后的地图对上呢!后来我发现<span class="t_tag" href="tag.php?name=google">google</span>的地图<span class="t_tag" href="tag.php?name=%E6%9C%8D%E5%8A%A1">服务</span>,ditu.gogle开始的都没有偏差,<span class="t_tag" href="tag.php?name=maps">maps</span>.google开头的服务就有偏差,我就开始查找google的取偏移量算法,事前我还是图破解google<span class="t_tag" href="tag.php?name=%E6%89%8B%E6%9C%BA">手机</span>版本的<span class="t_tag" href="tag.php?name=%E6%95%B0%E6%8D%AE">数据</span>,没有成功,估计是使用了自己的压缩或加密算法,最后也没有找到规律,后来才尝试破解web版本的不过web版本的接口我对于js不是特别熟悉,所以本次破解放弃了分析源代码的步骤,而是直接采用排除法那就是把地图部分访问的全部地址,一个接一个封杀掉,查找那个气偏移做用的网址
<a href="http://ditu.google.cn/maps/vp?spn=0.0" target="_blank">http://ditu.google.cn/maps/vp?spn=0.0</a>,0.0;z=18;vp=39.111195,117.148067
最后找到了就是这个,记住每次测试用清理浏览器缓存哦,使用fixfox的fildder和adblock就够了 然后就是
分析每次返回内容的规律,黄天不负有心人啊,我总算是搞定了,下面是我整理的接口<br/><br/>Google 中国地图偏移接口<br/><br/><br/><br/>1.  
    接口地址:<a href="http://ditu.google.cn/maps/vp?spn=0.0" target="_blank">http://ditu.google.cn/maps/vp?spn=0.0</a>,0.0;z=18;vp=39.111195,117.148067<br/><br/><br/><br/>(注:.cn和.com都可以,我用国内<span class="t_tag" href="tag.php?name=%E6%9C%8D%E5%8A%A1%E5%99%A8">服务器</span>就会选择.cn用<span class="t_tag" href="tag.php?name=%E7%BE%8E%E5%9B%BD">美国</span>服务器就会选择.com)<br/><br/>2.    
 返回内容中的有效部分:<br/><br/>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参数,任意两个小数用逗号分开<br/><br/>Vp参数纬经度值,用逗号分隔,z参数为地图缩放级别,无实际意义<br/><br/>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方向上维度偏移像素<br/><br/>6.  
    经纬度的偏移转换我们需要江经纬度39.111195,117.148067转化为18级像素值25620917 和
55392414,然后分别加上偏移量-270,1193,然后再转化为经纬度39.11231854918217
和117.15446412563324,即位偏移后的经纬度<br/><br/><br/><br/>以上是我花了2个小时完成的google偏移接口的破解,后来公司要求,把google的偏移数据全部弄下来,以防止gogle更换服务接口,我现在采用的是每隔0.01个经纬度,取一次偏移量,数据存入bdb,中国的总数据量  千万条级别,我用了两天的<span class="t_tag" href="tag.php?name=%E6%97%B6%E9%97%B4">时间</span>已经完成了三分之一中国的爬取,当然我用了三台服务器,总数据量估计在1个G一下,是可以接受的范围,精度可以保证最大级别18级地图,偏差小于5个像素<br/><br/><br/><br/><br/><br/><br/>public
static boolean getOffset(HttpClient httpClient, int lat, int lng)
{<br/><br/>StringBuilder url = new
StringBuilder();<br/><br/>url.append("http://ditu.google.com/maps/vp?");<br/><br/>url.append("spn=0.0,0.0;z=18;vp=");<br/><br/>url.append(lat
/ 100D);<br/><br/>url.append(",");<br/><br/>url.append(lng / 100D);<br/><br/>String
urlStr = url.toString();<br/><br/>GetMethod method = new
GetMethod(urlStr);<br/><br/>try {<br/><br/>int status =
httpClient.executeMethod(method);<br/><br/>if (status == 200) {<br/><br/>byte[] bs =
method.getResponseBody();<br/><br/>String js = new String(bs, "utf-8");<br/><br/>int
x = js.lastIndexOf("[");<br/><br/>int y = js.lastIndexOf("]");<br/><br/>if (x > 0
;; y > 0) {<br/><br/>String text = js.substring(x + 1, y);<br/><br/>int b
= text.lastIndexOf(",");<br/><br/>int a = text.lastIndexOf(",", b - 1);<br/><br/>if
(a > 0 ;; b > 0) {<br/><br/>String offsetPixX = text.substring(a +
2, b);<br/><br/>String offsetPixY = text.substring(b + 2);<br/><br/>OffsetBean
offset = new
OffsetBean();<br/><br/>offset.setLng(lng);<br/><br/>offset.setLat(lat);<br/><br/>offset.setOffset_x(Integer.parseInt(offsetPixX));<br/><br/>offset.setOffset_y(Integer.parseInt(offsetPixY));<br/><br/>OffsetBDB
offsetBDB =
OffsetBDB.getInstance();<br/><br/>offsetBDB.putOffset(offset);<br/><br/>return
true;<br/><br/>}<br/><br/>} else {<br/><br/>logger.error("error 1:  lat:" + lat +
"\tlng:" + lng);<br/><br/>}<br/><br/>} else {<br/><br/>logger.error("error 2:  lat:" +
lat + "\tlng:" + lng);<br/><br/>}<br/><br/>} catch (Exception e)
{<br/><br/>e.printStackTrace();<br/><br/>} finally
{<br/><br/>method.releaseConnection();<br/><br/>}<br/><br/>return
false;<br/><br/>}<br/><br/><br/>本文来自CSDN博客,转载请标明出处:<a href="http://blog.csdn.net/dongmeng110/archive/2009/10/31/4750380.aspx" target="_blank">http://blog.csdn.net/dongmeng110/archive/2009/10/31/4750380.aspx</a></td></tr></tbody></table>
喜欢0 评分0
游客

返回顶部