diff --git a/index.js b/index.js index 39a1993..7f5a39f 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ var crypto = require('crypto'); module.exports = abaculus; function abaculus(arg, callback) { - var z = arg.zoom || 1, + var z = arg.zoom || 0, s = arg.scale || 1, center = arg.center || null, bbox = arg.bbox || null, @@ -16,17 +16,21 @@ function abaculus(arg, callback) { limit = arg.limit || 19008, tileSize = arg.tileSize || 256; - if (!getTile) return callback(new Error('Invalid function for getting tiles')); + if (!getTile) return callback(new Error('Invalid function for getting tiles.')); if (center) { // get center coordinates in px from lng,lat - center = abaculus.coordsFromCenter(z, s, center, limit, tileSize); + center = abaculus.coordsFromCenter(z, s, center, tileSize); } else if (bbox) { // get center coordinates in px from [w,s,e,n] bbox - center = abaculus.coordsFromBbox(z, s, bbox, limit, tileSize); + center = abaculus.coordsFromBbox(z, s, bbox, tileSize); } else { return callback(new Error('No coordinates provided.')); } + + if (center.w <= 0 || center.h <= 0) return callback(new Error('Incorrect coordinates.')); + if (center.w >= limit || center.h >= limit) return callback(new Error('Desired image is too large.')); + // generate list of tile coordinates center var coords = abaculus.tileList(z, s, center, tileSize); @@ -34,35 +38,31 @@ function abaculus(arg, callback) { abaculus.stitchTiles(coords, format, quality, getTile, callback); } -abaculus.coordsFromBbox = function(z, s, bbox, limit, tileSize) { - var sm = new SphericalMercator({ size: tileSize * s }); +abaculus.coordsFromBbox = function(z, s, bbox, tileSize) { + var sm = new SphericalMercator({ size: (tileSize || 256) * s }); var topRight = sm.px([bbox[2], bbox[3]], z), bottomLeft = sm.px([bbox[0], bbox[1]], z); var center = {}; center.w = topRight[0] - bottomLeft[0]; center.h = bottomLeft[1] - topRight[1]; - if (center.w <= 0 || center.h <= 0) throw new Error('Incorrect coordinates'); - var origin = [topRight[0] - center.w / 2, topRight[1] + center.h / 2]; center.x = origin[0]; center.y = origin[1]; - center.w = Math.round(center.w * s); - center.h = Math.round(center.h * s); + center.w = Math.round(center.w); + center.h = Math.round(center.h); - if (center.w >= limit || center.h >= limit) throw new Error('Desired image is too large.'); return center; }; -abaculus.coordsFromCenter = function(z, s, center, limit, tileSize) { - var sm = new SphericalMercator({ size: tileSize * s }); +abaculus.coordsFromCenter = function(z, s, center, tileSize) { + var sm = new SphericalMercator({ size: (tileSize || 256) * s }); var origin = sm.px([center.x, center.y], z); center.x = origin[0]; center.y = origin[1]; center.w = Math.round(center.w * s); center.h = Math.round(center.h * s); - if (center.w >= limit || center.h >= limit) throw new Error('Desired image is too large.'); return center; }; @@ -78,8 +78,8 @@ abaculus.tileList = function(z, s, center, tileSize) { var ts = Math.round(size * s); var centerCoordinate = { - column: x / size, - row: y / size, + column: x / ts, + row: y / ts, zoom: z }; @@ -112,7 +112,7 @@ abaculus.tileList = function(z, s, center, tileSize) { } var tl = floorObj(pointCoordinate({x: 0, y:0})); - var br = floorObj(pointCoordinate(dimensions)); + var br = floorObj(pointCoordinate({ x: dimensions.x - 1, y: dimensions.y - 1 })); var coords = {}; coords.tiles = []; var tileCount = (br.column - tl.column + 1) * (br.row - tl.row + 1); @@ -131,7 +131,10 @@ abaculus.tileList = function(z, s, center, tileSize) { Math.pow(2,c.zoom) + c.column : c.column % Math.pow(2,c.zoom); - if (c.row < 0) continue; + c.row = c.row < 0 ? + Math.pow(2, c.zoom) + c.row : + c.row % Math.pow(2, c.zoom); + coords.tiles.push({ z: c.zoom, x: c.column, diff --git a/test/test.js b/test/test.js index 46a36dd..e745e39 100644 --- a/test/test.js +++ b/test/test.js @@ -11,7 +11,8 @@ var zoom = 5, y = 4096, quality = 256, format = 'png', - limit = 19008; + limit = 19008, + tileSize = 256; // fixtures @@ -25,27 +26,27 @@ describe('Get center from bbox', function() { it('should fail if (x1, y1) and (x2,y2) are equal', function(done) { var bbox = [0, 0, 0, 0]; - assert.throws( function() { - printer.coordsFromBbox(zoom, scale, bbox, limit); - }, /Incorrect coordinates/); + var center = printer.coordsFromBbox(zoom, scale, bbox, tileSize); + assert(center.w <= 0 || center.h <= 0, 'Incorrect coordinates') + done(); }); it('should fail if the image is too large', function(done) { var bbox = [-60, -60, 60, 60]; - assert.throws( function() { - printer.coordsFromBbox(7, 2, bbox, limit); - }, /Desired image is too large./); + var center = printer.coordsFromBbox(7, 2, bbox, tileSize); + assert(center.w >= limit || center.h >= limit, 'Desired image is too large') + done(); }); it('should return the correct coordinates', function(done) { var bbox = [-60, -60, 60, 60]; - var center = printer.coordsFromBbox(zoom, scale, bbox, limit); - assert.deepEqual(center.w, 10920); + var center = printer.coordsFromBbox(zoom, scale, bbox, tileSize); + assert.deepEqual(center.w, 10922); assert.deepEqual(center.h, 13736); - assert.deepEqual(center.x, x); - assert.deepEqual(center.y, y); + assert.deepEqual(center.x, 16384); + assert.deepEqual(center.y, 16384); done(); }); }); @@ -58,9 +59,10 @@ describe('get coordinates from center', function() { w: 4752, h: 4752 }; - assert.throws( function() { - printer.coordsFromCenter(zoom, scale, center, limit); - }, /Desired image is too large./); + + var center = printer.coordsFromCenter(zoom, scale, center, tileSize); + assert(center.w >= limit || center.h >= limit, 'Desired image is too large') + done(); }); it('should return correct origin coords', function(done) { @@ -70,9 +72,9 @@ describe('get coordinates from center', function() { w: 800, h: 800 }; - center = printer.coordsFromCenter(zoom, scale, center, limit); - assert.equal(center.x, x); - assert.equal(center.y, 3631); + var center2 = printer.coordsFromCenter(zoom, scale, center, tileSize); + assert.equal(center2.x, 16384); + assert.equal(center2.y, 14525); done(); }); }); @@ -82,13 +84,13 @@ describe('create list of tile coordinates', function() { var expectedCoords = { tiles: [ - { z: 5, x: 15, y: 15, px: -112, py: -108 }, - { z: 5, x: 15, y: 16, px: -112, py: 916 }, - { z: 5, x: 16, y: 15, px: 912, py: -108 }, - { z: 5, x: 16, y: 16, px: 912, py: 916 } + { z: 5, x: 3, y: 3, px: -112, py: -108 }, + { z: 5, x: 3, y: 4, px: -112, py: 916 }, + { z: 5, x: 4, y: 3, px: 912, py: -108 }, + { z: 5, x: 4, y: 4, px: 912, py: 916 } ], dimensions: { x: 1824, y: 1832 }, - center: { row: 16, column: 16, zoom: 5 }, + center: { row: 4, column: 4, zoom: 5 }, scale: 4 }; it('should return a tiles object with correct coords', function(done) {