New behavior for layer.getZoomForResolution. This method now returns the index of the resolution closest to the passed in resolution - making for fewer unwanted resolution changes, and a generally happier populace (see #990).

git-svn-id: http://svn.openlayers.org/trunk/openlayers@4381 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
Tim Schaub
2007-09-19 00:23:26 +00:00
parent a2fabd7d17
commit 1f745b4be9
8 changed files with 112 additions and 39 deletions

View File

@@ -736,8 +736,7 @@ OpenLayers.Layer = OpenLayers.Class({
* {Integer} The index of the zoomLevel (entry in the resolutions array) * {Integer} The index of the zoomLevel (entry in the resolutions array)
* that still contains the passed-in extent. We do this by calculating * that still contains the passed-in extent. We do this by calculating
* the ideal resolution for the given exteng (based on the map size) * the ideal resolution for the given exteng (based on the map size)
* and then find the smallest resolution that is greater than this * and then find the closest resolution to this ideal resolution.
* ideal resolution.
*/ */
getZoomForExtent: function(extent) { getZoomForExtent: function(extent) {
var viewSize = this.map.getSize(); var viewSize = this.map.getSize();
@@ -761,23 +760,28 @@ OpenLayers.Layer = OpenLayers.Class({
/** /**
* APIMethod: getZoomForResolution * APIMethod: getZoomForResolution
* Get the index for the closest resolution in the layers resolutions array.
* *
* Parameters: * Parameters:
* resolution - {Float} * resolution - {Float} Map units per pixel.
* *
* Returns: * Returns:
* {Integer} The index of the zoomLevel (entry in the resolutions array) * {Integer} The index of the zoomLevel (entry in the resolutions array)
* that is the smallest resolution that is greater than the passed-in * that is the closest to the passed-in resolution.
* resolution.
*/ */
getZoomForResolution: function(resolution) { getZoomForResolution: function(resolution) {
var zoom, diff;
for(var i=1; i < this.resolutions.length; i++) { var minDiff = Number.POSITIVE_INFINITY;
if ( this.resolutions[i] < resolution) { for(var i=0; i < this.resolutions.length; i++) {
diff = Math.abs(this.resolutions[i] - resolution);
if(diff < minDiff) {
zoom = i;
minDiff = diff;
} else if(diff > minDiff) {
break; break;
} }
} }
return (i - 1); return zoom;
}, },
/** /**

View File

@@ -43,21 +43,33 @@
var overviewZoom = control.ovmap.getZoom(); var overviewZoom = control.ovmap.getZoom();
t.eq(overviewCenter.lon, -71, "Overviewmap center lon correct"); t.eq(overviewCenter.lon, -71, "Overviewmap center lon correct");
t.eq(overviewCenter.lat, 42, "Overviewmap center lat correct"); t.eq(overviewCenter.lat, 42, "Overviewmap center lat correct");
t.eq(overviewZoom, 8, "Overviewmap zoomcorrect"); t.eq(overviewZoom, 9, "Overviewmap zoomcorrect");
control.mapDivClick({'xy':new OpenLayers.Pixel(5,5)}); control.mapDivClick({'xy':new OpenLayers.Pixel(5,5)});
// There are box model issues that keep browsers from giving us
// identical results here. Test the normalized difference against
// a tolerance instead of testing equality.
function normalizedDiff(a, b) {
return Math.abs((a - b) / (a + b));
}
var tolerance = 1e-4;
var cent = map.getCenter(); var cent = map.getCenter();
t.eq(cent.lon, -71.3515625, "Clicking on the Overview Map has the correct effect on map lon"); t.ok(normalizedDiff(cent.lon, -71.00390625) < tolerance,
t.eq(cent.lat, 42.17578125, "Clicking on the Overview Map has the correct effect on map lat"); "Clicking on the Overview Map has the correct effect on map lon");
t.ok(normalizedDiff(cent.lat, 42.00390625) < tolerance,
"Clicking on the Overview Map has the correct effect on map lat");
control.rectMouseDown({'xy':new OpenLayers.Pixel(5,5), 'which':1}); control.rectMouseDown({'xy':new OpenLayers.Pixel(5,5), 'which':1});
control.rectMouseMove({'xy':new OpenLayers.Pixel(15,15), 'which':1}); control.rectMouseMove({'xy':new OpenLayers.Pixel(15,15), 'which':1});
control.rectMouseUp({'xy':new OpenLayers.Pixel(15,15), 'which':1}); control.rectMouseUp({'xy':new OpenLayers.Pixel(15,15), 'which':1});
var cent = map.getCenter(); var cent = map.getCenter();
t.eq(cent.lon, -71.2734375, "Dragging on the Overview Map has the correct effect on map lon"); t.ok(normalizedDiff(cent.lon, -70.83984375) < tolerance,
t.eq(cent.lat, 42.09765625, "Dragging on the Overview Map has the correct effect on map lat"); "Dragging on the Overview Map has the correct effect on map lon");
t.ok(normalizedDiff(cent.lat, 41.84765625) < tolerance,
"Dragging on the Overview Map has the correct effect on map lat");
map.setCenter(new OpenLayers.LonLat(0,0), 0); map.setCenter(new OpenLayers.LonLat(0,0), 0);
var overviewCenter = control.ovmap.getCenter(); var overviewCenter = control.ovmap.getCenter();

View File

@@ -150,12 +150,26 @@
bounds = new OpenLayers.Bounds(10,10,12,12); bounds = new OpenLayers.Bounds(10,10,12,12);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
t.eq( zoom, 8, "getZoomForExtent() returns correct value"); /**
* ideal resolution: 2 map units / 500px = 0.004
* layer.resolutions = [1.40625, 0.703125, 0.3515625, 0.17578125,
* 0.087890625, 0.0439453125, 0.02197265625,
* 0.010986328125, 0.0054931640625, 0.00274658203125,
* 0.001373291015625, 0.0006866455078125, 0.00034332275390625,
* 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125]
*
* So, we expect a zoom of 9 because it is the closest resolution.
*/
t.eq( zoom, 9, "getZoomForExtent() returns correct value");
bounds = new OpenLayers.Bounds(10,10,100,100); bounds = new OpenLayers.Bounds(10,10,100,100);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
t.eq( zoom, 2, "getZoomForExtent() returns correct value"); /**
* ideal resolution: 90 map units / 500px = 0.18
* So, we expect a zoom of 3 because it is the closest.
*/
t.eq( zoom, 3, "getZoomForExtent() returns correct value");
} }
function test_07_Layer_Grid_moveTo(t) { function test_07_Layer_Grid_moveTo(t) {
@@ -541,10 +555,10 @@
map.zoomToMaxExtent(); map.zoomToMaxExtent();
map.zoomIn(); map.zoomIn();
var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200)); var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200));
t.eq(bounds.toBBOX(), "-180,-90,0,90", "get tile bounds returns correct bounds"); t.eq(bounds.toBBOX(), "-90,0,0,90", "get tile bounds returns correct bounds");
map.pan(200,0); map.pan(200,0);
var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200)); var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200));
t.eq(bounds.toBBOX(), "0,-90,180,90", "get tile bounds returns correct bounds after pan"); t.eq(bounds.toBBOX(), "0,0,90,90", "get tile bounds returns correct bounds after pan");
} }
function test_Layer_Grid_moveTo_buffer_calculation (t) { function test_Layer_Grid_moveTo_buffer_calculation (t) {

View File

@@ -128,12 +128,26 @@
bounds = new OpenLayers.Bounds(10,10,12,12); bounds = new OpenLayers.Bounds(10,10,12,12);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
t.eq( zoom, 8, "getZoomForExtent() returns correct value"); /**
* ideal resolution: 2 map units / 500px = 0.004
* layer.resolutions = [1.40625, 0.703125, 0.3515625, 0.17578125,
* 0.087890625, 0.0439453125, 0.02197265625,
* 0.010986328125, 0.0054931640625, 0.00274658203125,
* 0.001373291015625, 0.0006866455078125, 0.00034332275390625,
* 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125]
*
* So, we expect a zoom of 9 because it is the closest resolution.
*/
t.eq( zoom, 9, "getZoomForExtent() returns correct value");
bounds = new OpenLayers.Bounds(10,10,100,100); bounds = new OpenLayers.Bounds(10,10,100,100);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
t.eq( zoom, 2, "getZoomForExtent() returns correct value"); /**
* ideal resolution: 90 map units / 500px = 0.18
* So, we expect a zoom of 3 because it is the closest.
*/
t.eq( zoom, 3, "getZoomForExtent() returns correct value");
} }
function test_06_Layer_kaMap_mergeNewParams (t) { function test_06_Layer_kaMap_mergeNewParams (t) {
@@ -236,10 +250,10 @@
map.zoomToMaxExtent(); map.zoomToMaxExtent();
map.zoomIn(); map.zoomIn();
var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200)); var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200));
t.eq(bounds.toBBOX(), "-180,0,0,180", "get tile bounds returns correct bounds"); t.eq(bounds.toBBOX(), "-90,0,0,90", "get tile bounds returns correct bounds");
map.pan(200,0); map.pan(200,0);
var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200)); var bounds = layer.getTileBounds(new OpenLayers.Pixel(200,200));
t.eq(bounds.toBBOX(), "0,0,180,180", "get tile bounds returns correct bounds after pan"); t.eq(bounds.toBBOX(), "0,0,90,90", "get tile bounds returns correct bounds after pan");
} }
function test_99_Layer_KaMap_destroy (t) { function test_99_Layer_KaMap_destroy (t) {

View File

@@ -77,13 +77,26 @@
bounds = new OpenLayers.Bounds(10,10,12,12); bounds = new OpenLayers.Bounds(10,10,12,12);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
/**
t.eq( zoom, 8, "getZoomForExtent() returns correct value"); * ideal resolution: 2 map units / 500px = 0.004
* layer.resolutions = [1.40625, 0.703125, 0.3515625, 0.17578125,
* 0.087890625, 0.0439453125, 0.02197265625,
* 0.010986328125, 0.0054931640625, 0.00274658203125,
* 0.001373291015625, 0.0006866455078125, 0.00034332275390625,
* 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125]
*
* So, we expect a zoom of 9 because it is the closest resolution.
*/
t.eq( zoom, 9, "getZoomForExtent() returns correct value");
bounds = new OpenLayers.Bounds(10,10,100,100); bounds = new OpenLayers.Bounds(10,10,100,100);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
/**
t.eq( zoom, 2, "getZoomForExtent() returns correct value"); * ideal resolution: 90 map units / 500px = 0.18
* So, we expect a zoom of 3 because it is the closest.
*/
t.eq( zoom, 3, "getZoomForExtent() returns correct value");
} }

