关于将geoserver gwc切片加载到地图上出现偏移的问题

将投影坐标系由EPSG:4326改为EPSG:900913  修改getBound函数

参考以下知识

一。EPSG:900913

http://www.cnblogs.com/kaixin110/archive/2008/05/30/1210772.html
Google Map用什么投影坐标系统呢?以前一直以为是WGS84,但是大家都知道Google Map的地图在两极部分的畸变非常大,所以显然它不是WGS84这一类的球面坐标系统。由于一次工作,需要将google map和我自己设计的WebGIS进行叠合,我的WebGIS用的是WGS84,EPSG:4326,叠合后总是有mismatch的地方,后来索性研究 了一下openlayers的文档,得知Google Map使用的是编号为EPSG:900913的投影。从这个编号看,就知道它不是EPSG本身定义的投影,所以,我即便在map的属性设置里加上projection
=”ESPG:900913″,并在google map的 layer里设置’sphericalMercator’: true后,仍然不行。
其实,最终的问题是我的坐标系统不是基于900913的。有两种解决办法。一,将自己的数据转化为900913,可以用ogr或者arcToolbox里 相应的命令行,不再多说了。或者就是通过MapServer on-the-fly去reprojections。但是MapServer,ogr,以及arcGIS进行投影转换需要有预定好的投影,而在proj4 和arcGIS里并没有预定900913。定义方法如下:
1. 在/proj/nad/epsg里添加“# Google Mercator
<900913> +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs <>”
这样你就可以使用ogr,Mapserver实时的进行转换了。
2. 如果你需要用arcGIS来转换,需要在文件ArcGIS\Coordinate Systems\Projected Coordinate Systems\world里添加文件 Google Mercator (world).prj. 我自己写的内容为:
PROJCS[”Google_Mercator”,GEOGCS[”GCS_WGS_1984″,
DATUM[”D_WGS_1984″,SPHEROID[”WGS_1984″,6378137,0]],
PRIMEM[”Greenwich”,0],UNIT[”Degree”,0.017453292519943295]],
PROJECTION[”Mercator”],PARAMETER[”False_Easting”,0],PARAMETER[”False_Northing”,0],
PARAMETER[”Central_Meridian”,0],PARAMETER[”Standard_Parallel_1″,0],UNIT[”Meter”,1]]

PS. EPSG: 900913 为横轴墨卡托投影。它和EPSG:3395非常类似,只是没有扁率298. 257223563。也就是说他不是一个椭球。还有一点需要注意,Google 投影用的是Mercator——2SP该投影在acrGIS以及proj4里均没有定义。所以要做一些转换。
如果您对地图投影,墨卡托投影,特别是WebGIS里面的使用情况有疑惑,请参考如下的文献:
http://www.spatialreference.org/ref/user/google-projection/
http://jira.codehaus.org/browse/GEOT-1511
http://spatialreference.org/ref/user/6/
http://www.ibm.com/developerworks/cn/java/j-coordconvert/#resources
http://www.sharpgis.net/2007/05/05/SpatialReferencesCoordinate
SystemsProjectionsDatumsEllipsoidsConfusing.aspx

code:
在html中:

var lon = 4174203.107;
var lat = 3556972.005;
var zoom = 5;
var options = { maxExtent: new OpenLayers.Bounds(7765266.742441,429318.305045,16113672.956358,7543262.315404),
maxResolution: 16543,
projection: “EPSG:900913”,
units: “km”,
numZoomLevels: 7};
map = new OpenLayers.Map(‘map’, options);
layer = new OpenLayers.Layer.MapServer( “CHGIS MapServer”, “/cgi-bin/mapserv.exe?map=/ms4w/apache/htdocs/buddhist/google.map&layers=PII_google”,
{layers: ‘basic’},
{opacity:0.5, isBaseLayer:false});
map.addLayer(layer);
satellite = new OpenLayers.Layer.Google( “Google Satellite” , {type: G_SATELLITE_MAP,
‘maxZoomLevel’:18, ‘sphericalMercator’: true} );
map.addLayers([satellite]);

在map文件中:

