From 861a9c10f5a76989b1a20c9b7fdb3c585349952e Mon Sep 17 00:00:00 2001 From: crschmidt Date: Wed, 8 Apr 2009 06:54:16 +0000 Subject: [PATCH] adding XYZ layer (and OSM laayer) to OpenLayers. r=fredj, (Closes #1950) git-svn-id: http://svn.openlayers.org/trunk/openlayers@9240 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf --- examples/spherical-mercator.html | 42 +--- lib/OpenLayers.js | 2 + lib/OpenLayers/Layer/XYZ.js | 356 ++++++++++++++++++++++++++++++ tests/Layer/XYZ.html | 366 +++++++++++++++++++++++++++++++ tests/list-tests.html | 1 + 5 files changed, 732 insertions(+), 35 deletions(-) create mode 100644 lib/OpenLayers/Layer/XYZ.js create mode 100644 tests/Layer/XYZ.html diff --git a/examples/spherical-mercator.html b/examples/spherical-mercator.html index 221c238297..ebddb1b892 100644 --- a/examples/spherical-mercator.html +++ b/examples/spherical-mercator.html @@ -78,34 +78,21 @@ {'type': YAHOO_MAP_HYB, 'sphericalMercator': true} ); + // create OSM layer + var mapnik = new OpenLayers.Layer.OSM(); // create OAM layer - var oam = new OpenLayers.Layer.TMS( + var oam = new OpenLayers.Layer.XYZ( "OpenAerialMap", - "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/", + "http://tile.openaerialmap.org/tiles/1.0.0/openaerialmap-900913/${z}/${x}/${y}.png", { - type: 'png', getURL: osm_getTileURL + sphericalMercator: true } ); // create OSM layer - var mapnik = new OpenLayers.Layer.TMS( - "OpenStreetMap (Mapnik)", - "http://a.tile.openstreetmap.org/", - { - type: 'png', getURL: osm_getTileURL, - displayOutsideMaxExtent: true, - attribution: 'OpenStreetMap' - } - ); - // create OSM layer - var osmarender = new OpenLayers.Layer.TMS( + var osmarender = new OpenLayers.Layer.OSM( "OpenStreetMap (Tiles@Home)", - "http://tah.openstreetmap.org/Tiles/tile/", - { - type: 'png', getURL: osm_getTileURL, - displayOutsideMaxExtent: true, - attribution: 'OpenStreetMap' - } + "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png" ); @@ -133,21 +120,6 @@ if (!map.getCenter()) {map.zoomToMaxExtent()} } - function osm_getTileURL(bounds) { - var res = this.map.getResolution(); - var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w)); - var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h)); - var z = this.map.getZoom(); - var limit = Math.pow(2, z); - - if (y < 0 || y >= limit) { - return OpenLayers.Util.getImagesLocation() + "404.png"; - } else { - x = ((x % limit) + limit) % limit; - return this.url + z + "/" + x + "/" + y + "." + this.type; - } - } - diff --git a/lib/OpenLayers.js b/lib/OpenLayers.js index 0c28416ea7..aee35408c2 100644 --- a/lib/OpenLayers.js +++ b/lib/OpenLayers.js @@ -115,7 +115,9 @@ "OpenLayers/Layer/WMS/Untiled.js", "OpenLayers/Layer/GeoRSS.js", "OpenLayers/Layer/Boxes.js", + "OpenLayers/Layer/XYZ.js", "OpenLayers/Layer/TMS.js", + "OpenLayers/Layer/ArcGISCache.js", "OpenLayers/Layer/TileCache.js", "OpenLayers/Popup/Anchored.js", "OpenLayers/Popup/AnchoredBubble.js", diff --git a/lib/OpenLayers/Layer/XYZ.js b/lib/OpenLayers/Layer/XYZ.js new file mode 100644 index 0000000000..252607b14f --- /dev/null +++ b/lib/OpenLayers/Layer/XYZ.js @@ -0,0 +1,356 @@ +/* Copyright (c) 2006-2009 MetaCarta, Inc., 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/Grid.js + */ + +/** + * Class: OpenLayers.Layer.XYZ + * The XYZ class is designed to make it easier for people who have tiles + * arranged by a standard XYZ grid. + */ +OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, { + + /** + * APIProperty: isBaseLayer + * Default is true, as this is designed to be a base tile source. + */ + isBaseLayer: true, + + /** + * APIProperty: sphericalMecator + * Whether the tile extents should be set to the defaults for + * spherical mercator. Useful for things like OpenStreetMap. + * Default is false, except for the OSM subclass. + */ + sphericalMercator: false, + + /** + * Constructor: OpenLayers.Layer.XYZ + * + * Parameters: + * name - {String} + * url - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, url, options) { + if (options && options.sphericalMercator || this.sphericalMercator) { + options = OpenLayers.Util.extend({ + maxExtent: new OpenLayers.Bounds( + -128 * 156543.0339, + -128 * 156543.0339, + 128 * 156543.0339, + 128 * 156543.0339 + ), + maxResolution: 156543.0339, + numZoomLevels: 19, + units: "m", + projection: "EPSG:900913" + }, options); + } + url = url || this.url; + name = name || this.name; + var newArguments = [name, url, {}, options]; + OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments); + }, + + /** + * APIMethod: clone + * Create a clone of this layer + * + * Parameters: + * obj - {Object} Is this ever used? + * + * Returns: + * {} An exact clone of this OpenLayers.Layer.Grid + */ + clone: function (obj) { + + if (obj == null) { + obj = new OpenLayers.Layer.XYZ(this.name, + this.url, + this.options); + } + + //get all additions from superclasses + obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this, [obj]); + + // copy/set any non-init, non-simple values here + if (this.tileSize != null) { + obj.tileSize = this.tileSize.clone(); + } + + // we do not want to copy reference to grid, so we make a new array + obj.grid = []; + + return obj; + }, + + /** + * Method: getUrl + * + * Parameters: + * 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) { + var res = this.map.getResolution(); + var x = Math.round((bounds.left - this.maxExtent.left) + / (res * this.tileSize.w)); + var y = Math.round((this.maxExtent.top - bounds.top) + / (res * this.tileSize.h)); + var z = this.map.getZoom(); + var limit = Math.pow(2, z); + + var url = this.url; + var s = '' + x + y + z; + if (url instanceof Array) + { + url = this.selectUrl(s, url); + } + + var path = OpenLayers.String.format(url, {'x': x, 'y': y, 'z': z}); + + return path; + }, + + /** + * Method: addTile + * addTile creates a tile, initializes it, and adds it to the layer div. + * + * Parameters: + * bounds - {} + * position - {} + * + * Returns: + * {} 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 - {} + */ + setMap: function(map) { + OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments); + if (!this.tileOrigin) { + this.tileOrigin = new OpenLayers.LonLat(this.maxExtent.left, + this.maxExtent.bottom); + } + }, + + CLASS_NAME: "OpenLayers.Layer.XYZ" +}); + + +/** + * Class: OpenLayers.Layer.OSM + * A class to access OpenStreetMap tiles. By default, uses the OpenStreetMap + * hosted tile.openstreetmap.org 'Mapnik' tileset. If you wish to use + * tiles@home / osmarender layer instead, you can pass a layer like: + * + * (code) + * new OpenLayers.Layer.OSM("t@h", + * "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"); + * (end) + * + * This layer defaults to Spherical Mercator. + */ + +OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { + name: "OpenStreetMap", + attribution: "Data CC-By-SA by OpenStreetMap", + sphericalMercator: true, + url: 'http://tile.openstreetmap.org/${z}/${x}/${y}.png', + CLASS_NAME: "OpenLayers.Layer.OSM" +}); +/* Copyright (c) 2006-2009 MetaCarta, Inc., 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/Grid.js + */ + +/** + * Class: OpenLayers.Layer.XYZ + * The XYZ class is designed to make it easier for people who have tiles + * arranged by a standard XYZ grid. + */ +OpenLayers.Layer.XYZ = OpenLayers.Class(OpenLayers.Layer.Grid, { + + /** + * APIProperty: isBaseLayer + * Default is true, as this is designed to be a base tile source. + */ + isBaseLayer: true, + + /** + * APIProperty: sphericalMecator + * Whether the tile extents should be set to the defaults for + * spherical mercator. Useful for things like OpenStreetMap. + * Default is false, except for the OSM subclass. + */ + sphericalMercator: false, + + /** + * Constructor: OpenLayers.Layer.OSM + * + * Parameters: + * name - {String} + * url - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, url, options) { + if (options && options.sphericalMercator || this.sphericalMercator) { + options = OpenLayers.Util.extend({ + maxExtent: new OpenLayers.Bounds( + -128 * 156543.0339, + -128 * 156543.0339, + 128 * 156543.0339, + 128 * 156543.0339 + ), + maxResolution: 156543.0339, + numZoomLevels: 19, + units: "m", + projection: "EPSG:900913" + }, options); + } + url = url || this.url; + name = name || this.name; + var newArguments = [name, url, {}, options]; + OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments); + }, + + /** + * APIMethod: clone + * Create a clone of this layer + * + * Parameters: + * obj - {Object} Is this ever used? + * + * Returns: + * {} An exact clone of this OpenLayers.Layer.Grid + */ + clone: function (obj) { + + if (obj == null) { + obj = new OpenLayers.Layer.XYZ(this.name, + this.url, + this.options); + } + + //get all additions from superclasses + obj = OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this, [obj]); + + // copy/set any non-init, non-simple values here + if (this.tileSize != null) { + obj.tileSize = this.tileSize.clone(); + } + + // we do not want to copy reference to grid, so we make a new array + obj.grid = []; + + return obj; + }, + + /** + * Method: getUrl + * + * Parameters: + * 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) { + var res = this.map.getResolution(); + var x = Math.round((bounds.left - this.maxExtent.left) + / (res * this.tileSize.w)); + var y = Math.round((this.maxExtent.top - bounds.top) + / (res * this.tileSize.h)); + var z = this.map.getZoom(); + var limit = Math.pow(2, z); + + var url = this.url; + var s = '' + x + y + z; + if (url instanceof Array) + { + url = this.selectUrl(s, url); + } + + var path = OpenLayers.String.format(url, {'x': x, 'y': y, 'z': z}); + + return path; + }, + + /** + * Method: addTile + * addTile creates a tile, initializes it, and adds it to the layer div. + * + * Parameters: + * bounds - {} + * position - {} + * + * Returns: + * {} 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 - {} + */ + setMap: function(map) { + OpenLayers.Layer.Grid.prototype.setMap.apply(this, arguments); + if (!this.tileOrigin) { + this.tileOrigin = new OpenLayers.LonLat(this.maxExtent.left, + this.maxExtent.bottom); + } + }, + + CLASS_NAME: "OpenLayers.Layer.XYZ" +}); + + +/** + * Class: OpenLayers.Layer.OSM + * A class to access OpenStreetMap tiles. By default, uses the OpenStreetMap + * hosted tile.openstreetmap.org 'Mapnik' tileset. If you wish to use + * tiles@home / osmarender layer instead, you can pass a layer like: + * + * (code) + * new OpenLayers.Layer.OSM("t@h", + * "http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png"); + * (end) + * + * This layer defaults to Spherical Mercator. + */ + +OpenLayers.Layer.OSM = OpenLayers.Class(OpenLayers.Layer.XYZ, { + name: "OpenStreetMap", + attribution: "Data CC-By-SA by OpenStreetMap", + sphericalMercator: true, + url: 'http://tile.openstreetmap.org/${z}/${x}/${y}.png', + CLASS_NAME: "OpenLayers.Layer.OSM" +}); diff --git a/tests/Layer/XYZ.html b/tests/Layer/XYZ.html new file mode 100644 index 0000000000..a6cf1ef5b4 --- /dev/null +++ b/tests/Layer/XYZ.html @@ -0,0 +1,366 @@ + + + + + + +
+ + + + + + + + +
+ + diff --git a/tests/list-tests.html b/tests/list-tests.html index 88b3ed79b0..70279837f1 100644 --- a/tests/list-tests.html +++ b/tests/list-tests.html @@ -126,6 +126,7 @@
  • Layer/WFS.html
  • Layer/WMS.html
  • Layer/WrapDateLine.html
  • +
  • Layer/XYZ.html
  • Layer/Yahoo.html
  • Map.html
  • Marker.html