1

OpenLayers 2 has a layer subclass called OpenLayers.Layer.ArcGIS93Rest which is great but it is passing BBOX parameter in Google Projection (EPSG:900913) which is what my base layer uses, instead of transforming it from the map projection to the layer's projection (in this case 102656). Even if I change the layer's projection, the URL generated tells the server of its correct projection, but the BBOX is NOT in this projection :-(

I have no control over the projection of the server maps. So I cannot change the server.

Here is an example - it is using the CT State Plane projection...

    var layerB = new OpenLayers.Layer.ArcGIS93Rest("My new layer",
        myMapserverExportURL, //Note this ends with 'MapServer/export'
        {
            layers: "show:6,7,9",
            srs: 'EPSG:102656',
            TRANSPARENT: "true"
        },
        {
            isBaseLayer: false,
            visibility: false,
            resolutions: this.getScales(6, 11)
        });
    layerB.projection = new OpenLayers.Projection("EPSG:102656");
    map.addLayer(layerB);
1

I've experimentally fixed this, but it involved changing the default getURL function defined in the OpenLayers.Layer.ArcGIS93Rest class.

Here is that function with the lines I've changed. Not sure if it would make sense to make this a permanent change to the openlayers 2.0 code? This comes from the release 2.13.1 version of the debug version of openlayers 2, the getURL function def in class ArcGIS93Rest.
Look for comments starting with ////

You will see that I added some code to clone the bounds to bounds2, and I use bounds2 to transform the BBOX if necessary. Transforming the bounds passed in has side effects.

...
/**
 * Method: getURL
 * Return an image url this layer.
 *
 * Parameters:
 * bounds - {<OpenLayers.Bounds>} A bounds representing the bbox for the
 *                                request.
 *
 * Returns:
 * {String} A string with the map image's url.
 */
getURL: function (bounds) {
    bounds = this.adjustBounds(bounds);

    // ArcGIS Server only wants the numeric portion of the projection ID.
    var projWords = this.projection.getCode().split(":");
    var srid = projWords[projWords.length - 1];

    //// +++ Added Code Here: if layer proj is different from map proj, then transform the bbox bounds
    var bounds2 = bounds.clone();
    if (this.projection.projCode != this.map.projection.projCode) {
        // this will do in-place transformation: bounds.transform(source,dest)
        bounds2.transform(this.map.projection, this.projection);
    }
    //// +++ End of Added Code: if layer proj is different from map proj, then transform the bbox bounds

    var imageSize = this.getImageSize(); 
    var newParams = {
        'BBOX': bounds2.toBBOX(),  //// NOTE: now use bounds2, which was transformed if necesssary
        'SIZE': imageSize.w + "," + imageSize.h,
        // We always want image, the other options were json, image with a whole lotta html around it, etc.
        'F': "image",
        'BBOXSR': srid,
        'IMAGESR': srid
    };

    // Now add the filter parameters.
    if (this.layerDefs) {
        var layerDefStrList = [];
        var layerID;
        for(layerID in this.layerDefs) {
            if (this.layerDefs.hasOwnProperty(layerID)) {
                if (this.layerDefs[layerID]) {
                    layerDefStrList.push(layerID);
                    layerDefStrList.push(":");
                    layerDefStrList.push(this.layerDefs[layerID]);
                    layerDefStrList.push(";");
                }
            }
        }
        if (layerDefStrList.length > 0) {
            newParams['LAYERDEFS'] = layerDefStrList.join("");
        }
    }
    var requestString = this.getFullRequestString(newParams);
    return requestString;
},
...

So, this has the desired effect! The layer now displays correctly over my basemap.

Rather than actually changing the code though, I will simply take the code below and create my own function, and then simply set the getURL property of this layer to my altered version of the function.

Like this:

    var layerB = new OpenLayers.Layer.ArcGIS93Rest("My new layer",
        myMapserverExportURL, //Note this ends with 'MapServer/export'
        {
            layers: "show:6,7,9",
            srs: 'EPSG:102656',
            TRANSPARENT: "true"
        },
        {
            getURL: myNewGetURLFunction,
            isBaseLayer: false,
            visibility: false,
            resolutions: this.getScales(6, 11)
        });
    layerB.projection = new OpenLayers.Projection("EPSG:102656");
    map.addLayer(layerB);

function myNewGetURLFunction(bounds) {
...  See above 
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.