MAP
IMAGETYPE PNG
# EXTENT 72.9958 17.9958 136.0042 54.0042
EXTENT 7765266.742441 429318.305045 16113672.956358 7543262.315404
SIZE 1200 800
SHAPEPATH “data”
IMAGECOLOR 234 255 255
TRANSPARENT ON
FONTSET “fonts/fonts.list”
SYMBOLSET “symbols/symbols.sym”
PROJECTION
# “+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs”
“init=epsg:900913”
END
#定义图层LAYERS
END

二.墨卡托投影与wgs坐标转换

Google map 地图分块算法的解析 EPSG:900913

我下面的小伙子总是不明白map api,这块算法原理。我想很多人也一样,所以写一下说明一下哈

projection: “EPSG:900913”, //投影为 900913,google 墨卡托投影 units: “m”, //屏幕坐标以米为单位
maxResolution: 156543.0339, //最大比例下的每像素屏幕地图单位值 maxExtent: new OpenLayers.Bounds(-20037508, -20037508,20037508, 20037508.34), numZoomLevels: 17。
这是openlayer中的说明,大多人看不懂哈

解释开始:

1、先了解一个常量,世界一张图。一个像素代表多少米

世界范围,一个256*256的图 就是一个世界地图(如下)。 1个像素代表的米数就是 156543.0339。下面这图的面积就是=世界面积=156543.0339*256 * 156543.0339*256

2、其实全世界墨卡托范围是 -20037508, -20037508,20037508, 20037508.34 ,从第四象限到第一象限

其实这个值很简单,就是 -20037508 = -156543.0339*128  ; 为什么称128 呢? 因为 他是256的一半,所以一个像素*128正好代表一个象限的长度,也就是世界的一半长度。

3、切片的级别,比例尺级别

我们一般考虑切片到 18级别 ,maxZoomLevel = 18; 也就是说 世界一张图,被放大到 2的18次方倍哈。宽度、高度同时放大到2的18次方倍

我们用这个函数就可以知道 每个比例尺下,每个像素代表多少米啦。那我们18级别一个像素代表的米为:0.5971642833709717 (一像素不到一米哈)

Map.getZoomUnits = function(zoom)
{
    var zu = [0,0];
    var a = Math.pow(2,(18-zoom));
    zu[0] = 0.5971642833709717 * a;            
    zu[1] = 0.5971642833709717 * a;
    return zu;
};

4、根据墨卡托经纬度定位到x ,y ,z块号。

用点所在的墨卡托 减去 之前的基础墨卡托值,得到相对绝对距离米,再用这个 总米 / 当前比例尺每块代表的米 就知道是在哪一xy块啦

中国一般在第一象限哈

SE.Map.prototype.toMapId = function(point,zoom)
{
    var x=point.MercatorLng-156543.0339*128;
    var y=-156543.0339*128-point.MercatorLat;
    var zu = this.getZoomUnits(zoom,true);
    var spanX = zu[0]*256;//zu[0]为1px代表的纬度,this.imgSize为加载的图片大小(256)
    var spanY = zu[1]*256;//zu[1]为1px代表的经度,this.imgSize为加载的图片大小(256)
    var bx=parseInt(x/spanX);
    var by=parseInt(y/spanY);
    return [bx,by,(x-bx*spanX)/spanX*this.imgSize,(y-by*spanY)/spanY*this.imgSize];
};

附上:经纬度转84、84转经纬度 算法函数:

/**
    w84转为墨卡托坐标(经纬度转墨卡托)
    WGS84是地理坐标的一种,地理坐标本身有很多种,web墨卡托是投影坐标

    lon :    w84经度
    lat :    w84纬度
*/
PG.Tool.forwardMercator = function(lon, lat) {
    lon = parseFloat(lon);
    lat = parseFloat(lat);
    var x = lon * 20037508.34 / 180;
    var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
    y = y * 20037508.34 / 180;        
    return [x,y];
};

/**
    将墨卡托坐标转为w84(墨卡托转经纬度)

    x :    墨卡托经度
    y :    墨卡托纬度
*/
PG.Tool.inverseMercator = function(x, y) {
    var lon = (x / 20037508.34) * 180;
    var lat = (y / 20037508.34) * 180;
    lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) – Math.PI / 2);
    return [lon, lat];
};

转载自:https://blog.csdn.net/xyr05288/article/details/44196607

You may also like...