View File

@@ -78,13 +78,27 @@
bounds = new OpenLayers.Bounds(10,10,12,12); bounds = new OpenLayers.Bounds(10,10,12,12);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
/**
t.eq( zoom, 7, "getZoomForExtent() returns correct value"); * ideal resolution: 2 map units / 500px = 0.004
* layer.resolutions = [0.703125, 0.3515625, 0.17578125,
* 0.087890625, 0.0439453125, 0.02197265625,
* 0.010986328125, 0.0054931640625, 0.00274658203125,
* 0.001373291015625, 0.0006866455078125, 0.00034332275390625,
* 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125,
* 0.000021457672119140625]
*
* So, we expect a zoom of 8 because it is the closest resolution.
*/
t.eq( zoom, 8, "getZoomForExtent() returns correct value");
bounds = new OpenLayers.Bounds(10,10,100,100); bounds = new OpenLayers.Bounds(10,10,100,100);
zoom = layer.getZoomForExtent(bounds); zoom = layer.getZoomForExtent(bounds);
/**
* ideal resolution: 90 map units / 500px = 0.18
* So, we expect a zoom of 2 because it is the closest.
*/
t.eq( zoom, 1, "getZoomForExtent() returns correct value"); t.eq( zoom, 2, "getZoomForExtent() returns correct value");
} }

