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

转自: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);

    }



}
囧。。。貌似这个方法也解决不了非线性的问题。
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值