Permalink
Browse files

[topo] do not fetch out of range tiles

  • Loading branch information...
1 parent 25a5597 commit 81b9006564d007bd6e815f47866ee0f0536fd6a3 @vicb committed Dec 3, 2012
@@ -0,0 +1,127 @@
+/**
+ * Copyright 2012 Victor Berchet
+ *
+ * This file is part of VisuGps3
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ *
+ */
+
+/**
+ * @fileoverview Base class for topo maps.
+ * @author Victor Berchet <victor@suumit.com>
+ */
+
+goog.provide('vgps3.topo.AbstractTopo');
+
+goog.require('goog.array');
+
+
+/**
+ * @constructor
+ * @extends {vgps3.PluginBase}
+ */
+vgps3.topo.AbstractTopo = function() {
+ goog.base(this);
+
+ /**
+ * @type {Array.<google.maps.LatLngBounds>} The visible areas
+ * @protected
+ */
+ this.bounds_;
+
+ /**
+ * @type {goog.debug.Logger}
+ * @private_
+ */
+ this.logger_ = goog.debug.Logger.getLogger('vgps3.topo.AbstractTopo');
+
+};
+goog.inherits(vgps3.topo.AbstractTopo, vgps3.PluginBase);
+
+/**
+ * Set the visible area
+ *
+ * @param {!Array.<Array.<number>>} latlngBounds format: [lat, lng, lat, lng]
+ * @protected
+ */
+vgps3.topo.AbstractTopo.prototype.setBounds_ = function(latlngBounds) {
+ var that = this;
+
+ this.bounds_ = [];
+ goog.array.forEach(latlngBounds || [], function(bounds) {
+ var lats = [bounds[0], bounds[2]],
+ lngs = [bounds[1], bounds[3]];
+
+ goog.array.sort(lats);
+ goog.array.sort(lngs);
+
+ that.bounds_.push(new google.maps.LatLngBounds(
+ new google.maps.LatLng(lats[0], lngs[0]),
+ new google.maps.LatLng(lats[1], lngs[1])
+ ));
+ });
+};
+
+
+/**
+ * Checks if the tile is provided by the map.
+ *
+ * @param {google.maps.Point} coord
+ * @param {number} zoom
+ * @protected
+ *
+ * @return {boolean} Whether the tile is provided by the current map
+ */
+vgps3.topo.AbstractTopo.prototype.isTileVisible_ = function(coord, zoom) {
+ var numTiles = Math.pow(2, zoom),
+ e = 256 * coord.x / numTiles,
+ w = 256 * (coord.x + 1) / numTiles,
+ s = 256 * (coord.y + 1) / numTiles,
+ n = 256 * coord.y / numTiles,
+ projection,
+ tileBounds,
+ visible;
+
+ projection = this.gMap_.getProjection();
+
+ tileBounds = new google.maps.LatLngBounds(
+ projection.fromPointToLatLng(new google.maps.Point(w, s)),
+ projection.fromPointToLatLng(new google.maps.Point(e, n))
+ );
+
+ goog.array.some(this.bounds_, function(bounds) {
+ visible = bounds.intersects(tileBounds);
+
+ if (visible) {
+ this.logger_.info("Tile visible in range: " + bounds.toString());
+ }
+
+ return visible;
+ },
+ this
+ );
+
+ return visible;
+}
+
+/**
+ * Returns the map type.
+ *
+ * @return {google.maps.ImageMapType} The map type.
+ *
+ * @protected
+ */
+vgps3.topo.AbstractTopo.prototype.getMapType_ = goog.abstractMethod;
+
+/**
+ * Returns the URL of a tile.
+ *
+ * @param {google.maps.Point} coord
+ * @param {number} zoom
+ * @return {?string}
+ *
+ * @protected
+ */
+vgps3.topo.AbstractTopo.prototype.getTileUrl_ = goog.abstractMethod;
@@ -17,15 +17,15 @@ goog.provide('vgps3.topo.ch.Map');
goog.require('goog.math');
goog.require('vgps3.Map');
-goog.require('vgps3.PluginBase');
+goog.require('vgps3.topo.AbstractTopo');
goog.require('vgps3.proj.GProj');
goog.require('vgps3.proj.Swisstopo');
/**
* @constructor Spain IGN map type for google maps.
- * @extends {vgps3.PluginBase}
+ * @extends {vgps3.topo.AbstractTopo}
*/
vgps3.topo.ch.Map = function() {
/**
@@ -54,17 +54,16 @@ vgps3.topo.ch.Map = function() {
goog.base(this);
};
-goog.inherits(vgps3.topo.ch.Map, vgps3.PluginBase);
+goog.inherits(vgps3.topo.ch.Map, vgps3.topo.AbstractTopo);
/**
- * Registers this map type in google maps.
- *
* @override
*/
vgps3.topo.ch.Map.prototype.init = function(vgps) {
var that = this;
goog.base(this, 'init', vgps);
+ this.setBounds_([[45.3981, 5.1402, 48.2306, 11.4774]]);
this.gMap_.mapTypes.set(vgps3.topo.ch.MapTypeId.TERRAIN, /** @type {?} */ (this.getMapType_()));
this.center_ = this.gMap_.getCenter();
this.previousZoom_ = this.gMap_.getZoom();
@@ -73,7 +72,6 @@ vgps3.topo.ch.Map.prototype.init = function(vgps) {
'maptypeid_changed',
goog.bind(this.mapTypeChangeHandler_, this)
);
-
// Capture the center value when the map becomes idle
// This is required to apply this value when the zoom level changes as consecutive zoom
// resolution ratio is not 2 as expected by the google maps API
@@ -106,10 +104,10 @@ vgps3.topo.ch.Map.prototype.enable_ = function() {
this.updateProjection_();
this.zoomListener_ = google.maps.event.addListener(
- this.gMap_,
- 'zoom_changed',
- goog.bind(this.updateProjection_, this)
- );
+ this.gMap_,
+ 'zoom_changed',
+ goog.bind(this.updateProjection_, this)
+ );
};
@@ -145,8 +143,7 @@ vgps3.topo.ch.Map.prototype.updateProjection_ = function() {
/**
- * @return {google.maps.ImageMapType} The map type.
- * @private
+ * @override
*/
vgps3.topo.ch.Map.prototype.getMapType_ = function() {
var mapType = new google.maps.ImageMapType({
@@ -166,18 +163,12 @@ vgps3.topo.ch.Map.prototype.getMapType_ = function() {
/**
- * Returns the URL of a tile.
- *
- * @param {google.maps.Point} coord
- * @param {number} zoom
- * @return {?string}
- *
- * @private
+ * @override
*/
vgps3.topo.ch.Map.prototype.getTileUrl_ = function(coord, zoom) {
- var numTiles = 1 << zoom;
+ var numTiles = Math.pow(2, zoom);
- if (coord.y < 0 || coord.y >= numTiles) {
+ if (!this.isTileVisible_(coord, zoom)) {
return null;
}
return vgps3.topo.ch.TILES_URL
@@ -17,15 +17,15 @@
goog.provide('vgps3.topo.es.Map');
goog.require('vgps3.Map');
-goog.require('vgps3.PluginBase');
+goog.require('vgps3.topo.AbstractTopo');
goog.require('vgps3.proj.GProj');
goog.require('vgps3.proj.Iberpix');
/**
* @constructor Spain IGN map type for google maps.
- * @extends {vgps3.PluginBase}
+ * @extends {vgps3.topo.AbstractTopo}
*/
vgps3.topo.es.Map = function() {
/**
@@ -54,16 +54,16 @@ vgps3.topo.es.Map = function() {
goog.base(this);
};
-goog.inherits(vgps3.topo.es.Map, vgps3.PluginBase);
+goog.inherits(vgps3.topo.es.Map, vgps3.topo.AbstractTopo);
/**
- * Registers this map type in google maps.
- *
* @override
*/
vgps3.topo.es.Map.prototype.init = function(vgps) {
goog.base(this, 'init', vgps);
+ // @see http://www.idee.es/wms/PNOA/PNOA?Request=GetCapabilities&Service=WMS
+ this.setBounds_([[44.0314, -21.3797, 27.1410, 5.0789]]);
this.gMap_.mapTypes.set(vgps3.topo.es.MapTypeId.TERRAIN, /** @type {?} */ (this.getMapType_()));
google.maps.event.addListener(
this.gMap_,
@@ -94,16 +94,16 @@ vgps3.topo.es.Map.prototype.enable_ = function() {
this.updateProjection_(true);
this.zoomListener_ = google.maps.event.addListener(
- this.gMap_,
- 'zoom_changed',
- goog.bind(this.updateProjection_, this)
- );
+ this.gMap_,
+ 'zoom_changed',
+ goog.bind(this.updateProjection_, this)
+ );
this.moveListener_ = google.maps.event.addListener(
- this.gMap_,
- 'center_changed',
- goog.bind(this.updateProjection_, this)
- );
+ this.gMap_,
+ 'center_changed',
+ goog.bind(this.updateProjection_, this)
+ );
};
@@ -151,14 +151,13 @@ vgps3.topo.es.Map.prototype.updateProjection_ = function(opt_force) {
/**
- * @return {google.maps.ImageMapType} The map type.
- * @private
+ * @override
*/
vgps3.topo.es.Map.prototype.getMapType_ = function() {
var mapType = new google.maps.ImageMapType({
getTileUrl: goog.bind(this.getTileUrl_, this),
tileSize: new google.maps.Size(256, 256),
- minZoom: 6,
+ minZoom: vgps3.topo.es.ZOOM_OFFSET,
maxZoom: 18,
name: 'TopoES',
alt: 'Cartes IGN Espagne'
@@ -171,28 +170,21 @@ vgps3.topo.es.Map.prototype.getMapType_ = function() {
/**
- * Returns the URL of a tile.
- *
- * @param {google.maps.Point} coord
- * @param {number} zoom
- * @return {?string}
- *
- * @private
+ * @override
*/
vgps3.topo.es.Map.prototype.getTileUrl_ = function(coord, zoom) {
- var numTiles = 1 << zoom,
- y = -coord.y - 1;
- if (y < 0 || y >= numTiles) {
+ var numTiles = Math.pow(2,zoom);
+
+ if (!this.isTileVisible_(coord, zoom)) {
return null;
}
return vgps3.topo.es.TILES_URL
.replace('{server}', (vgps3.topo.es.serverIndex_++ % 5).toString(10))
.replace('{layer}', this.getLayerName_(zoom))
.replace('{zone}', this.zone_.toString(10))
- .replace('{scale}', (2048 / Math.pow(2, zoom - 6) * 1000).toString(10))
+ .replace('{scale}', (2048 / Math.pow(2, zoom - vgps3.topo.es.ZOOM_OFFSET) * 1000).toString(10))
.replace('{x}', (((coord.x % numTiles) + numTiles) % numTiles).toString(10))
- .replace('{y}', y.toString(10));
-
+ .replace('{y}', (-coord.y - 1).toString(10));
};
@@ -240,7 +232,7 @@ vgps3.topo.es.LAYER_NAMES = ['mapa_millon', 'mapa_mtn200', 'mapa_mtn50', 'mapa_m
/**
* @const
- * @type {number}
+ * @type {number} 2^ZOOM_OFFSET should be >= number of tiles required to cover the whole world
*/
vgps3.topo.es.ZOOM_OFFSET = Math.round(Math.log(2 * Math.PI * 6378137 / (2048 * 256)) / Math.LN2);
Oops, something went wrong.

0 comments on commit 81b9006

Please sign in to comment.