From 1f745b4be956eb30872d9a7e95e60dc100a62543 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Wed, 19 Sep 2007 00:23:26 +0000 Subject: [PATCH] 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 --- lib/OpenLayers/Layer.js | 22 +++++++++++++--------- tests/Control/test_OverviewMap.html | 22 +++++++++++++++++----- tests/Layer/test_Grid.html | 22 ++++++++++++++++++---- tests/Layer/test_KaMap.html | 22 ++++++++++++++++++---- tests/Layer/test_TMS.html | 21 +++++++++++++++++---- tests/Layer/test_TileCache.html | 20 +++++++++++++++++--- tests/Layer/test_WrapDateLine.html | 18 +++++++++--------- tests/test_Layer.html | 4 +++- 8 files changed, 112 insertions(+), 39 deletions(-) diff --git a/lib/OpenLayers/Layer.js b/lib/OpenLayers/Layer.js index 42ec6a38ba..0c8e02f59f 100644 --- a/lib/OpenLayers/Layer.js +++ b/lib/OpenLayers/Layer.js @@ -736,8 +736,7 @@ OpenLayers.Layer = OpenLayers.Class({ * {Integer} The index of the zoomLevel (entry in the resolutions array) * that still contains the passed-in extent. We do this by calculating * the ideal resolution for the given exteng (based on the map size) - * and then find the smallest resolution that is greater than this - * ideal resolution. + * and then find the closest resolution to this ideal resolution. */ getZoomForExtent: function(extent) { var viewSize = this.map.getSize(); @@ -761,23 +760,28 @@ OpenLayers.Layer = OpenLayers.Class({ /** * APIMethod: getZoomForResolution + * Get the index for the closest resolution in the layers resolutions array. * * Parameters: - * resolution - {Float} + * resolution - {Float} Map units per pixel. * * Returns: * {Integer} The index of the zoomLevel (entry in the resolutions array) - * that is the smallest resolution that is greater than the passed-in - * resolution. + * that is the closest to the passed-in resolution. */ getZoomForResolution: function(resolution) { - - for(var i=1; i < this.resolutions.length; i++) { - if ( this.resolutions[i] < resolution) { + var zoom, diff; + var minDiff = Number.POSITIVE_INFINITY; + 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; } } - return (i - 1); + return zoom; }, /** diff --git a/tests/Control/test_OverviewMap.html b/tests/Control/test_OverviewMap.html index 92cd01bb94..911272757e 100644 --- a/tests/Control/test_OverviewMap.html +++ b/tests/Control/test_OverviewMap.html @@ -43,21 +43,33 @@ var overviewZoom = control.ovmap.getZoom(); t.eq(overviewCenter.lon, -71, "Overviewmap center lon 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)}); + // 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(); - t.eq(cent.lon, -71.3515625, "Clicking on the Overview Map has the correct effect on map lon"); - t.eq(cent.lat, 42.17578125, "Clicking on the Overview Map has the correct effect on map lat"); + t.ok(normalizedDiff(cent.lon, -71.00390625) < tolerance, + "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.rectMouseMove({'xy':new OpenLayers.Pixel(15,15), 'which':1}); control.rectMouseUp({'xy':new OpenLayers.Pixel(15,15), 'which':1}); var cent = map.getCenter(); - t.eq(cent.lon, -71.2734375, "Dragging on the Overview Map has the correct effect on map lon"); - t.eq(cent.lat, 42.09765625, "Dragging on the Overview Map has the correct effect on map lat"); + t.ok(normalizedDiff(cent.lon, -70.83984375) < tolerance, + "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); var overviewCenter = control.ovmap.getCenter(); diff --git a/tests/Layer/test_Grid.html b/tests/Layer/test_Grid.html index 11acc54a95..c4164bf4be 100644 --- a/tests/Layer/test_Grid.html +++ b/tests/Layer/test_Grid.html @@ -150,12 +150,26 @@ bounds = new OpenLayers.Bounds(10,10,12,12); 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); 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) { @@ -541,10 +555,10 @@ map.zoomToMaxExtent(); map.zoomIn(); 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); 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) { diff --git a/tests/Layer/test_KaMap.html b/tests/Layer/test_KaMap.html index a79bd7d50a..54c82c6fed 100644 --- a/tests/Layer/test_KaMap.html +++ b/tests/Layer/test_KaMap.html @@ -128,12 +128,26 @@ bounds = new OpenLayers.Bounds(10,10,12,12); 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); 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) { @@ -236,10 +250,10 @@ map.zoomToMaxExtent(); map.zoomIn(); 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); 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) { diff --git a/tests/Layer/test_TMS.html b/tests/Layer/test_TMS.html index dbcb54cc52..17dc55a803 100644 --- a/tests/Layer/test_TMS.html +++ b/tests/Layer/test_TMS.html @@ -77,13 +77,26 @@ bounds = new OpenLayers.Bounds(10,10,12,12); 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); 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"); } diff --git a/tests/Layer/test_TileCache.html b/tests/Layer/test_TileCache.html index db3a6a7438..78bae8d4cb 100644 --- a/tests/Layer/test_TileCache.html +++ b/tests/Layer/test_TileCache.html @@ -78,13 +78,27 @@ bounds = new OpenLayers.Bounds(10,10,12,12); 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); 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"); } diff --git a/tests/Layer/test_WrapDateLine.html b/tests/Layer/test_WrapDateLine.html index 3490322c1d..cad289f4c5 100644 --- a/tests/Layer/test_WrapDateLine.html +++ b/tests/Layer/test_WrapDateLine.html @@ -131,9 +131,9 @@ var m = new OpenLayers.Map('map'); m.addLayer(layer); 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[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][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[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%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=-90%2C270%2C0%2C360&WIDTH=256&HEIGHT=256", "cell [3][0] is not wrapped at all."); } function test_Layer_WrapDateLine_KaMap (t) { @@ -146,9 +146,9 @@ var m = new OpenLayers.Map('map'); m.addLayer(layer); 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][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[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[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=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=110735960.625", "grid[3][0] is okay"); } function test_Layer_WrapDateLine_WMS_Overlay (t) { t.plan( 3 ); @@ -163,9 +163,9 @@ var m = new OpenLayers.Map('map'); m.addLayers([baselayer,layer]); 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][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[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[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=-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%2C0%2C90%2C90&WIDTH=256&HEIGHT=256", "grid[3][0] wms overlay okay"); } diff --git a/tests/test_Layer.html b/tests/test_Layer.html index a88eb9970a..c143219a2a 100644 --- a/tests/test_Layer.html +++ b/tests/test_Layer.html @@ -155,7 +155,7 @@ function test_06_Layer_getZoomForResolution(t) { - t.plan(4); + t.plan(6); var layer = new OpenLayers.Layer('Test Layer'); @@ -163,6 +163,8 @@ layer.resolutions = [128, 64, 32, 16, 8, 4, 2]; 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(3), 5, "zoom allmost all the way in"); t.eq(layer.getZoomForResolution(1), 6, "zoom all the way in");