Google地球(GPS)坐标之地图坐标偏移

来源:互联网 发布:spss20 mac 安装教程 编辑:程序博客网 时间:2024/06/10 05:11

转自:http://www.xkshow.cn/?p=33

这个问题涉及国家的法律问题,很重要。根据我国相关法律,在国内发行的任何民用中国地图产品不准使用真实的坐标,必须加入一定的偏移量(大约600米),据说这一做法是“出于国家安全方面的考虑”。

偏移数据是不公开的,五六百米是实测结果。我国法律条文规定在国内必须使用国家测绘局的坐标体系(西安80),而国际通行的坐标体系是WGS84。另外,民航使用的坐标系是国际标准WGS84,否则国际航班没法正常飞行。

Google Maps就属于在国内发行的民用中国地图产品,自然也不例外地加入了偏移量。所有在中国市场上能买到的GPS中国地图(比如灵图,凯立德,Route66和Garmin等)也都带有600米左右的偏差,其显示的坐标与真实坐标相差600米,没有任何实用价值.

例如,在软件里查看GPS坐标,同一地点的数据如下:

官方地图坐标 N22.540938666666665,E113.95289433333335

偏移地图坐标 N22.5383656877113157,E113.9581618420152

GPS数据查看器显示的坐标与纠偏地图坐标相同,官方地图与纠偏地图误差大约有500米。(可以简单的使用偏移差值计算,但并非所有的确均相同)

Google Map的中国地图,坐标做过偏移,没法直接和GPS得来的经纬度数据匹配使用,得要在相关行业管理部门取得加密插件,植入软件里,才能正确显示位置。

国家保密插件,也叫做加密插件或者加偏或者SM模组,其实就是对真实坐标系统进行人为地加偏处理,按照几行代码的算法,将真实的坐标加密成虚假的坐标,而这个加偏并不是线性的加偏,所以各地的偏移情况有所不同,而加密后的坐标也常被人称为火星坐标系统,让国外的政府和企业等,都看不懂我国坐标系统。

现在,所有电子地图所有导航设备,都需要加入国家保密插件。第一步,地图公司测绘地图,测绘完成后,送到国家测绘局,将真实坐标的电子地图,加密成“火星坐标“,这样的地图才是可以出版和发布的,然后才可以让GPS公司处理。第二步,所有GPS公司,只要需要汽车导航的,需要用到导航电子地图的,统统需要在软件中加入国家保密算法,将Com口读出来的真实的坐标信号,加密转换成国家要求的保密的坐标,这样,GPS导航仪和导航电子地图就可以完全匹配,GPS也就可以正常工作。

所以,所有导航电子地图公司,像四维图新、瑞图、易图通、高德等,都需要将自己的电子地图拿到国家测绘局进行加密处理,而所有导航软件公司,都需要将自己的导航软件中加入国家测绘局提供的加密算法的代码,而这一段代码,就是国家的机密,不是公开的,每次去国家测绘局加密处理都需要预约并在封闭的环境中进行,编译完成后需要是在主程序的exe中,而不能编译在外部dll等文件中。

当然,并不是说这样就没有使用GPS的可能了。通过自定义GmapType(ditu)和自定义投影坐标Gprojection(dituProjection)来实现偏差纠正,原理是修改ditu层的投影换算函数:

.fromLatlngToPixel()+offset

.fromPixelToLatlng()-offset

这样就无须修改上层Overlay的坐标参数,直接使用正确的Lat,Lng即可。即通过重新调整地图的投影,从而实现地图的正确显示。


附:

自定义投影坐标(GProjection)来实现Google Map中国地图和卫星图的偏差纠正

原理:

通过自定义GMapType(ditu)和自定义投影坐标GProjection(dituProjection) 来实现偏差纠正。 

原理是修改ditu层的投影换算函数,
在.fromLatLngToPixel()里面 +Offset
在.fromPixelToLatLng()里面 -Offset

这样子就无需修改上层Overlay的坐标参数,直接使用正确的Lat,Lng即可

代码:(以上海为例)

function load_gmap(){    //shanghai    var xOffset= -0.001889737;    var yOffset= 0.004844069;    var map = null;    if(GBrowserIsCompatible()) {var Cditu = new GCopyright(1,    new GLatLngBounds(     new GLatLng(-90,-180),     new GLatLng(90,180) ),   0,   "Mapabc.com"); var copyright = new GCopyrightCollection("");copyright.addCopyright(Cditu);var dituTileLayer = new GTileLayer(copyright, 1, 17);dituTileLayer.getTileUrl = function(tile, zoomlevel,x) {    var url = G_NORMAL_MAP.getTileLayers()[0].getTileUrl(tile,zoomlevel,x);    var bits = url.split("&");    bits[1] = "http://servicetile.mapabc.com/googlechina/maptile?" + bits[1];    /**bits[1] = "http://mapgoogle.mapabc.com/googlechina/maptile?" + bits[1];**/    bits.shift();    url = bits.join("&");    return url; };function dituProjection(xOffset,yOffset){    this.xOffset = xOffset;    this.yOffset = yOffset;}dituProjection.prototype = new GProjection();dituProjection.prototype.fromLatLngToPixel = function(latlng,  zoom){    return (G_NORMAL_MAP.getProjection()).fromLatLngToPixel(new GLatLng(latlng.lat()+this.xOffset,latlng.lng()+this.yOffset),zoom);};dituProjection.prototype.fromPixelToLatLng = function(pixel,zoom,unbounded){    var latlng = (G_NORMAL_MAP.getProjection()).fromPixelToLatLng(pixel,zoom,unbounded);    return new GLatLng(latlng.lat()-this.xOffset,latlng.lng()-this.yOffset);}dituProjection.prototype.tileCheckRange = function(tile, zoom, tilesize){    return (G_NORMAL_MAP.getProjection()).tileCheckRange(tile,zoom,tilesize);}dituProjection.prototype.getWrapWidth = function(zoom){    return (G_NORMAL_MAP.getProjection()).getWrapWidth(zoom);}var ditu = new GMapType([dituTileLayer],new dituProjection(xOffset,yOffset), "Ditu", { shortName: "ditu", alt: "layer from ditu.google.com" });map = new GMap2(document.getElementById('gmap'),{mapTypes:[ditu,/*G_NORMAL_MAP,*/G_SATELLITE_MAP]});map.addControl(new GLargeMapControl());/**map.addControl(new GMapTypeControl());**/map.addControl(new GOverviewMapControl());map.addControl(new GScaleControl());map.enableDoubleClickZoom();/**map.enableScrollWheelZoom();**/map.setCenter(new GLatLng(31.231628368031693, 121.47645235061645 ), 16);ditu.getName = function(){ return '中国地图';};ditu._getName = function(){ return 'ditu';};/*G_NORMAL_MAP.getName = function(){ return '世界地图';};G_NORMAL_MAP._getName = function(){ return 'Map';};*/G_SATELLITE_MAP.getName = function(){ return '卫星图';};G_SATELLITE_MAP._getName = function(){ return 'Satellite';};/** the map type **/var _mt = ditu;map.setMapType(_mt);map.addControl(new GMapTypeControl());var point = new GLatLng(31.231628368031693, 121.47645235061645);var marker = new GMarker(point);GEvent.addListener(marker,"click",function(){marker.openInfoWindowHtml('Text Info Here!');});map.addOverlay(marker);    }}
囧。。。貌似这个方法也解决不了非线性的问题。