OpenLayers + Google Spherical Mercator Example
I’ve been a dormant user of OpenLayers for months (4 months?) now and it was a surprise that the svn trunk had huge differences from what I remember OL (2.4/5?) to be. One of the cool features that and the OpenLayers community contributed was the Google Speherical Mercator hack. Below is a quick step tutorial on how I was able to overlay a custom WMS to Google (set as the baselayer). For this tutorial, I want to overlay a road layer on top of Google.
1. We need to convert our data to Google Projection (Spatial Reference System: 900913). This applies to whatever kind of data (mine is vector stored both in Mapinfo and PostGis) we have. For PostGis, we need to:
INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, proj4text, srtext) VALUES ( 900913, 'spatialreference.org', 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', 'PROJCS ["unnamed",GEOGCS["unnamed ellipse",DATUM["unknown",SPHEROID["unnamed",6378137,0]],PRIMEM ["Greenwich",0],UNIT["degree",0.0174532925199433]],PROJECTION["Mercator_2SP"],PARAMETER ["standard_parallel_1",0],PARAMETER["central_meridian",0],PARAMETER ["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1],EXTENSION ["PROJ4","+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"]]'); SELECT AddGeometryColumn('public','roads','the_geom_google',900913,'LINESTRING',2); UPDATE roads SET the_geom_google = Transform(the_geom, 900913); |
2. MapFile Settings courtesy of SpatialReference: Google Projection
WEB #Other Web Config Settings goes here... "wms_srs" "EPSG:900913" END 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" END |
3. By ensuring that Mapserver has the new 900913 projection, problems such as “msWMSLoadGetMapParams(): WMS server error. Invalid SRS given : SRS must be valid for all requested layers.” or “msProcessProjection(): Projection library error. no options found in ‘init’ file” will be avoided.
cd /ms4w/proj/nad/ gvim epsg # GCS Voirol 1875 Degree <104304> +proj=longlat +a=6378249.2 +b=6356514.999904194 no_defs <> # GCS Voirol Unifie 1960 Degree <104305> +proj=longlat +ellps=clrk80 no_defs <> # Google Spherical 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 |
4. Below is an example WMS Request. Note: “SRS=EPSG 900913″ is added; TRANSPARENT=true not TRANSPARENT=on; Check your BBOX settings for the correct extent.
http://127.0.0.1/cgi-bin/mapserv? LAYERS=beijing_all &MAP=%2Fhome%2Fmap%2Fbeijing%2Fnew%2Fbeijing_google.map &FORMAT=AGG &TRANSPARENT=true &SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap &STYLES= &EXCEPTIONS=application%2Fvnd.ogc.se_inimage &SRS=EPSG%3A900913 &BBOX=12956687.788758555,4852222.554861524,12956993.536871642,4852528.30297461 &WIDTH=256&HEIGHT=256 |
5. Requesting the WMS from OpenLayers.
var options = { projection: "EPSG:900913", units: "m", //maxResolution: 156543.0339, numZoomLevels: 18, maxExtent: new OpenLayers.Bounds(12823075.86334, 4800551.12375, 13101918.14248, 021301.26141) }; // avoid pink tiles OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3; OpenLayers.Util.onImageLoadErrorColor = "transparent"; map = new OpenLayers.Map('mapdiv',options); sat_wms = new OpenLayers.Layer.Google( "Layer", {type: G_SATELLITE_MAP,'sphericalMercator': true} ); map.addLayer(sat_wms); // start custom layer here var layer_obj = new OpenLayers.Layer.WMS( "Beijing", "http://127.0.0.1/cgi-bin/mapserv", { layers: 'beijing_all', map: '/home/map/beijing/new/beijing_google.map', format: 'AGG', 'transparent': 'true' } ); layer_obj.setIsBaseLayer(false); layer_obj.setVisibility(true); map.addLayer(layer_obj); map.addControl(new OpenLayers.Control.MousePosition()); map.addControl(new OpenLayers.Control.LayerSwitcher()); map.addControl(new OpenLayers.Control.Scale()); var center = new OpenLayers.LonLat(12956625.68367, 4852316.90682); map.setCenter(center, 17); |