More trip planner testing with colors
[busui.git] / labs / openlayers / lib / OpenLayers / Layer / Zoomify.js
blob:a/labs/openlayers/lib/OpenLayers/Layer/Zoomify.js -> blob:b/labs/openlayers/lib/OpenLayers/Layer/Zoomify.js
--- a/labs/openlayers/lib/OpenLayers/Layer/Zoomify.js
+++ b/labs/openlayers/lib/OpenLayers/Layer/Zoomify.js
@@ -1,1 +1,309 @@
-
+/* 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. */
+
+/*
+ * Development supported by a R&D grant DC08P02OUK006 - Old Maps Online
+ * (www.oldmapsonline.org) from Ministry of Culture of the Czech Republic.
+ */
+
+
+/**
+ * @requires OpenLayers/Layer/Grid.js
+ */
+
+/**
+ * Class: OpenLayers.Layer.Zoomify
+ *
+ * Inherits from:
+ *  - <OpenLayers.Layer.Grid>
+ */
+OpenLayers.Layer.Zoomify = OpenLayers.Class(OpenLayers.Layer.Grid, {
+
+    /**
+     * Property: url
+     * {String} URL for root directory with TileGroupX subdirectories.
+     */
+    url: null,
+
+    /**
+     * Property: size
+     * {<OpenLayers.Size>} The Zoomify image size in pixels.
+     */
+    size: null,
+
+    /**
+     * APIProperty: isBaseLayer
+     * {Boolean}
+     */
+    isBaseLayer: true,
+
+    /**
+     * Property: standardTileSize
+     * {Integer} The size of a standard (non-border) square tile in pixels.
+     */
+    standardTileSize: 256,
+
+    /**
+     * Property: numberOfTiers
+     * {Integer} Depth of the Zoomify pyramid, number of tiers (zoom levels)
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    numberOfTiers: 0,
+
+    /**
+     * Property: tileCountUpToTier
+     * {Array(Integer)} Number of tiles up to the given tier of pyramid.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tileCountUpToTier: new Array(),
+
+    /**
+     * Property: tierSizeInTiles
+     * {Array(<OpenLayers.Size>)} Size (in tiles) for each tier of pyramid.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tierSizeInTiles: new Array(),
+
+    /**
+     * Property: tierImageSize
+     * {Array(<OpenLayers.Size>)} Image size in pixels for each pyramid tier.
+     *                          - filled during Zoomify pyramid initialization.
+     */
+    tierImageSize: new Array(),
+
+    /**
+     * Constructor: OpenLayers.Layer.Zoomify
+     *
+     * Parameters:
+     * name - {String} A name for the layer.
+     * url - {String} - Relative or absolute path to the image or more
+     *        precisly to the TileGroup[X] directories root.
+     *        Flash plugin use the variable name "zoomifyImagePath" for this.
+     * size - {<OpenLayers.Size>} The size (in pixels) of the image.
+     * options - {Object} Hashtable of extra options to tag onto the layer
+     */
+    initialize: function(name, url, size, options) {
+
+        // initilize the Zoomify pyramid for given size
+        this.initializeZoomify( size );
+
+        var newArguments = [];
+        newArguments.push(name, url, size, {}, options);
+
+        OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments);
+    },
+
+    /**
+     * Method: initializeZoomify
+     * It generates constants for all tiers of the Zoomify pyramid
+     *
+     * Parameters:
+     * size - {<OpenLayers.Size>} The size of the image in pixels
+     *
+     */
+    initializeZoomify: function( size ) {
+
+        var imageSize = size.clone()
+        var tiles = new OpenLayers.Size(
+            Math.ceil( imageSize.w / this.standardTileSize ),
+            Math.ceil( imageSize.h / this.standardTileSize )
+            );
+
+        this.tierSizeInTiles.push( tiles );
+        this.tierImageSize.push( imageSize );
+
+        while (imageSize.w > this.standardTileSize ||
+               imageSize.h > this.standardTileSize ) {
+
+            imageSize = new OpenLayers.Size(
+                Math.floor( imageSize.w / 2 ),
+                Math.floor( imageSize.h / 2 )
+                );
+            tiles = new OpenLayers.Size(
+                Math.ceil( imageSize.w / this.standardTileSize ),
+                Math.ceil( imageSize.h / this.standardTileSize )
+                );
+            this.tierSizeInTiles.push( tiles );
+            this.tierImageSize.push( imageSize );
+        }
+
+        this.tierSizeInTiles.reverse();
+        this.tierImageSize.reverse();
+
+        this.numberOfTiers = this.tierSizeInTiles.length;
+
+        this.tileCountUpToTier[0] = 0;
+        for (var i = 1; i < this.numberOfTiers; i++) {
+            this.tileCountUpToTier.push(
+                this.tierSizeInTiles[i-1].w * this.tierSizeInTiles[i-1].h +
+                this.tileCountUpToTier[i-1]
+                );
+        }
+    },
+
+    /**
+     * APIMethod:destroy
+     */
+    destroy: function() {
+        // for now, nothing special to do here.
+        OpenLayers.Layer.Grid.prototype.destroy.apply(this, arguments);
+
+        // Remove from memory the Zoomify pyramid - is that enough?
+        this.tileCountUpToTier.length = 0
+        this.tierSizeInTiles.length = 0
+        this.tierImageSize.length = 0
+
+    },
+
+    /**
+     * APIMethod: clone
+     *
+     * Parameters:
+     * obj - {Object}
+     *
+     * Returns:
+     * {<OpenLayers.Layer.Zoomify>} An exact clone of this <OpenLayers.Layer.Zoomify>
+     */
+    clone: function (obj) {
+
+        if (obj == null) {
+            obj = new OpenLayers.Layer.Zoomify(this.name,
+                                           this.url,
+                                           this.size,
+                                           this.options);
+        }
+
+        //get all additions from superclasses
+        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);
+
+        // copy/set any non-init, non-simple values here
+
+        return obj;
+    },
+
+    /**
+     * Method: getURL
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     *
+     * Returns:
+     * {String} A string with the layer's url and parameters and also the
+     *          passed-in bounds and appropriate tile size specified as
+     *          parameters
+     */
+    getURL: function (bounds) {
+        bounds = this.adjustBounds(bounds);
+        var res = this.map.getResolution();
+        var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
+        var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
+        var z = this.map.getZoom();
+
+        var tileIndex = x + y * this.tierSizeInTiles[z].w + this.tileCountUpToTier[z];
+        var path = "TileGroup" + Math.floor( (tileIndex) / 256 ) +
+            "/" + z + "-" + x + "-" + y + ".jpg";
+        var url = this.url;
+        if (url instanceof Array) {
+            url = this.selectUrl(path, url);
+        }
+        return url + path;
+    },
+
+    /**
+     * Method: getImageSize
+     * getImageSize returns size for a particular tile. If bounds are given as
+     * first argument, size is calculated (bottom-right tiles are non square).
+     *
+     */
+    getImageSize: function() {
+        if (arguments.length > 0) {
+            bounds = this.adjustBounds(arguments[0]);
+            var res = this.map.getResolution();
+            var x = Math.round((bounds.left - this.tileOrigin.lon) / (res * this.tileSize.w));
+            var y = Math.round((this.tileOrigin.lat - bounds.top) / (res * this.tileSize.h));
+            var z = this.map.getZoom();
+            var w = this.standardTileSize;
+            var h = this.standardTileSize;
+            if (x == this.tierSizeInTiles[z].w -1 ) {
+                var w = this.tierImageSize[z].w % this.standardTileSize;
+            };
+            if (y == this.tierSizeInTiles[z].h -1 ) {
+                var h = this.tierImageSize[z].h % this.standardTileSize;
+            };
+            return (new OpenLayers.Size(w, h));
+        } else {
+            return this.tileSize;
+        }
+    },
+
+    /**
+     * Method: addTile
+     * addTile creates a tile, initializes it, and adds it to the layer div.
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bounds>}
+     * position - {<OpenLayers.Pixel>}
+     *
+     * Returns:
+     * {<OpenLayers.Tile.Image>} The added OpenLayers.Tile.Image
+     */
+    addTile:function(bounds,position) {
+        return new OpenLayers.Tile.Image(this, position, bounds,
+                                         null, this.tileSize);
+    },
+
+    /**
+     * APIMethod: setMap
+     * When the layer is added to a map, then we can fetch our origin
+     *    (if we don't have one.)
+     *
+     * Parameters:
+     * map - {<OpenLayers.Map>}
+     */
+    setMap: function(map) {
+        OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments);
+        this.tileOrigin = new OpenLayers.LonLat(this.map.maxExtent.left,
+                                                this.map.maxExtent.top);
+    },
+
+    /**
+     * Method: calculateGridLayout
+     * Generate parameters for the grid layout. This
+     *
+     * Parameters:
+     * bounds - {<OpenLayers.Bound>}
+     * extent - {<OpenLayers.Bounds>}
+     * resolution - {Number}
+     *
+     * Returns:
+     * Object containing properties tilelon, tilelat, tileoffsetlat,
+     * tileoffsetlat, tileoffsetx, tileoffsety
+     */
+    calculateGridLayout: function(bounds, extent, resolution) {
+        var tilelon = resolution * this.tileSize.w;
+        var tilelat = resolution * this.tileSize.h;
+
+        var offsetlon = bounds.left - extent.left;
+        var tilecol = Math.floor(offsetlon/tilelon) - this.buffer;
+        var tilecolremain = offsetlon/tilelon - tilecol;
+        var tileoffsetx = -tilecolremain * this.tileSize.w;
+        var tileoffsetlon = extent.left + tilecol * tilelon;
+
+        var offsetlat = extent.top - bounds.top + tilelat;
+        var tilerow = Math.floor(offsetlat/tilelat) - this.buffer;
+        var tilerowremain = tilerow - offsetlat/tilelat;
+        var tileoffsety = tilerowremain * this.tileSize.h;
+        var tileoffsetlat = extent.top - tilelat*tilerow;
+
+        return {
+          tilelon: tilelon, tilelat: tilelat,
+          tileoffsetlon: tileoffsetlon, tileoffsetlat: tileoffsetlat,
+          tileoffsetx: tileoffsetx, tileoffsety: tileoffsety
+        };
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Zoomify"
+});
+