- Removed unnecessary accessors from OpenLayers.Layer: getProjection(),

getMaxExtent(), getMaxResolution(), and getNumZoomLevels(). They were just 
   wrapping around the properties. better to just access the property directly. 
   Needed to update for these removals in many different files. 

- Improved initResolutions() functionality. It is now I believe both thorough
   and complete. The only exception is that we should maybe allow a way for 
   the user to set up resolutions[] array using only minResolution and 
   numZoomLevels instead of only maxResolution and numZoomLevels... but I'm not
   really sure anyone would ever really want to use that. And at any rate, I
   don't know the math for how to do it. I'm sure schuyler or Dr. 5 would.
   Oh. for a summary of how initResolutions works, see:
   http://trac.openlayers.org/wiki/SettingZoomLevels

- Move getResolution(), initResolutions() out of HTTPRequest and into Layer. On 
   thinking this through (and trying to write documentation), I realized that 
   the real, true, GENERIC case for a layer will be using this awesome 
   resolutions[] array that allows for setting number of zoom levels, default 
   max resolutions, special scale arrays, etc. 

- Updated code for getZoomForExtent() to work with resolutions[] array, instead 
   of using the the log 2 equation. 

- Move standard getZoomForExtent() and getExtent() out of Grid and into 
   Layer. Like above, there is no reason for these methods to be found so far
   down in the food chain. They are part of the generic calculations for 
   generic layers, so they belong in Layer. 



git-svn-id: http://svn.openlayers.org/trunk/openlayers@1379 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
euzuro
2006-08-26 02:51:38 +00:00
parent a8891101d6
commit f582775d11
14 changed files with 283 additions and 263 deletions

View File

