]> dev.renevier.net Git - syp.git/blob - openlayers/lib/OpenLayers/Layer/FixedZoomLevels.js
fixes notices
[syp.git] / openlayers / lib / OpenLayers / Layer / FixedZoomLevels.js
1 /* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
2  * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
3  * full text of the license. */
4
5 /**
6  * @requires OpenLayers/Layer.js
7  */
8
9 /**
10  * Class: OpenLayers.Layer.FixedZoomLevels
11  *   Some Layers will already have established zoom levels (like google 
12  *    or ve). Instead of trying to determine them and populate a resolutions[]
13  *    Array with those values, we will hijack the resolution functionality
14  *    here.
15  * 
16  *   When you subclass FixedZoomLevels: 
17  * 
18  *   The initResolutions() call gets nullified, meaning no resolutions[] array 
19  *    is set up. Which would be a big problem getResolution() in Layer, since 
20  *    it merely takes map.zoom and indexes into resolutions[]... but....
21  * 
22  *   The getResolution() call is also overridden. Instead of using the 
23  *    resolutions[] array, we simply calculate the current resolution based
24  *    on the current extent and the current map size. But how will we be able
25  *    to calculate the current extent without knowing the resolution...?
26  *  
27  *   The getExtent() function is also overridden. Instead of calculating extent
28  *    based on the center point and the current resolution, we instead 
29  *    calculate the extent by getting the lonlats at the top-left and 
30  *    bottom-right by using the getLonLatFromViewPortPx() translation function,
31  *    taken from the pixel locations (0,0) and the size of the map. But how 
32  *    will we be able to do lonlat-px translation without resolution....?
33  * 
34  *   The getZoomForResolution() method is overridden. Instead of indexing into
35  *    the resolutions[] array, we call OpenLayers.Layer.getExent(), passing in
36  *    the desired resolution. With this extent, we then call getZoomForExtent() 
37  * 
38  * 
39  *   Whenever you implement a layer using OpenLayers.Layer.FixedZoomLevels, 
40  *    it is your responsibility to provide the following three functions:
41  * 
42  *   - getLonLatFromViewPortPx
43  *   - getViewPortPxFromLonLat
44  *   - getZoomForExtent
45  * 
46  *  ...those three functions should generally be provided by any reasonable 
47  *  API that you might be working from.
48  *
49  */
50 OpenLayers.Layer.FixedZoomLevels = OpenLayers.Class({
51       
52   /********************************************************/
53   /*                                                      */
54   /*                 Baselayer Functions                  */
55   /*                                                      */
56   /*    The following functions must all be implemented   */
57   /*                  by all base layers                  */
58   /*                                                      */
59   /********************************************************/
60     
61     /**
62      * Constructor: OpenLayers.Layer.FixedZoomLevels
63      * Create a new fixed zoom levels layer.
64      */
65     initialize: function() {
66         //this class is only just to add the following functions... 
67         // nothing to actually do here... but it is probably a good
68         // idea to have layers that use these functions call this 
69         // inititalize() anyways, in case at some point we decide we 
70         // do want to put some functionality or state in here. 
71     },
72     
73     /**
74      * Method: initResolutions
75      * Populate the resolutions array
76      */
77     initResolutions: function() {
78
79         var props = new Array('minZoomLevel', 'maxZoomLevel', 'numZoomLevels');
80           
81         for(var i=0, len=props.length; i<len; i++) {
82             var property = props[i];
83             this[property] = (this.options[property] != null)  
84                                      ? this.options[property] 
85                                      : this.map[property];
86         }
87
88         if ( (this.minZoomLevel == null) ||
89              (this.minZoomLevel < this.MIN_ZOOM_LEVEL) ){
90             this.minZoomLevel = this.MIN_ZOOM_LEVEL;
91         }        
92
93         //
94         // At this point, we know what the minimum desired zoom level is, and
95         //  we must calculate the total number of zoom levels. 
96         //  
97         //  Because we allow for the setting of either the 'numZoomLevels'
98         //   or the 'maxZoomLevel' properties... on either the layer or the  
99         //   map, we have to define some rules to see which we take into
100         //   account first in this calculation. 
101         //
102         // The following is the precedence list for these properties:
103         // 
104         // (1) numZoomLevels set on layer
105         // (2) maxZoomLevel set on layer
106         // (3) numZoomLevels set on map
107         // (4) maxZoomLevel set on map*
108         // (5) none of the above*
109         //
110         // *Note that options (4) and (5) are only possible if the user 
111         //  _explicitly_ sets the 'numZoomLevels' property on the map to 
112         //  null, since it is set by default to 16. 
113         //
114
115         //
116         // Note to future: In 3.0, I think we should remove the default 
117         // value of 16 for map.numZoomLevels. Rather, I think that value 
118         // should be set as a default on the Layer.WMS class. If someone
119         // creates a 3rd party layer and does not specify any 'minZoomLevel', 
120         // 'maxZoomLevel', or 'numZoomLevels', and has not explicitly 
121         // specified any of those on the map object either.. then I think
122         // it is fair to say that s/he wants all the zoom levels available.
123         // 
124         // By making map.numZoomLevels *null* by default, that will be the 
125         // case. As it is, I don't feel comfortable changing that right now
126         // as it would be a glaring API change and actually would probably
127         // break many peoples' codes. 
128         //
129
130         //the number of zoom levels we'd like to have.
131         var desiredZoomLevels;
132
133         //this is the maximum number of zoom levels the layer will allow, 
134         // given the specified starting minimum zoom level.
135         var limitZoomLevels = this.MAX_ZOOM_LEVEL - this.minZoomLevel + 1;
136
137         if ( ((this.options.numZoomLevels == null) && 
138               (this.options.maxZoomLevel != null)) // (2)
139               ||
140              ((this.numZoomLevels == null) &&
141               (this.maxZoomLevel != null)) // (4)
142            ) {
143             //calculate based on specified maxZoomLevel (on layer or map)
144             desiredZoomLevels = this.maxZoomLevel - this.minZoomLevel + 1;
145         } else {
146             //calculate based on specified numZoomLevels (on layer or map)
147             // this covers cases (1) and (3)
148             desiredZoomLevels = this.numZoomLevels;
149         }
150
151         if (desiredZoomLevels != null) {
152             //Now that we know what we would *like* the number of zoom levels
153             // to be, based on layer or map options, we have to make sure that
154             // it does not conflict with the actual limit, as specified by 
155             // the constants on the layer itself (and calculated into the
156             // 'limitZoomLevels' variable). 
157             this.numZoomLevels = Math.min(desiredZoomLevels, limitZoomLevels);
158         } else {
159             // case (5) -- neither 'numZoomLevels' not 'maxZoomLevel' was 
160             // set on either the layer or the map. So we just use the 
161             // maximum limit as calculated by the layer's constants.
162             this.numZoomLevels = limitZoomLevels;
163         }
164
165         //now that the 'numZoomLevels' is appropriately, safely set, 
166         // we go back and re-calculate the 'maxZoomLevel'.
167         this.maxZoomLevel = this.minZoomLevel + this.numZoomLevels - 1;
168
169         if (this.RESOLUTIONS != null) {
170             var resolutionsIndex = 0;
171             this.resolutions = [];
172             for(var i= this.minZoomLevel; i <= this.maxZoomLevel; i++) {
173                 this.resolutions[resolutionsIndex++] = this.RESOLUTIONS[i];            
174             }
175             this.maxResolution = this.resolutions[0];
176             this.minResolution = this.resolutions[this.resolutions.length - 1];
177         }       
178     },
179     
180     /**
181      * APIMethod: getResolution
182      * Get the current map resolution
183      * 
184      * Returns:
185      * {Float} Map units per Pixel
186      */
187     getResolution: function() {
188
189         if (this.resolutions != null) {
190             return OpenLayers.Layer.prototype.getResolution.apply(this, arguments);
191         } else {
192             var resolution = null;
193             
194             var viewSize = this.map.getSize();
195             var extent = this.getExtent();
196             
197             if ((viewSize != null) && (extent != null)) {
198                 resolution = Math.max( extent.getWidth()  / viewSize.w,
199                                        extent.getHeight() / viewSize.h );
200             }
201             return resolution;
202         }
203      },
204
205     /**
206      * APIMethod: getExtent
207      * Calculates using px-> lonlat translation functions on tl and br 
208      *     corners of viewport
209      * 
210      * Returns:
211      * {<OpenLayers.Bounds>} A Bounds object which represents the lon/lat 
212      *                       bounds of the current viewPort.
213      */
214     getExtent: function () {
215         var extent = null;
216         
217         
218         var size = this.map.getSize();
219         
220         var tlPx = new OpenLayers.Pixel(0,0);
221         var tlLL = this.getLonLatFromViewPortPx(tlPx);
222
223         var brPx = new OpenLayers.Pixel(size.w, size.h);
224         var brLL = this.getLonLatFromViewPortPx(brPx);
225         
226         if ((tlLL != null) && (brLL != null)) {
227             extent = new OpenLayers.Bounds(tlLL.lon, 
228                                        brLL.lat, 
229                                        brLL.lon, 
230                                        tlLL.lat);
231         }
232
233         return extent;
234     },
235
236     /**
237      * Method: getZoomForResolution
238      * Get the zoom level for a given resolution
239      *
240      * Parameters:
241      * resolution - {Float}
242      *
243      * Returns:
244      * {Integer} A suitable zoom level for the specified resolution.
245      *           If no baselayer is set, returns null.
246      */
247     getZoomForResolution: function(resolution) {
248       
249         if (this.resolutions != null) {
250             return OpenLayers.Layer.prototype.getZoomForResolution.apply(this, arguments);
251         } else {
252             var extent = OpenLayers.Layer.prototype.getExtent.apply(this, []);
253             return this.getZoomForExtent(extent);
254         }
255     },
256
257
258
259     
260     /********************************************************/
261     /*                                                      */
262     /*             Translation Functions                    */
263     /*                                                      */
264     /*    The following functions translate GMaps and OL    */ 
265     /*     formats for Pixel, LonLat, Bounds, and Zoom      */
266     /*                                                      */
267     /********************************************************/
268     
269     
270     //
271     // TRANSLATION: MapObject Zoom <-> OpenLayers Zoom
272     //
273   
274     /**
275      * Method: getOLZoomFromMapObjectZoom
276      * Get the OL zoom index from the map object zoom level
277      *
278      * Parameters:
279      * moZoom - {Integer}
280      * 
281      * Returns:
282      * {Integer} An OpenLayers Zoom level, translated from the passed in zoom
283      *           Returns null if null value is passed in
284      */
285     getOLZoomFromMapObjectZoom: function(moZoom) {
286         var zoom = null;
287         if (moZoom != null) {
288             zoom = moZoom - this.minZoomLevel;
289         }
290         return zoom;
291     },
292     
293     /**
294      * Method: getMapObjectZoomFromOLZoom
295      * Get the map object zoom level from the OL zoom level
296      *
297      * Parameters:
298      * olZoom - {Integer}
299      * 
300      * Returns:
301      * {Integer} A MapObject level, translated from the passed in olZoom
302      *           Returns null if null value is passed in
303      */
304     getMapObjectZoomFromOLZoom: function(olZoom) {
305         var zoom = null; 
306         if (olZoom != null) {
307             zoom = olZoom + this.minZoomLevel;
308         }
309         return zoom;
310     },
311
312     CLASS_NAME: "OpenLayers.Layer.FixedZoomLevels"
313 });
314