diff --git a/lib/OpenLayers/Strategy/BBOX.js b/lib/OpenLayers/Strategy/BBOX.js index 7e3b5e779c..a5a855b98d 100644 --- a/lib/OpenLayers/Strategy/BBOX.js +++ b/lib/OpenLayers/Strategy/BBOX.js @@ -19,7 +19,8 @@ OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, { /** * Property: bounds - * {} The current data bounds. + * {} The current data bounds (in the same projection + * as the layer - not always the same projection as the map). */ bounds: null, @@ -103,12 +104,29 @@ OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, { * must be incondtionally read. */ update: function(options) { - var mapBounds = this.layer.map.getExtent(); + var mapBounds = this.getMapBounds(); if ((options && options.force) || this.invalidBounds(mapBounds)) { this.calculateBounds(mapBounds); this.triggerRead(); } }, + + /** + * Method: getMapBounds + * Get the map bounds expressed in the same projection as this layer. + * + * Returns: + * {} Map bounds in the projection of the layer. + */ + getMapBounds: function() { + var bounds = this.layer.map.getExtent(); + if(!this.layer.projection.equals(this.layer.map.getProjectionObject())) { + bounds = bounds.clone().transform( + this.layer.map.getProjectionObject(), this.layer.projection + ); + } + return bounds; + }, /** * Method: invalidBounds @@ -122,7 +140,7 @@ OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, { */ invalidBounds: function(mapBounds) { if(!mapBounds) { - mapBounds = this.layer.map.getExtent(); + mapBounds = this.getMapBounds(); } return !this.bounds || !this.bounds.containsBounds(mapBounds); }, @@ -136,7 +154,7 @@ OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, { */ calculateBounds: function(mapBounds) { if(!mapBounds) { - mapBounds = this.layer.map.getExtent(); + mapBounds = this.getMapBounds(); } var center = mapBounds.getCenterLonLat(); var dataWidth = mapBounds.getWidth() * this.ratio; @@ -189,6 +207,8 @@ OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, { /** * Method: merge * Given a list of features, determine which ones to add to the layer. + * If the layer projection differs from the map projection, features + * will be transformed from the layer projection to the map projection. * * Parameters: * resp - {} The response object passed @@ -198,6 +218,17 @@ OpenLayers.Strategy.BBOX = OpenLayers.Class(OpenLayers.Strategy, { this.layer.destroyFeatures(); var features = resp.features; if(features && features.length > 0) { + var remote = this.layer.projection; + var local = this.layer.map.getProjectionObject(); + if(!local.equals(remote)) { + var geom; + for(var i=0, len=features.length; i 0) { + var remote = this.layer.projection; + var local = this.layer.map.getProjectionObject(); + if(!local.equals(remote)) { + var geom; + for(var i=0, len=features.length; i diff --git a/tests/Strategy/Fixed.html b/tests/Strategy/Fixed.html index c529435e1f..0bb8c7f90e 100644 --- a/tests/Strategy/Fixed.html +++ b/tests/Strategy/Fixed.html @@ -13,6 +13,11 @@ options.callback.call(options.scope, {features: featureList}); } }; + + // Create a dummy layer that can act as the map base layer. + // This will be unnecessary if #1920 is addressed or if base layer + // handling is changed. + var dummy = new OpenLayers.Layer(null, {isBaseLayer: true}); var layer = new OpenLayers.Layer.Vector("Vector Layer", { strategies: [new OpenLayers.Strategy.Fixed()], @@ -42,7 +47,7 @@ }); var map = new OpenLayers.Map('map'); - map.addLayers([layer, layerp, layer2]); + map.addLayers([dummy, layer, layerp, layer2]); t.ok(layer2.events.listeners["visibilitychanged"][0].obj == s && layer2.events.listeners["visibilitychanged"][0].func == s.load, @@ -54,6 +59,62 @@ t.ok(layer2.events.listeners["visibilitychanged"] == false, "visibilitychanged listener unregistered"); } + + function tests_merge(t) { + + t.plan(4); + + var strategy = new OpenLayers.Strategy.Fixed(); + + // create map with default projection + var map = new OpenLayers.Map("map"); + + // create layer with custom projection + var layer = new OpenLayers.Layer.Vector(null, { + isBaseLayer: true, + strategies: [strategy], + protocol: new OpenLayers.Protocol(), + projection: new OpenLayers.Projection("EPSG:900913") + }); + map.addLayer(layer); + map.zoomToMaxExtent(); + + // create some features + var geometries = [ + new OpenLayers.Geometry.Point(100, 200), + new OpenLayers.Geometry.Point(1000, 2000) + ]; + var features = [ + new OpenLayers.Feature.Vector(geometries[0].clone()), + new OpenLayers.Feature.Vector(geometries[1].clone()) + ]; + + // call merge with a mocked up response + strategy.merge({features: features}); + + // test that feature geometries have been transformed to map projection + var from = layer.projection; + var to = map.getProjectionObject(); + t.geom_eq(layer.features[0].geometry, features[0].geometry.transform(from, to), "[different proj] feature 0 geometry transformed"); + t.geom_eq(layer.features[1].geometry, features[1].geometry.transform(from, to), "[different proj] feature 1 geometry transformed"); + + // same as above but with same map/layer projection + layer.destroyFeatures(); + layer.projection = map.getProjectionObject(); + + features = [ + new OpenLayers.Feature.Vector(geometries[0].clone()), + new OpenLayers.Feature.Vector(geometries[1].clone()) + ]; + + // call merge again with mocked up response + strategy.merge({features: features}); + + // test that feature geometries have not been transformed + t.geom_eq(layer.features[0].geometry, features[0].geometry, "[same proj] feature 0 geometry not transformed"); + t.geom_eq(layer.features[1].geometry, features[1].geometry, "[same proj] feature 1 geometry not transformed"); + + }