More trip planner testing with colors
[busui.git] / labs / openlayers / lib / OpenLayers / Layer / FixedZoomLevels.js
blob:a/labs/openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js -> blob:b/labs/openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js
  /* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
  * full list of contributors). Published under the Clear BSD license.
  * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  * full text of the license. */
   
  /**
  * @requires OpenLayers/Layer.js
  */
   
  /**
  * Class: OpenLayers.Layer.FixedZoomLevels
  * 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....?
  *
  * The getZoomForResolution() method is overridden. Instead of indexing into
  * the resolutions[] array, we call OpenLayers.Layer.getExent(), passing in
  * the desired resolution. With this extent, we then call getZoomForExtent()
  *
  *
  * 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.
  *
  */
  OpenLayers.Layer.FixedZoomLevels = OpenLayers.Class({
   
  /********************************************************/
  /* */
  /* Baselayer Functions */
  /* */
  /* The following functions must all be implemented */
  /* by all base layers */
  /* */
  /********************************************************/
   
  /**
  * Constructor: OpenLayers.Layer.FixedZoomLevels
  * Create a new fixed zoom levels layer.
  */
  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.
  },
   
  /**
  * Method: initResolutions
  * Populate the resolutions array
  */
  initResolutions: function() {
   
  var props = new Array('minZoomLevel', 'maxZoomLevel', 'numZoomLevels');
   
  for(var i=0, len=props.length; i<len; i++) {
  var property = props[i];
  this[property] = (this.options[property] != null)
  ? this.options[property]
  : this.map[property];
  }
   
  if ( (this.minZoomLevel == null) ||
  (this.minZoomLevel < this.MIN_ZOOM_LEVEL) ){
  this.minZoomLevel = this.MIN_ZOOM_LEVEL;
  }
   
  //
  // At this point, we know what the minimum desired zoom level is, and
  // we must calculate the total number of zoom levels.
  //
  // Because we allow for the setting of either the 'numZoomLevels'
  // or the 'maxZoomLevel' properties... on either the layer or the
  // map, we have to define some rules to see which we take into
  // account first in this calculation.
  //
  // The following is the precedence list for these properties:
  //
  // (1) numZoomLevels set on layer
  // (2) maxZoomLevel set on layer
  // (3) numZoomLevels set on map
  // (4) maxZoomLevel set on map*
  // (5) none of the above*
  //
  // *Note that options (4) and (5) are only possible if the user
  // _explicitly_ sets the 'numZoomLevels' property on the map to
  // null, since it is set by default to 16.
  //
   
  //
  // Note to future: In 3.0, I think we should remove the default
  // value of 16 for map.numZoomLevels. Rather, I think that value
  // should be set as a default on the Layer.WMS class. If someone
  // creates a 3rd party layer and does not specify any 'minZoomLevel',
  // 'maxZoomLevel', or 'numZoomLevels', and has not explicitly
  // specified any of those on the map object either.. then I think
  // it is fair to say that s/he wants all the zoom levels available.
  //
  // By making map.numZoomLevels *null* by default, that will be the
  // case. As it is, I don't feel comfortable changing that right now
  // as it would be a glaring API change and actually would probably
  // break many peoples' codes.
  //
   
  //the number of zoom levels we'd like to have.
  var desiredZoomLevels;
   
  //this is the maximum number of zoom levels the layer will allow,
  // given the specified starting minimum zoom level.
  var limitZoomLevels = this.MAX_ZOOM_LEVEL - this.minZoomLevel + 1;
   
  if ( ((this.options.numZoomLevels == null) &&
  (this.options.maxZoomLevel != null)) // (2)
  ||
  ((this.numZoomLevels == null) &&
  (this.maxZoomLevel != null)) // (4)
  ) {
  //calculate based on specified maxZoomLevel (on layer or map)
  desiredZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1;
  } else {
  //calculate based on specified numZoomLevels (on layer or map)
  // this covers cases (1) and (3)
  desiredZoomLevels = this.numZoomLevels;
  }
   
  if (desiredZoomLevels != null) {
  //Now that we know what we would *like* the number of zoom levels
  // to be, based on layer or map options, we have to make sure that
  // it does not conflict with the actual limit, as specified by
  // the constants on the layer itself (and calculated into the
  // 'limitZoomLevels' variable).
  this.numZoomLevels = Math.min(desiredZoomLevels, limitZoomLevels);
  } else {
  // case (5) -- neither 'numZoomLevels' not 'maxZoomLevel' was
  // set on either the layer or the map. So we just use the
  // maximum limit as calculated by the layer's constants.
  this.numZoomLevels = limitZoomLevels;
  }
   
  //now that the 'numZoomLevels' is appropriately, safely set,
  // we go back and re-calculate the 'maxZoomLevel'.
  this.maxZoomLevel = this.minZoomLevel + this.numZoomLevels - 1;
   
  if (this.RESOLUTIONS != null) {
  var resolutionsIndex = 0;
  this.resolutions = [];
  for(var i= this.minZoomLevel; i <= this.maxZoomLevel; i++) {
  this.resolutions[resolutionsIndex++] = this.RESOLUTIONS[i];
  }
  this.maxResolution = this.resolutions[0];
  this.minResolution = this.resolutions[this.resolutions.length - 1];
  }
  },
   
  /**
  * APIMethod: getResolution
  * Get the current map resolution
  *
  * Returns:
  * {Float} Map units per Pixel
  */
  getResolution: function() {
   
  if (this.resolutions != null) {
  return OpenLayers.Layer.prototype.getResolution.apply(this, arguments);
  } else {
  var resolution = null;
   
  var viewSize = this.map.getSize();
  var extent = this.getExtent();
   
  if ((viewSize != null) && (extent != null)) {
  resolution = Math.max( extent.getWidth() / viewSize.w,
  extent.getHeight() / viewSize.h );
  }
  return resolution;
  }
  },
   
  /**
  * APIMethod: getExtent
  * Calculates using px-> lonlat translation functions on tl and br
  * corners of viewport
  *
  * Returns:
  * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat
  * bounds of the current viewPort.
  */
  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;
  },
   
  /**
  * Method: getZoomForResolution
  * Get the zoom level for a given resolution
  *
  * Parameters:
  * resolution - {Float}
  *
  * Returns:
  * {Integer} A suitable zoom level for the specified resolution.
  * If no baselayer is set, returns null.
  */
  getZoomForResolution: function(resolution) {
   
  if (this.resolutions != null) {
  return OpenLayers.Layer.prototype.getZoomForResolution.apply(this, arguments);
  } else {
  var extent = OpenLayers.Layer.prototype.getExtent.apply(this, []);
  return this.getZoomForExtent(extent);
  }
  },
   
   
   
   
  /********************************************************/
  /* */
  /* Translation Functions */
  /* */
  /* The following functions translate GMaps and OL */
  /* formats for Pixel, LonLat, Bounds, and Zoom */
  /* */
  /********************************************************/
   
   
  //
  // TRANSLATION: MapObject Zoom <-> OpenLayers Zoom
  //
   
  /**
  * Method: getOLZoomFromMapObjectZoom
  * Get the OL zoom index from the map object zoom level
  *
  * Parameters:
  * moZoom - {Integer}
  *
  * Returns:
  * {Integer} An OpenLayers Zoom level, translated from the passed in zoom
  * Returns null if null value is passed in
  */
  getOLZoomFromMapObjectZoom: function(moZoom) {
  var zoom = null;
  if (moZoom != null) {
  zoom = moZoom - this.minZoomLevel;
  }
  return zoom;
  },
   
  /**
  * Method: getMapObjectZoomFromOLZoom
  * Get the map object zoom level from the OL zoom level
  *
  * Parameters:
  * olZoom - {Integer}
  *
  * Returns:
  * {Integer} A MapObject level, translated from the passed in olZoom
  * Returns null if null value is passed in
  */
  getMapObjectZoomFromOLZoom: function(olZoom) {
  var zoom = null;
  if (olZoom != null) {
  zoom = olZoom + this.minZoomLevel;
  }
  return zoom;
  },
   
  CLASS_NAME: "OpenLayers.Layer.FixedZoomLevels"
  });