source: sandbox/tschaub/arcgiscache/lib/OpenLayers/Layer/ArcGISCache.js

Last change on this file was 9918, checked in by tschaub, 6 years ago

Adding an ArcGISCache layer.

File size: 7.9 KB
Line 
1/**
2 * @requires OpenLayers/Layer/XYZ.js
3 * @requires OpenLayers/Tile/Image.js
4 */
5
6/**
7 * Class: OpenLayers.Layer.ArcGISCache
8 * Create a layer to read from an ArcGIS tile cache.
9 *
10 * Examples:
11 *
12 * Create a new layer based on a cache in geographic coordinates.
13 * (code)
14 *     var layer = new OpenLayers.Layer.ArcGISCache({
15 *         url: "http://example.com/mylayer/"
16 *     });
17 * (end)
18 *
19 * Create a new layer based on a cache in spherical mercator.
20 * (code)
21 *     var layer = new OpenLayers.Layer.ArcGISCache({
22 *         url: "http://example.com/mylayer/",
23 *         sphericalMercator: true
24 *     });
25 * (end)
26 *
27 * Create a layer in geographic coordinates with a custom tile origin.
28 * (code)
29 *     var layer = new OpenLayers.Layer.ArcGISCache({
30 *         url: "http://example.com/mylayer/",
31 *         tileOrigin: new OpenLayers.LonLat(-100, 45)
32 *     });
33 * (end)
34 *
35 * Inherits from:
36 *  - <OpenLayers.Layer.XYZ>
37 */
38OpenLayers.Layer.ArcGISCache = OpenLayers.Class(OpenLayers.Layer.XYZ, {
39   
40    /**
41     * APIProperty: url
42     * {String | Array} The base URL for the layer cache.  If your tiles can
43     *     be accessed at "http://example.com/mylayer/L00/R00000000/C00000000.png"
44     *     this value would be "http://example.com/mylayer/".  You can also
45     *     provide a list of URL strings for the layer if your cache is
46     *     available from multiple origins.  This must be set before the layer
47     *     is drawn.
48     */
49    url: null,
50   
51    /**
52     * APIProperty: tileOrigin
53     * {<OpenLayers.LonLat>} The location of the tile origin for the cache.
54     *     An ArcGIS cache has it's origin at the upper-left (lowest x value
55     *     and highest y value of the coordinate system).  The units for the
56     *     tile origin should be the same as the units for the cached data.
57     *     If this is not set, it will be derived from the layer maxExtent.
58     */
59    tileOrigin: null,
60   
61    /**
62     * APIProperty: sphericalMercator
63     * {Boolean} This layer is in a sperical (or web) mercator projection.
64     *     Default is false.  If set to true, resolution and projection related
65     *     parameters will be calculated if not provided (maxExtent,
66     *     maxResolution, numZoomLevels, units, and projection).
67     */
68    sphericalMercator: false,
69   
70    /**
71     * APIProperty: type
72     * {String} Image type for the layer.  This becomes the filename extension
73     *     in tile requests.  Default is "png" (generating a url like
74     *     "http://example.com/mylayer/L00/R00000000/C00000000.png").
75     */
76    type: "png",
77   
78    /**
79     * APIProperty: params
80     * {Object} An optional object with members representing query string
81     *     parameters to be appended to tile requests.  By default, no query
82     *     string is appended (params is null).  If a params object is provided,
83     *     all property name/value pairs will be URI component encoded in the
84     *     query string for each tile.  Call mergeNewParams to update the
85     *     params object after layer construction.
86     */
87    params: null,
88
89    /**
90     * APIProperty: zoomOffset
91     * {Number} If your cache has more zoom levels than you want to provide
92     *     access to with this layer, supply a zoomOffset.  This zoom offset
93     *     is added to the current map zoom level to determine the level
94     *     for a requested tile.  For example, if you supply a zoomOffset
95     *     of 3, when the map is at the zoom 0, tiles will be requested from
96     *     level 3 of your cache.  Default is 0 (assumes cache level and map
97     *     zoom are equivalent).
98     */
99    zoomOffset: 0,
100   
101    /**
102     * APIProperty: upperCase
103     * {Boolean} Use upper case for row and column ids.  Default is true.
104     */
105    upperCase: true,
106   
107    /**
108     * APIProperty: name
109     * {String} The layer title (for display in UI components like a layer
110     *     switcher.)
111     */
112    name: "",
113   
114    /**
115     * Constructor: OpenLayers.Layer.ArcGISCache
116     * Create a new layer for displaying tiles from an ArcGIS tile cache.
117     *
118     * Parameters:
119     * options - {Object} Properties to be set on the layer.  Any of the layer
120     *     properties may be set by including members in this object.  The <url>
121     *     property is the only required property.
122     */
123    initialize: function(options) {
124        var args = [options.name, options.url, options];
125        OpenLayers.Layer.XYZ.prototype.initialize.apply(this, args);
126
127        if (this.maxExtent && !this.tileOrigin) {
128            this.tileOrigin = new OpenLayers.LonLat(
129                this.maxExtent.left, this.maxExtent.top
130            )
131        }
132        if (options && options.params) {
133            this.params = OpenLayers.Util.extend({}, options.params);
134        } else {
135            this.params = null;
136        }
137    },
138   
139    /**
140     * Method: zeroPad
141     * Create a zero padded string optionally with a radix for casting numbers.
142     *
143     * Parameters:
144     * num - {Number} The number to be zero padded.
145     * len - {Number} The length of the string to be returned.
146     * radix - {Number} An integer between 2 and 36 specifying the base to use
147     *     for representing numeric values.
148     */
149    zeroPad: function(num, len, radix) {
150        var str = num.toString(radix || 10);
151        while (str.length < len) {
152            str = "0" + str;
153        }
154        return str;
155    },
156
157   
158    /**
159     * Method: getUrl
160     * Determine the URL for a tile given the tile bounds.  This is a generous
161     *     algorithm that determines the row and column numbers given the center
162     *     of the tile bounds.  This allows for some imprecision in the
163     *     <tileOrigin> and resolution based calculations.
164     *
165     * Parameters:
166     * bounds - {<OpenLayers.Bounds>}
167     *
168     * Returns:
169     * {String} The URL for a tile based on given bounds.
170     */
171    getURL: function(bounds) {
172       
173        // allow for level to be offset from zoom
174        var level = "L" + this.zeroPad(this.zoomOffset + this.map.getZoom(), 2);
175
176        // use tile center to avoid precision issues at tile edges
177        var center = bounds.getCenterLonLat();       
178        var res = this.map.getResolution();
179
180        // column id is a zero padded base 16 number
181        // counting in the positive x direction
182        var colWidth = res * this.tileSize.h;
183        var xOffset = center.lon - this.tileOrigin.lon;
184        var col = "C" + this.zeroPad(Math.floor(xOffset / colWidth), 8, 16);
185        if (this.upperCase) {
186            col = col.toUpperCase();
187        }
188       
189        // row id is a zero padded base 16 number
190        // counting in the negative y direction
191        var rowHeight = res * this.tileSize.w;
192        var yOffset = center.lat - this.tileOrigin.lat;
193        var row = "R" + this.zeroPad(Math.floor(-yOffset / rowHeight), 8, 16);
194        if (this.upperCase) {
195            row = row.toUpperCase();
196        }
197       
198        var url = this.url;
199        if (url instanceof Array) {
200            url = this.selectUrl(level + row + col, url);
201        }
202       
203        // optionally append a query string based on params
204        var query = "";
205        if (this.params) {
206            query = "?" + OpenLayers.Util.getParameterString(this.params);
207        }
208
209        var base = url.replace(/\/$/, "") + "/";
210        return base + level + "/" + row + "/" + col + "." + this.type + query; 
211    },
212   
213    /**
214     * APIMethod: clone
215     * Create a copy of this layer.
216     *
217     * Returns:
218     * {<OpenLayers.Layer.ArcGISCache>} A new layer with the same properties
219     *     as this one.
220     */
221    clone: function(obj) {
222        // this allows subclasses to apply this method with impunity
223        if (!obj) {
224            var options = OpenLayers.Util.extend({}, this.options);
225            obj = new OpenLayers.Layer.ArcGISCache(options);
226        }
227        return OpenLayers.Layer.XYZ.prototype.clone.apply(this, [obj]);
228    },
229
230    CLASS_NAME: "OpenLayers.Layer.ArcGISCache"
231});
Note: See TracBrowser for help on using the repository browser.