View File

@@ -131,9 +131,9 @@
var m = new OpenLayers.Map('map'); var m = new OpenLayers.Map('map');
m.addLayer(layer); m.addLayer(layer);
m.zoomToMaxExtent(); m.zoomToMaxExtent();
t.eq(layer.grid[3][0].url, "http://octo.metacarta.com/cgi-bin/mapserv?MAP=%2Fmapdata%2Fvmap_wms.map&LAYERS=basic&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C-90%2C180%2C90&WIDTH=256&HEIGHT=256", "cell [3][0] is wrapped around the world."); t.eq(layer.grid[3][0].url, "http://octo.metacarta.com/cgi-bin/mapserv?MAP=%2Fmapdata%2Fvmap_wms.map&LAYERS=basic&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C0%2C90%2C90&WIDTH=256&HEIGHT=256", "cell [3][0] is wrapped around the world.");
t.eq(layer.grid[0][0].url, "http://octo.metacarta.com/cgi-bin/mapserv?MAP=%2Fmapdata%2Fvmap_wms.map&LAYERS=basic&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C450%2C180%2C630&WIDTH=256&HEIGHT=256", "cell [0][0] is wrapped around the world lon, but not lat"); t.eq(layer.grid[0][0].url, "http://octo.metacarta.com/cgi-bin/mapserv?MAP=%2Fmapdata%2Fvmap_wms.map&LAYERS=basic&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C270%2C90%2C360&WIDTH=256&HEIGHT=256", "cell [0][0] is wrapped around the world lon, but not lat");
t.eq(layer.grid[0][3].url, "http://octo.metacarta.com/cgi-bin/mapserv?MAP=%2Fmapdata%2Fvmap_wms.map&LAYERS=basic&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=-180%2C450%2C0%2C630&WIDTH=256&HEIGHT=256", "cell [3][0] is not wrapped at all."); t.eq(layer.grid[0][3].url, "http://octo.metacarta.com/cgi-bin/mapserv?MAP=%2Fmapdata%2Fvmap_wms.map&LAYERS=basic&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=-90%2C270%2C0%2C360&WIDTH=256&HEIGHT=256", "cell [3][0] is not wrapped at all.");
} }
function test_Layer_WrapDateLine_KaMap (t) { function test_Layer_WrapDateLine_KaMap (t) {
@@ -146,9 +146,9 @@
var m = new OpenLayers.Map('map'); var m = new OpenLayers.Map('map');
m.addLayer(layer); m.addLayer(layer);
m.zoomToMaxExtent(); m.zoomToMaxExtent();
t.eq(layer.grid[0][0].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=-1280&l=0&s=221471921.25", "grid[0][0] kamap is okay"); t.eq(layer.grid[0][0].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=-1280&l=0&s=110735960.625", "grid[0][0] kamap is okay");
t.eq(layer.grid[0][3].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=-1280&l=-256&s=221471921.25", "grid[0][3] kamap is okay"); t.eq(layer.grid[0][3].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=-1280&l=-256&s=110735960.625", "grid[0][3] kamap is okay");
t.eq(layer.grid[3][0].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=-512&l=0&s=221471921.25", "grid[3][0] is okay"); t.eq(layer.grid[3][0].url, "http://www.openlayers.org/world/index.php?g=satellite&map=world&i=jpeg&t=-512&l=0&s=110735960.625", "grid[3][0] is okay");
} }
function test_Layer_WrapDateLine_WMS_Overlay (t) { function test_Layer_WrapDateLine_WMS_Overlay (t) {
t.plan( 3 ); t.plan( 3 );
@@ -163,9 +163,9 @@
var m = new OpenLayers.Map('map'); var m = new OpenLayers.Map('map');
m.addLayers([baselayer,layer]); m.addLayers([baselayer,layer]);
m.zoomToMaxExtent(); m.zoomToMaxExtent();
t.eq(layer.grid[0][0].url, "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?LAYERS=bathymetry%2Cland_fn%2Cpark%2Cdrain_fn%2Cdrainage%2Cprov_bound%2Cfedlimit%2Crail%2Croad%2Cpopplace&TRANSPARENT=true&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C450%2C180%2C630&WIDTH=256&HEIGHT=256", "grid[0][0] wms overlay is okay"); t.eq(layer.grid[0][0].url, "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?LAYERS=bathymetry%2Cland_fn%2Cpark%2Cdrain_fn%2Cdrainage%2Cprov_bound%2Cfedlimit%2Crail%2Croad%2Cpopplace&TRANSPARENT=true&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C270%2C90%2C360&WIDTH=256&HEIGHT=256", "grid[0][0] wms overlay is okay");
t.eq(layer.grid[0][3].url, "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?LAYERS=bathymetry%2Cland_fn%2Cpark%2Cdrain_fn%2Cdrainage%2Cprov_bound%2Cfedlimit%2Crail%2Croad%2Cpopplace&TRANSPARENT=true&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=-180%2C450%2C0%2C630&WIDTH=256&HEIGHT=256", "grid[0][3] wms overlay is okay"); t.eq(layer.grid[0][3].url, "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?LAYERS=bathymetry%2Cland_fn%2Cpark%2Cdrain_fn%2Cdrainage%2Cprov_bound%2Cfedlimit%2Crail%2Croad%2Cpopplace&TRANSPARENT=true&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=-90%2C270%2C0%2C360&WIDTH=256&HEIGHT=256", "grid[0][3] wms overlay is okay");
t.eq(layer.grid[3][0].url, "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?LAYERS=bathymetry%2Cland_fn%2Cpark%2Cdrain_fn%2Cdrainage%2Cprov_bound%2Cfedlimit%2Crail%2Croad%2Cpopplace&TRANSPARENT=true&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C-90%2C180%2C90&WIDTH=256&HEIGHT=256", "grid[3][0] wms overlay okay"); t.eq(layer.grid[3][0].url, "http://www2.dmsolutions.ca/cgi-bin/mswms_gmap?LAYERS=bathymetry%2Cland_fn%2Cpark%2Cdrain_fn%2Cdrainage%2Cprov_bound%2Cfedlimit%2Crail%2Croad%2Cpopplace&TRANSPARENT=true&FORMAT=image%2Fpng&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&STYLES=&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&SRS=EPSG%3A4326&BBOX=0%2C0%2C90%2C90&WIDTH=256&HEIGHT=256", "grid[3][0] wms overlay okay");
} }
</script> </script>

View File

@@ -155,7 +155,7 @@
function test_06_Layer_getZoomForResolution(t) { function test_06_Layer_getZoomForResolution(t) {
t.plan(4); t.plan(6);
var layer = new OpenLayers.Layer('Test Layer'); var layer = new OpenLayers.Layer('Test Layer');
@@ -163,6 +163,8 @@
layer.resolutions = [128, 64, 32, 16, 8, 4, 2]; layer.resolutions = [128, 64, 32, 16, 8, 4, 2];
t.eq(layer.getZoomForResolution(200), 0, "zoom all the way out"); t.eq(layer.getZoomForResolution(200), 0, "zoom all the way out");
t.eq(layer.getZoomForResolution(65), 1, "index closest to 65");
t.eq(layer.getZoomForResolution(63), 1, "index closest to 63");
t.eq(layer.getZoomForResolution(25), 2, "zoom in middle"); t.eq(layer.getZoomForResolution(25), 2, "zoom in middle");
t.eq(layer.getZoomForResolution(3), 5, "zoom allmost all the way in"); t.eq(layer.getZoomForResolution(3), 5, "zoom allmost all the way in");
t.eq(layer.getZoomForResolution(1), 6, "zoom all the way in"); t.eq(layer.getZoomForResolution(1), 6, "zoom all the way in");