Road Overlay on Google Vector in Forbidden City and Tiananmen, Beijing, China

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);