[GIS] Reproject a vector layer (EPSG:27700) using WFS onto a googlemaps background (EPSG:900913)

geoserveropenlayers-2vectorwfs

I have the following HTML-JavaScript code and I have problems re-projecting the vector layer (WFS) from EPSG:27700 (British National Grid) to EPSG:900913 (Google Maps).

I managed to project the WMS layer but I have difficulties with the WFS.

With what I have read so far, to perform this re-projection you need "GeoJSON" and "Proj4js".

There is no much documentation and examples using these 2 features.

One more thing to add is that using the existing WFS coding I managed to
project the "Tasmanian" layers that already exist in GeoServer. But these are on a different projecting system (EPSG:4326)

Code is the following:

<html>
<head>
    <style>
            html,body {
                    height: 99%;
                    width: 99%;
            }
            #map {
                    width: 80%;
                    height: 80%;
                    border: 1px solid black;
            }
    </style>
<title>OpenLayers: Google Layer Example</title>
<link rel="stylesheet" href="http://openlayers.org/api/theme/default/style.css" type="text/css" />
<link rel="stylesheet" href="http://openlayers.org/dev/examples/style.css" type="text/css" />
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<script src="http://www.openstreetmap.org/openlayers/OpenStreetMap.js"></script>
<script src="http://maps.google.com/maps/api/js?v=3.2&amp;sensor=false"></script>
<script src="http://ecn.dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2 mkt=en-us"></script>
<script src="http://developers.cloudmade.com/attachments/download/58/cloudmade.js"></script>
<script src="http://proj4js.org/lib/proj4js-compressed.js"></script>
<script type="text/javascript">
    Proj4js.defs["EPSG: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 +no_defs";
    Proj4js.defs["EPSG:27700"] = "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs";
    Proj4js.defs["EPSG:4326"] = "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs";

  function init() {
    //set up projections
    // World Geodetic System 1984 projection
    var WGS84 = new OpenLayers.Projection("EPSG:4326");

    // WGS84 Google Mercator projection
    var WGS84_google_mercator = new OpenLayers.Projection("EPSG:900913");

    // OS British National Grid
    var os = new OpenLayers.Projection("EPSG:27700");

            //Initialize the map
            var map = new OpenLayers.Map ("map", {
                    controls:[
                            //allows the user pan ability
                            new OpenLayers.Control.Navigation(),
                            //displays the pan/zoom tools
                            new OpenLayers.Control.PanZoomBar(),
                            //displays a layer switcher
                            new OpenLayers.Control.LayerSwitcher(),

                    ],
                            projection: WGS84_google_mercator,
                        displayProjection: WGS84
            } );

            //base layers
            var openstreetmap = new OpenLayers.Layer.OSM();

            var cloudmade = new OpenLayers.Layer.CloudMade("CloudMade", {
                key: 'BC9A493B41014CAABB98F0471D759707'}
            );

            var google_maps = new OpenLayers.Layer.Google("Google Maps", {
        numZoomLevels: 20}
    );
            var google_satellite = new OpenLayers.Layer.Google("Google Satellite", 
                    {
                    type: google.maps.MapTypeId.SATELLITE,
                    'sphericalMercator': true,
                    buffer:0,
                    numZoomLevels: 20}
            );
            var bing_shaded = new OpenLayers.Layer.VirtualEarth("Bing Maps", 
            {
                     type: VEMapStyle.Shaded,
                    'sphericalMercator': true,
                     numZoomLevels: 20}
            );
    var bing_hybrid = new OpenLayers.Layer.VirtualEarth("Bing Satellite", {
        type: VEMapStyle.Hybrid,
               'sphericalMercator': true,
        numZoomLevels: 20}
        );
    var bing_aerial = new OpenLayers.Layer.VirtualEarth("Bing Aerial", {
        type: VEMapStyle.Aerial,
                    'sphericalMercator': true,
        numZoomLevels: 20}
        );

            // WMS Layers for the projection of the shapefiles
            var layer1 = new OpenLayers.Layer.WMS( "National Parks",
                        "http://localhost:8080/geoserver/wms",
                      {
                        srs: 'EPSG:4326',
                            layers: 'National_Parks',
                            transparent: 'true',
                            format: 'image/png',
                            buffer:0
                      },
                      {
                            'singleTile': true, 'ratio': 1, 'opacity': 0.75, 'isBaseLayer': false, 'wrapDateLine': false,'transitionEffect':'resize', displayInLayerSwitcher : true, 'alwaysInRange': true, 'displayOutsideMaxExtent':true
                      }
                      );

            // WFS Layers for the projection of the shapefiles
            var wfslayer = new OpenLayers.Layer.Vector("National Parks in GB",
            {
            strategies: [new OpenLayers.Strategy.BBOX()],
            protocol: new OpenLayers.Protocol.WFS({
          url:  "http://localhost:8080/geoserver/wfs",
                      //featureType: "tasmania_state_boundaries",
                      featureType: "National_Parks",
                      //featureNS: "http://www.openplans.org/topp",
                      featureNS: "http://opengeo.org/protec_are",
                      version: "1.1.0",
          srsName: "EPSG:900913",
          })
                    });

                            //transformation between coordinate systems (27700 to 900913)
                            var format = new OpenLayers.Format.GeoJSON({
                            'internalProjection': new OpenLayers.Projection("EPSG:900913"),
                            'externalProjection': new OpenLayers.Projection("EPSG:27700")
                            });


                            var newfeatures = format.write(wfslayer.features);
                            var newlayer = new OpenLayers.Layer.Vector("newlayer");
                        newlayer.addFeatures(format.read(newfeatures));


            // Display the layers on the map
            map.addLayers([openstreetmap, cloudmade, google_maps, google_satellite,bing_shaded, bing_hybrid, bing_aerial, layer1, newlayer]);

            var mapextent = new OpenLayers.Bounds(-16.08,49.06,6.76,58.74).transform(map.displayProjection, map.baseLayer.projection);
    map.zoomToExtent(mapextent);

    }

</script>
</head>
<body onload="init()">
<h1 id="title">OpenLayers: Google Layer Example</h1>
<div id="map" </div>
<div id="coordinates"></div>
</body>
</html>

Thanks a lot for the information guys.

Senthil I made the changes that you suggested and I managed to get the layer on the screen.

As quite a lot of people might have the same problem I would like to summarise some important things.

–> If the web page(HTML) containing the map (comment from 'iant') that you are creating exists on the same server as WFS/GeoServer (e.g when you use the same PC) then you don't need to use proxy.

–> For conversion between projection systems (e.g. from EPSG:27700 to EPSG:900913) you don't need Proj4Js or GeoJSON. WFS Version 1.1.0 will do the trick.

–> Do not run the HTML web page as a file by double clicking on it (e.g file:///E:/GISWork/GISApplication/Geoserver-2.0.3/data_dir/www/GIS.html)
but run it through the server (e.g http://localhost:8080/geoserver/www/GIS.html)
otherwise you won't be able to see the layer on the screen.

Best Answer

I have done EPSG:2193 to EPSG:900913 for WMS and WFS with Geoserver - Google layers through Openlayers. You donot need to have Proj4Js or GeoJson (it can be used to set the format, but GML format is fine too).

Remove all unnecessary javascripts inlcuded and create Openlayer Map as below:

var map = new OpenLayers.Map ("map", {
                projection: new OpenLayers.Projection('EPSG:900913'), 
               controls: []
           } );

// Add controller as needed.

   var wfslayer = new OpenLayers.Layer.Vector(layerName, {
        strategies: [new OpenLayers.Strategy.BBOX()],
        reportError: true,
        visibility: true,           
        protocol: new OpenLayers.Protocol.WFS({
                           url:  "http://localhost:8080/geoserver/wfs",
                           featureType: "National_Parks",
                           featureNS: "http://opengeo.org/protec_are",
                           version: "1.1.0",
                           srsName: "EPSG:900913",
                })
    });

    this.map.addLayer(wfslayer);

Make sure GeoServer has workspace 'Namespace URI' as http://opengeo.org/protec_are

Try to debug with Firebug and check the response for WFS call.