@@ -67,6 +67,7 @@ if (typeof(_OPENLAYERS_SFL_) == "undefined") {
"OpenLayers/Tile/Image.js",
"OpenLayers/Tile/WFS.js",
"OpenLayers/Layer/EventPane.js",
"OpenLayers/Layer/FixedZoomLevels.js",
"OpenLayers/Layer/Google.js",
"OpenLayers/Layer/VirtualEarth.js",
// "OpenLayers/Layer/Yahoo.js",

View File

@@ -43,13 +43,28 @@ OpenLayers.Layer.prototype = {
/** @type String */
projection: null,
/** @type String */
units: null,
/** @type Array */
scales: null,
/** @type Array */
resolutions: null,
/** @type OpenLayers.Bounds */
maxExtent: null,
/** @type OpenLayers.Bounds */
minExtent: null,
/** @type float */
maxResolution: null,
/** @type float */
minResolution: null,
/** @type int */
numZoomLevels: null,
@@ -59,8 +74,6 @@ OpenLayers.Layer.prototype = {
/** @type float */
maxScale: null,
/** @type String */
units: null,
/**
* @constructor
@@ -190,6 +203,9 @@ OpenLayers.Layer.prototype = {
this[properties[i]] = this.map[properties[i]];
}
}
if (this.isBaseLayer) {
this.initResolutions();
}
},
/**
@@ -220,15 +236,6 @@ OpenLayers.Layer.prototype = {
}
},
/********************************************************/
/* */
/* Layer Options */
/* */
/* Accessor functions to Layer Options parameters */
/* */
/********************************************************/
/**
* @param {Boolean} isBaseLayer
*/
@@ -238,58 +245,96 @@ OpenLayers.Layer.prototype = {
this.map.events.triggerEvent("changelayer");
}
},
/**
* @type String
*/
getProjection: function() {
return this.projection;
},
/**
* @type OpenLayers.Bounds
*/
getMaxExtent: function() {
return this.maxExtent;
},
/**
* @type float
*/
getMaxResolution: function() {
return this.maxResolution;
},
/**
* @returns The total number of zoom levels this layer can reach
* @type int
*/
getNumZoomLevels: function() {
return this.numZoomLevels;
},
/********************************************************/
/* */
/* Baselayer Functions */
/* */
/* The following functions must all be implemented */
/* by all base layers */
/* */
/********************************************************/
/**
* @returns Degrees per Pixel
/** This method's responsibility is to set up the 'resolutions' array
* for the layer -- this array is what the layer will use to interface
* between the zoom levels of the map and the resolution display of the
* layer.
*
* The user has several options that determine how the array is set up.
*
* For a detailed explanation, see the following wiki from the
* openlayers.org homepage:
*
* http://trac.openlayers.org/wiki/SettingZoomLevels
*
* @private
*/
initResolutions: function() {
if ((this.scales != null) || (this.resolutions != null)) {
//preset levels
if (this.scales != null) {
this.resolutions = new Array();
for(var i = 0; i < this.scales.length; i++) {
this.resolutions[i] =
OpenLayers.Util.getResolutionFromScale(this.scales[i],
this.units);
}
}
this.numZoomLevels = this.resolutions.length;
} else {
//maxResolution and numZoomLevels
this.resolutions = new Array();
// determine maxResolution
if (this.minScale) {
this.maxResolution =
OpenLayers.Util.getResolutionFromScale(this.minScale,
this.units);
} else if (this.maxResolution == "auto") {
var viewSize = this.map.getSize();
var wRes = this.maxExtent.getWidth() / viewSize.w;
var hRes = this.maxExtent.getHeight()/ viewSize.h;
this.maxResolution = Math.max(wRes, hRes);
}
// determine minResolution
if (this.maxScale != null) {
this.minResolution =
OpenLayers.Util.getResolutionFromScale(this.maxScale);
} else if ((this.minResolution == "auto") &&
(this.minExtent != null)){
var viewSize = this.map.getSize();
var wRes = this.minExtent.getWidth() / viewSize.w;
var hRes = this.minExtent.getHeight()/ viewSize.h;
this.minResolution = Math.max(wRes, hRes);
}
// determine numZoomLevels
if (this.minResolution != null) {
var ratio = this.maxResolution / this.minResolution;
this.numZoomLevels =
Math.floor(Math.log(ratio) / Math.log(2)) + 1;
}
// now we have numZoomLevels and maxResolution,
// we can populate the resolutions array
for (var i=0; i < this.numZoomLevels; i++) {
this.resolutions.push(this.maxResolution / Math.pow(2, i));
}
}
},
/**
* @returns The currently selected resolution of the map, taken from the
* resolutions array, indexed by current zoom level.
* @type float
*/
getResolution: function() {
var viewSize = this.map.getSize();
var extent = this.getExtent();
return Math.max( extent.getWidth() / viewSize.w,
extent.getHeight() / viewSize.h );
var zoom = this.map.getZoom();
return this.resolutions[zoom];
},
/** Calculates using px-> lonlat translation functions on tl and br
* corners of viewport
/** Calculates based on resolution, center, and mapsize
*
* @returns A Bounds object which represents the lon/lat bounds of the
* current viewPort.
@@ -297,34 +342,55 @@ OpenLayers.Layer.prototype = {
*/
getExtent: function () {
var extent = null;
var size = this.map.getSize();
var tlPx = new OpenLayers.Pixel(0,0);
var tlLL = this.getLonLatFromViewPortPx(tlPx);
var brPx = new OpenLayers.Pixel(size.w, size.h);
var brLL = this.getLonLatFromViewPortPx(brPx);
if ((tlLL != null) && (brLL != null)) {
extent = new OpenLayers.Bounds(tlLL.lon,
brLL.lat,
brLL.lon,
tlLL.lat);
var center = this.map.getCenter();
if (center != null) {
var res = this.getResolution();
var size = this.map.getSize();
var w_deg = size.w * res;
var h_deg = size.h * res;
extent = new OpenLayers.Bounds(center.lon - w_deg / 2,
center.lat - h_deg / 2,
center.lon + w_deg / 2,
center.lat + h_deg / 2);
}
return extent;
},
/**
* @param {OpenLayers.Bounds} bounds
*
* @returns 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.
* @type int
*/
getZoomForExtent: function(extent) {
var viewSize = this.map.getSize();
var idealResolution = Math.max( extent.getWidth() / viewSize.w,
extent.getHeight() / viewSize.h );
for(var i=1; i <= this.resolutions.length; i++) {
if ( this.resolutions[i] < idealResolution) {
break;
}
}
return (i - 1);
},
/**
* @param {OpenLayers.Pixel} viewPortPx
*
* @returns An OpenLayers.LonLat which is the passed-in view port
* OpenLayers.Pixel, translated into lon/lat by the layer
* @type OpenLayers.LonLat
*/
* @param {OpenLayers.Pixel} viewPortPx
*
* @returns An OpenLayers.LonLat which is the passed-in view port
* OpenLayers.Pixel, translated into lon/lat by the layer
* @type OpenLayers.LonLat
*/
getLonLatFromViewPortPx: function (viewPortPx) {
var size = this.map.getSize();
var center = this.map.getCenter();
@@ -338,12 +404,12 @@ OpenLayers.Layer.prototype = {
},
/**
* @param {OpenLayers.LonLat} lonlat
*
* @returns An OpenLayers.Pixel which is the passed-in OpenLayers.LonLat,
* translated into view port pixels
* @type OpenLayers.Pixel
*/
* @param {OpenLayers.LonLat} lonlat
*
* @returns An OpenLayers.Pixel which is the passed-in OpenLayers.LonLat,
* translated into view port pixels
* @type OpenLayers.Pixel
*/
getViewPortPxFromLonLat: function (lonlat) {
var resolution = this.map.getResolution();
var extent = this.map.getExtent();
@@ -352,17 +418,6 @@ OpenLayers.Layer.prototype = {
Math.round(1/resolution * (extent.top - lonlat.lat))
);
},
/**
* @param {OpenLayers.Bounds} bounds
*
* @return {int}
*/
getZoomForExtent: function (bounds) {
// this should be implemented by subclasses
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Layer"

View File

@@ -0,0 +1,112 @@
/* Copyright (c) 2006 MetaCarta, Inc., published under the BSD license.
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the full
* text of the license. */
/**
* Some Layers will already have established zoom levels (like google
* or ve). Instead of trying to determine them and populate a resolutions[]
* Array with those values, we will hijack the resolution functionality
* here.
*
* When you subclass FixedZoomLevels:
*
* The initResolutions() call gets nullified, meaning no resolutions[] array
* is set up. Which would be a big problem getResolution() in Layer, since
* it merely takes map.zoom and indexes into resolutions[]... but....
*
* The getResolution() call is also overridden. Instead of using the
* resolutions[] array, we simply calculate the current resolution based
* on the current extent and the current map size. But how will we be able
* to calculate the current extent without knowing the resolution...?
*
* The getExtent() function is also overridden. Instead of calculating extent
* based on the center point and the current resolution, we instead
* calculate the extent by getting the lonlats at the top-left and
* bottom-right by using the getLonLatFromViewPortPx() translation function,
* taken from the pixel locations (0,0) and the size of the map. But how
* will we be able to do lonlat-px translation without resolution....?
*
* Whenever you implement a layer using OpenLayers.Layer.FixedZoomLevels,
* it is your responsibility to provide the following three functions:
*
* - getLonLatFromViewPortPx()
* - getViewPortPxFromLonLat()
* - getZoomForExtent()
*
* ...those three functions should generally be provided by any reasonable
* API that you might be working from.
*
* @class
*/
OpenLayers.Layer.FixedZoomLevels = Class.create();
OpenLayers.Layer.FixedZoomLevels.prototype = {
/********************************************************/
/* */
/* Baselayer Functions */
/* */
/* The following functions must all be implemented */
/* by all base layers */
/* */
/********************************************************/
/**
* @constructor
*/
initialize: function() {
//this class is only just to add the following functions...
// nothing to actually do here... but it is probably a good
// idea to have layers that use these functions call this
// inititalize() anyways, in case at some point we decide we
// do want to put some functionality or state in here.
},
initResolutions: function() {
// resolutions are set automatically in the black-box. this is the
// definition of a fixed-zoom-levels layer
},
/**
* @returns Degrees per Pixel
* @type float
*/
getResolution: function() {
var viewSize = this.map.getSize();
var extent = this.getExtent();
return Math.max( extent.getWidth() / viewSize.w,
extent.getHeight() / viewSize.h );
},
/** Calculates using px-> lonlat translation functions on tl and br
* corners of viewport
*
* @returns A Bounds object which represents the lon/lat bounds of the
* current viewPort.
* @type OpenLayers.Bounds
*/
getExtent: function () {
var extent = null;
var size = this.map.getSize();
var tlPx = new OpenLayers.Pixel(0,0);
var tlLL = this.getLonLatFromViewPortPx(tlPx);
var brPx = new OpenLayers.Pixel(size.w, size.h);
var brLL = this.getLonLatFromViewPortPx(brPx);
if ((tlLL != null) && (brLL != null)) {
extent = new OpenLayers.Bounds(tlLL.lon,
brLL.lat,
brLL.lon,
tlLL.lat);
}
return extent;
},
/** @final @type String */
CLASS_NAME: "FixedZoomLevels.js"
};

View File

@@ -12,7 +12,8 @@
*/
OpenLayers.Layer.Google = Class.create();
OpenLayers.Layer.Google.prototype =
Object.extend( new OpenLayers.Layer.EventPane(), {
Object.extend( new OpenLayers.Layer.EventPane(),
Object.extend( new OpenLayers.Layer.FixedZoomLevels(), {
/** @type Boolean */
isFixed: true,
@@ -39,6 +40,8 @@ OpenLayers.Layer.Google.prototype =
*/
initialize: function(name, options) {
OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,
arguments);
if (this.maxExtent == null) {
this.maxExtent = new OpenLayers.Bounds(-180, -90, 180, 90);
}
@@ -249,7 +252,6 @@ OpenLayers.Layer.Google.prototype =
//make sure zoom is within bounds
var gZoom = Math.min(Math.max(gZoom, this.minZoomLevel),
this.maxZoomLevel);
zoom = this.getOLZoomFromGZoom(gZoom);
}
@@ -438,4 +440,4 @@ OpenLayers.Layer.Google.prototype =
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Layer.Google"
});
}));

View File

@@ -392,66 +392,7 @@ OpenLayers.Layer.Grid.prototype =
}
}
},
/********************************************************/
/* */
/* Baselayer Functions */
/* */
/********************************************************/
/** Calculates based on resolution, center, and mapsize
*
* @returns A Bounds object which represents the lon/lat bounds of the
* current viewPort.
* @type OpenLayers.Bounds
*/
getExtent: function () {
var extent = null;
var center = this.map.getCenter();
if (center != null) {
var res = this.map.getResolution();
var size = this.map.getSize();
var w_deg = size.w * res;
var h_deg = size.h * res;
extent = new OpenLayers.Bounds(center.lon - w_deg / 2,
center.lat - h_deg / 2,
center.lon + w_deg / 2,
center.lat + h_deg / 2);
}
return extent;
},
/**
* @param {OpenLayers.Bounds} bounds
*
* @return {int}
*/
getZoomForExtent: function (bounds) {
var maxRes = this.map.getMaxResolution();
var viewSize = this.map.getSize();
var width = bounds.getWidth();
var height = bounds.getHeight();
var degPerPixel = (width > height) ? width / viewSize.w
: height / viewSize.h;
var zoom = Math.floor( (Math.log(maxRes/degPerPixel)) / Math.log(2) );
//make sure zoom is within bounds
zoom = Math.min( Math.max(zoom, 0),
this.getNumZoomLevels() - 1);
return zoom;
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Layer.Grid"
});

