[GIS] How to get OpenLayers to set the default view in EPSG:27700

mapscriptmapserveropenlayers-2ordnance-surveyweb-mapping

Disclaimer, I'm fairly new to OpenLayers, but I'm not new to JavaScript and/or Web Programming 🙂

Synopsis

I have an open layers based html page, that I'm trying to use to render a WMS map served using MapServer.

The WMS layer is the 250k Miniscale UK Ordnance survey raster map, consisting of 56 tiff tiles one for each of the major UK grid squares (e.g.: nz.tif, nu.tif and so on…)

MapServer is projecting the map from a tile index shapefile using EPSG:27700, this works perfectly in QGIS when I load it as a WMS layer, and any geometry I create, is created and located correctly even when saved using a different SRS.

However, when I try to render the same WMS layer using OpenLayers, the results are drastically different.

It doesn't matter what I attempt to do in my OpenLayers constructor I continuously get the following image:

enter image description here

I've figured out, that this is the lower left corner of the OS map (Origin 0,0 down of the coast of the Isles of Scilly where the coordinate system for EPSG:27700 starts)

If I look at the URL that OpenLayers is sending to MapServer using fiddler, this is what I see.

enter image description here

As you can see, the bounding box is always set to

BBOX = 0,-90,180,90

To me this seems very wrong, especially since you can see in the image that OpenLayers is telling MapServer that it's running using EPSG:27700

The map file used by MapServer to produce the map is as follows

MAP
    NAME "os250k"
    UNITS dd
    SIZE 640 480
    IMAGECOLOR 255 255 255
    IMAGETYPE png
    SHAPEPATH "H:\mapserver.digital-solutions.local\geodata\\"
    EXTENT 0 0 700000 1300000
    PROJECTION "init=epsg:27700" END
    WEB
      METADATA
        "ows_title" "Ordnance Survey 250k Mini Scale Map of the UK"
        "ows_onlineresource" "http://mapserver/cgi-bin/mapserv.exe?map=mapapps/os250k.map"
        "wms_version" "1.1.1"
        "wms_srs" "EPSG:27700"
        "wfs_version" "1.0.0"
        "wfs_srs" "EPSG:27700"
        "wms_enable_request" "*"
        "ows_enable_request" "*"
      END    
    END
    LAYER
        NAME "tiles"
        STATUS on
        TILEINDEX "os250.shp"
        TILEITEM "Location"
        TYPE RASTER
        PROJECTION "init=epsg:27700" END
        METADATA
            "ows_title" "Ordnance Survey Tiles for 250k Miniscale"
        END     
    END
END

The HTML code I'm using to render the map is as follows

<!doctype html">
<html>
    <head>
        <style type="text/css">
            body {
                margin: 1em;
            }
            #map {
                width: 640px;
                height: 480px;
                border: 1px solid black;
            }
        </style>
        <script src="http://openlayers.org/api/OpenLayers.js"></script>
        <script type="text/javascript">
            var zoom = 1;
            var map, layer;
            function init()
            {
                map = new OpenLayers.Map('map');
                map.projection = new OpenLayers.Projection("EPSG:27700");
                layer = new OpenLayers.Layer.WMS("UK Counties",
                "http://mapserver/cgi-bin/mapserv.exe?map=mapapps/os250k.map",
                {
                    layers: 'tiles',
                    format: 'image/png',
                    srs: 'EPSG:27700'
                });

                map.addLayer(layer);
                map.setCenter(new OpenLayers.LonLat(409447, 550814), zoom);

                //map.setCenter(new OpenLayers.LonLat(lng,lat)
                //  .transform(
                //    new OpenLayers.Projection("EPSG:4326"),
                //    new OpenLayers.Projection("EPSG:27700")
                //    ), zoom);

                //map.zoomToExtent(new OpenLayers.Bounds(minLng,minLat,maxLng,maxLat).transform("EPSG:4326", "EPSG:900913"))
                map.zoomToExtent(new OpenLayers.Bounds(407375,548966,414004,552315));

                //map.addControl(new OpenLayers.Control.LayerSwitcher() );
            }
        </script>
    </head>
    <body onload="init()">
        <h1>UK Ordnance Survey 250k Mini Scale</h1>
        <div id="map"></div>
    </body>
</html>

Yet no matter what I do, all I seem to get is that lower corner of the entire map.

What I've tried so far

Manually, I've used fiddler to grab the request and the URL to MapServer, and I've manually set the bounding box in a browser address bar to 0,0,320000,320000. Doing this produced an image that covered the Isles of Scilly and almost all of Cornwall.

This result from manual manipulation of the BBOX on the URL suggests to me that OpenLayers is indeed sending incorrect BBOX co-ordinates, or I'm not doing something I should be.

As you can (or should be able to) see from my HTML code, I've tried different values for centring the map, specifying the bounding box, I've added lines, commented lines out used snippets of code from other answers here on GIS-SE.

I've tried specifying co-ordinates in the maps projection of EPSG:27700, I'v tried setting the various co-ordinates using EPSG:4326, I've tried setting them as 4326 and transforming them to 27700 and vice versa, each time OpenLayers just seems to ignore what I'm asking it and continues to send the same set of parameters (as seen in the fiddler image above) to MapServer.

What I'm attempting to get OpenLayers to do

Zoom into a start location on my WMS layer, this location has a bounding box as follows in EPSG:27700

xMin,yMin = 407375,548966
xMax,yMax = 414004,552315

The center is somewhere around

409447,550814

I've projected the Open layers map using EPSG:27700, the WMS is serving using EPSG:27700 so I can't for the life of me understand why it's not producing the expected image (which should be centred around the town of Consett in County Durham UK.

I don't want OpenLayers to start up, loading the entire map as this is a huge map covering the entire UK which takes about 25 to 30 seconds to download on a LAN, I'm aiming for this to be rendered on a tablet eventually, so map size and amount of data downloaded is very important.

For reference, this is the exact same WMS layer, loaded into QGIS using a project set to EPSG:27700 and with the bounds and centre set as stated above

enter image description here

I'm pretty sure that it's not the map file that's to blame, but if there is a way of providing a default start point using the map script, rather than in OpenLayers then that would also be an acceptable solution.

Best Answer

And as always predictably happens......

About an hour after I post the question, I end up answering it and finding a solution.

It turns out, all I needed to add to my constructor was the following

map.maxExtent = new OpenLayers.Bounds(0,0,700000,1300000);

This was added just after setting the map projection as follows

function init()
{
  map = new OpenLayers.Map('map');
  map.projection = new OpenLayers.Projection("EPSG:27700");
  map.maxExtent = new OpenLayers.Bounds(0,0,700000,1300000); // <<-----
  layer = new OpenLayers.Layer.WMS("UK Counties",
  "http://mapserver/cgi-bin/mapserv.exe?map=mapapps/os250k.map",
  {
    layers: 'tiles',
    format: 'image/png',
    srs: 'EPSG:27700'
  });

Out of all the various posts and questions I read none of them explicitly mentioned setting this in any way, however it was actually this existing GIS-SE question that pointed me in the right direction

GeoServer WMS Layer not working in OpenLayers

My fiddling around with open layers had gotten me to a point where I got pink tiles as seen in the post, and mapserver was complaining about an incorrect SRS (I could see the response in Fiddler) I was trying to solve the SRS problem, when I noticed the set extents call.

On seeing the extents call I undid the code that got me the pink tiles, then altered my original code to include the extents call I'd just noticed making sure to set the extents correctly for my own map, and bingo...

When I refreshed the map, everything worked as expected.