Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions lib/tilejson.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ var path = require('path');
var fs = require('fs');
var url = require('url');
var get = require('get');
var mercator = new (require('sphericalmercator'))();
var tiletype = require('tiletype');
var EventEmitter = require('events').EventEmitter;
var Agent = require('agentkeepalive');
Expand Down Expand Up @@ -131,10 +132,35 @@ TileJSON.prototype.getInfo = function(callback) {
else callback(null, this.data);
};

TileJSON.prototype.validate = function(z, x, y) {
if (!this.data) {
// not loaded
return false;
}

if (z < Math.max(0, this.data.minzoom | 0) || z > (this.data.maxzoom || Infinity)) {
// out of available zoom range
return false;
}

var xyz = mercator.xyz(this.data.bounds || [-180, -85.0511, 180, 85.0511], z);

if (x < xyz.minX ||
x > xyz.maxX ||
y < xyz.minY ||
y > xyz.maxY) {
// out of bounds
return false;
}

return true;
};

// z, x, y are XYZ coordinates.
TileJSON.prototype.getTile = function(z, x, y, callback) {
if (!this.data) return callback(new Error('Tilesource not loaded'));
if (!this.data.tiles) return callback(new Error('Tile does not exist'));
if (!this.validate(z, x, y)) return setImmediate(callback, new Error('Tile does not exist'));

var url = this._prepareURL(this.data.tiles[0], z, x, y);
this.get(url, function(err, data, headers) {
Expand Down Expand Up @@ -166,6 +192,7 @@ TileJSON.prototype._prepareURL = function(url, z, x, y) {
TileJSON.prototype.getGrid = function(z, x, y, callback) {
if (!this.data) return callback(new Error('Gridsource not loaded'));
if (!this.data.grids) return callback(new Error('Grid does not exist'));
if (!this.validate(z, x, y)) return setImmediate(callback, new Error('Grid does not exist'));

var url = this._prepareURL(this.data.grids[0], z, x, y);
this.get(url, function(err, grid, headers) {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"dependencies": {
"get": "1.3.x",
"agentkeepalive": "0.2.x",
"tiletype": "0.0.x"
"tiletype": "0.0.x",
"sphericalmercator": "^1.0.2"
},
"devDependencies": {
"mocha": "*"
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/world-bright.tilejson
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"tiles": [ "http://a.tiles.mapbox.com/v3/mapbox.world-bright/{z}/{x}/{y}.png" ],
"minzoom": 0,
"maxzoom": 11,
"bounds": [ -180, -85, 180, 85 ]
"bounds": [ -80, -85, 180, 85 ]
}
24 changes: 24 additions & 0 deletions test/tilejson.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,22 @@ describe('tiles', function() {
});
});

it('should fail for zoom out of range', function(done) {
world_bright.getTile(12, 2, 2, function(err, data, headers) {
assert.ok(err);
assert.equal(err.message, 'Tile does not exist');
done();
});
});

it('should fail for coordinates out of bounds', function(done) {
world_bright.getTile(2, 0, 2, function(err, data, headers) {
assert.ok(err);
assert.equal(err.message, 'Tile does not exist');
done();
});
});

it('https should load tile 0/0/0', function(done) {
world_bright_ssl.getTile(0, 0, 0, function(err, data, headers) {
if (err) throw err;
Expand Down Expand Up @@ -310,6 +326,14 @@ describe('grids', function() {
done();
});
});

it('should fail for zoom out of range', function(done) {
grid_source.getGrid(12, 2, 2, function(err, data, headers) {
assert.ok(err);
assert.equal(err.message, 'Grid does not exist');
done();
});
});
});

describe('tiles from bad server', function() {
Expand Down