View File

@@ -36,17 +36,6 @@ OpenLayers.Layer.HTTPRequest.prototype =
this.params = Object.extend( new Object(), params);
},
/** When the layer is added to the map, once it has taken all the
* relevant properties from the map (in Layer.setMap()), we will
* make the call to initialize the layer's resolutions array.
*
* @param {OpenLayers.Map} map
*/
setMap: function(map) {
OpenLayers.Layer.prototype.setMap.apply(this, arguments);
this.initResolutions();
},
/**
*
*/
@@ -137,89 +126,6 @@ OpenLayers.Layer.HTTPRequest.prototype =
}
return requestString;
},
/** This method's responsibility is to set up the 'resolutions' array
* for the layer -- this array is what the layer will use to interface
* between the zoom levels of the map and the resolution display of the
* layer.
*
* The user has several options that determine how the array is set up.
*
* For a detailed explanation, see the following wiki from the
* openlayers.org homepage:
*
* http://trac.openlayers.org/wiki/SettingZoomLevels
*
* @private
*/
initResolutions: function() {
if ((this.scales != null) || (this.resolutions != null)) {
//preset levels
if (this.scales != null) {
this.resolutions = new Array();
for(var i = 0; i < this.scales.length; i++) {
this.resolutions[i] =
OpenLayers.Util.getResolutionFromScale(this.scales[i],
this.units);
}
}
this.numZoomLevels = this.resolutions.length;
} else {
//maxResolution and numZoomLevels
this.resolutions = new Array();
// determine maxResolution
if (this.minScale) {
this.maxResolution =
OpenLayers.Util.getResolutionFromScale(this.minScale,
this.units);
} else if (this.maxResolution == "auto") {
var viewSize = this.map.getSize();
var wRes = this.maxExtent.getWidth() / viewSize.w;
var hRes = this.maxExtent.getHeight()/ viewSize.h;
this.maxResolution = Math.max(wRes, hRes);
}
// determine minResolution
if (this.maxScale != null) {
this.minResolution =
OpenLayers.Util.getResolutionFromScale(this.maxScale);
} else if ((this.minResolution == "auto") &&
(this.minExtent != null)){
var viewSize = this.map.getSize();
var wRes = this.minExtent.getWidth() / viewSize.w;
var hRes = this.minExtent.getHeight()/ viewSize.h;
this.minResolution = Math.max(wRes, hRes);
}
// determine numZoomLevels
if (this.minResolution != null) {
var ratio = this.maxResolution / this.minResolution;
this.numZoomLevels =
Math.floor(Math.log(ratio) / Math.log(2)) + 1;
}
// now we have numZoomLevels and maxResolution,
// we can populate the resolutions array
for (var i=0; i < this.numZoomLevels; i++) {
this.resolutions.push(this.maxResolution / Math.pow(2, i));
}
}
},
/**
* @returns The currently selected resolution of the map, taken from the
* resolutions array, indexed by current zoom level.
* @type float
*/
getResolution: function() {
var zoom = this.map.getZoom();
return this.resolutions[zoom];
},
/** @final @type String */
CLASS_NAME: "OpenLayers.Layer.HTTPRequest"

View File

@@ -9,8 +9,9 @@
*/
OpenLayers.Layer.VirtualEarth = Class.create();
OpenLayers.Layer.VirtualEarth.prototype =
Object.extend( new OpenLayers.Layer.EventPane(), {
Object.extend( new OpenLayers.Layer.EventPane(),
Object.extend( new OpenLayers.Layer.FixedZoomLevels(), {
/** @type VEMap */
vemap: null,
@@ -27,6 +28,8 @@ OpenLayers.Layer.VirtualEarth.prototype =
*/
initialize:function(name) {
OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments);
OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,
arguments);
this.numZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1;
},
@@ -352,4 +355,4 @@ OpenLayers.Layer.VirtualEarth.prototype =
/** @final @type String */
CLASS_NAME: "OpenLayers.Layer.VirtualEarth"
});
}));

View File

@@ -173,7 +173,7 @@ OpenLayers.Layer.WFS.prototype =
/** combine the layer's url with its params and these newParams.
*
* Add the SRS parameter from getProjection() -- this is probably
* Add the SRS parameter from 'projection' -- this is probably
* more eloquently done via a setProjection() method, but this
* works for now and always.
*

View File

@@ -133,7 +133,7 @@ OpenLayers.Layer.WMS.prototype =
/** combine the layer's url with its params and these newParams.
*
* Add the SRS parameter from getProjection() -- this is probably
* Add the SRS parameter from projection -- this is probably
* more eloquently done via a setProjection() method, but this
* works for now and always.
*

View File

@@ -684,7 +684,7 @@ OpenLayers.Map.prototype = {
getProjection: function() {
var projection = null;
if (this.baseLayer != null) {
projection = this.baseLayer.getProjection();
projection = this.baseLayer.projection;
}
return projection;
},
@@ -696,7 +696,7 @@ OpenLayers.Map.prototype = {
getMaxResolution: function() {
var maxResolution = null;
if (this.baseLayer != null) {
maxResolution = this.baseLayer.getMaxResolution();
maxResolution = this.baseLayer.maxResolution;
}
return maxResolution;
},
@@ -707,7 +707,7 @@ OpenLayers.Map.prototype = {
getMaxExtent: function () {
var maxExtent = null;
if (this.baseLayer != null) {
maxExtent = this.baseLayer.getMaxExtent();
maxExtent = this.baseLayer.maxExtent;
}
return maxExtent;
},
@@ -720,7 +720,7 @@ OpenLayers.Map.prototype = {
getNumZoomLevels: function() {
var numZoomLevels = null;
if (this.baseLayer != null) {
numZoomLevels = this.baseLayer.getNumZoomLevels();
numZoomLevels = this.baseLayer.numZoomLevels;
}
return numZoomLevels;
},

View File

@@ -43,7 +43,7 @@
control.defaultMouseDown(evt);
evt.xy = new OpenLayers.Size(15,15);
control.defaultMouseUp(evt);
t.eq(map.getZoom(), 5, "Map zoom set correctly after zoombox");
t.eq(map.getZoom(), 6, "Map zoom set correctly after zoombox");
}
// -->

View File

@@ -104,10 +104,10 @@
var layer = new OpenLayers.Layer('Test Layer', options);
t.eq(layer.getProjection(), projection, "getProjection() works");
t.ok(layer.getMaxExtent().equals(maxExtent), "getMaxExtent() works");
t.eq(layer.getMaxResolution(), maxResolution, "getMaxResolution() works");
t.eq(layer.getNumZoomLevels(), numZoomLevels, "getNumZoomLevels() works");
t.eq(layer.projection, projection, "projection set correctly");
t.ok(layer.maxExtent.equals(maxExtent), "maxExtent set correctly");
t.eq(layer.maxResolution, maxResolution, "maxResolution set correctly");
t.eq(layer.numZoomLevels, numZoomLevels, "numZoomLevels set correctly");
}
function test_05_Layer_visibility(t) {

View File

@@ -104,7 +104,7 @@
bounds = new OpenLayers.Bounds(10,10,100,100);
zoom = layer.getZoomForExtent(bounds);
t.eq( zoom, 3, "getZoomForExtent() returns correct value");
t.eq( zoom, 2, "getZoomForExtent() returns correct value");
}

View File

@@ -97,7 +97,7 @@
bounds = new OpenLayers.Bounds(10,10,100,100);
zoom = layer.getZoomForExtent(bounds);
t.eq( zoom, 3, "getZoomForExtent() returns correct value");
t.eq( zoom, 2, "getZoomForExtent() returns correct value");
}