From c2797ad5d223f6d66c8b5b59a117e99d27137d59 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 18 Oct 2016 22:28:55 -0400 Subject: [PATCH] Fixed several low-zoom errors * Fixed zoom to allow zoom 0 prev patch: https://github.com/kartotherian/abaculus/commit/8b495f43f41730c66cf416289f68813781d42046 * Fixed bug with multiple negative world overlaping prev patch: https://github.com/kartotherian/abaculus/commit/ce0ff07a194ffe7619c22e562cc2c3a08f646c90 * Fixed when y exceeds max rows prev patch: https://github.com/kartotherian/abaculus/commit/89bcff125ce6b42a5fd5ff6da204376cea2e5ae6 --- index.js | 18 +++---- package.json | 7 ++- test/test.js | 134 +++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 122 insertions(+), 37 deletions(-) diff --git a/index.js b/index.js index fcf7264..6485e66 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, @@ -107,15 +107,15 @@ abaculus.tileList = function(z, s, center, tileSize) { return { row: Math.floor(obj.row), column: Math.floor(obj.column), - zoom: Math.floor(obj.zoom) + zoom: obj.zoom }; } + var maxTilesInRow = Math.pow(2, z); var tl = floorObj(pointCoordinate({x: 0, y:0})); var br = floorObj(pointCoordinate(dimensions)); var coords = {}; coords.tiles = []; - var tileCount = (br.column - tl.column + 1) * (br.row - tl.row + 1); for (var column = tl.column; column <= br.column; column++) { for (var row = tl.row; row <= br.row; row++) { @@ -127,11 +127,10 @@ abaculus.tileList = function(z, s, center, tileSize) { var p = coordinatePoint(c); // Wrap tiles with negative coordinates. - c.column = c.column < 0 ? - Math.pow(2,c.zoom) + c.column : - c.column % Math.pow(2,c.zoom); + c.column = c.column % maxTilesInRow; + if (c.column < 0) c.column = maxTilesInRow + c.column; - if (c.row < 0) continue; + if (c.row < 0 || c.row >= maxTilesInRow) continue; coords.tiles.push({ z: c.zoom, x: c.column, @@ -151,7 +150,6 @@ abaculus.tileList = function(z, s, center, tileSize) { abaculus.stitchTiles = function(coords, format, quality, getTile, callback) { if (!coords) return callback(new Error('No coords object.')); var tileQueue = queue(32); - var dat = []; var w = coords.dimensions.x, h = coords.dimensions.y, s = coords.scale, @@ -168,7 +166,7 @@ abaculus.stitchTiles = function(coords, format, quality, getTile, callback) { y: py, reencode: true }) - } + }; cb.scale = s; cb.format = format; // getTile is a function that returns @@ -181,7 +179,7 @@ abaculus.stitchTiles = function(coords, format, quality, getTile, callback) { if (err) return callback(err); if (!data) return callback(new Error('No tiles to stitch.')); var headers = []; - data.forEach(function(d, i) { + data.forEach(function(d) { headers.push(d.headers); }); diff --git a/package.json b/package.json index 71c2dbb..f484ca6 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,11 @@ { "name": "abaculus", - "version": "2.0.1", + "version": "2.0.2", "description": "stitches map tiles together for high-res exporting from tm2", "main": "index.js", + "contributors": [ + "Yuri Astrakhan " + ], "scripts": { "test": "mocha -R spec" }, @@ -16,6 +19,6 @@ "d3-queue": "^2.0.2" }, "devDependencies": { - "mocha": "1.x" + "mocha": "2.x" } } diff --git a/test/test.js b/test/test.js index 46a36dd..d660694 100644 --- a/test/test.js +++ b/test/test.js @@ -22,23 +22,21 @@ var tiles = fs.readdirSync(path.resolve(__dirname + '/fixtures/')).reduce(functi }, {}); describe('Get center from bbox', function() { - it('should fail if (x1, y1) and (x2,y2) are equal', function(done) { + it('should fail if (x1, y1) and (x2,y2) are equal', function() { var bbox = [0, 0, 0, 0]; assert.throws( function() { printer.coordsFromBbox(zoom, scale, bbox, limit); }, /Incorrect coordinates/); - done(); }); - it('should fail if the image is too large', function(done) { + it('should fail if the image is too large', function() { var bbox = [-60, -60, 60, 60]; assert.throws( function() { printer.coordsFromBbox(7, 2, bbox, limit); }, /Desired image is too large./); - done(); }); - it('should return the correct coordinates', function(done) { + it('should return the correct coordinates', function() { var bbox = [-60, -60, 60, 60]; var center = printer.coordsFromBbox(zoom, scale, bbox, limit); @@ -46,12 +44,11 @@ describe('Get center from bbox', function() { assert.deepEqual(center.h, 13736); assert.deepEqual(center.x, x); assert.deepEqual(center.y, y); - done(); }); }); describe('get coordinates from center', function() { - it('should should fail if the image is too large', function(done) { + it('should should fail if the image is too large', function() { var center = { x: 0, y: 0, @@ -61,9 +58,8 @@ describe('get coordinates from center', function() { assert.throws( function() { printer.coordsFromCenter(zoom, scale, center, limit); }, /Desired image is too large./); - done(); }); - it('should return correct origin coords', function(done) { + it('should return correct origin coords', function() { var center = { x: 0, y: 20, @@ -73,28 +69,116 @@ describe('get coordinates from center', function() { center = printer.coordsFromCenter(zoom, scale, center, limit); assert.equal(center.x, x); assert.equal(center.y, 3631); - done(); + }); + it('should return correct origin coords for negative y', function() { + var zoom = 2, + center = { + x: 39, + y: -14, + w: 1000, + h: 1000 + }; + center = printer.coordsFromCenter(zoom, scale, center, limit); + assert.equal(center.x, 623); + assert.equal(center.y, 552); }); }); describe('create list of tile coordinates', function() { - var center = {x: x, y: y, w: 1824, h: 1832 }; - - 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 } - ], - dimensions: { x: 1824, y: 1832 }, - center: { row: 16, column: 16, zoom: 5 }, - scale: 4 - }; - it('should return a tiles object with correct coords', function(done) { + it('should return a tiles object with correct coords', function() { + var zoom = 5, + scale = 4, + width = 1824, + height = 1832, + center = { x: 4096, y: 4096, w: width, h: height }; + + var expectedCoords = { + tiles: [ + { z: zoom, x: 15, y: 15, px: -112, py: -108 }, + { z: zoom, x: 15, y: 16, px: -112, py: 916 }, + { z: zoom, x: 16, y: 15, px: 912, py: -108 }, + { z: zoom, x: 16, y: 16, px: 912, py: 916 } + ], + dimensions: { x: width, y: height }, + center: { row: 16, column: 16, zoom: zoom }, + scale: scale + }; + var coords = printer.tileList(zoom, scale, center); + assert.deepEqual(JSON.stringify(coords), JSON.stringify(expectedCoords)); + }); + + it('should return a tiles object with correct coords when image exceeds y coords', function() { + var zoom = 2, + scale = 1, + width = 1000, + height = 1000, + center = {x: 623, y: 552, w: width, h: height}; + + var expectedCoords = { + tiles: [ + { z: zoom, x: 0, y: 0, px: -123, py: -52 }, + { z: zoom, x: 0, y: 1, px: -123, py: 204 }, + { z: zoom, x: 0, y: 2, px: -123, py: 460 }, + { z: zoom, x: 0, y: 3, px: -123, py: 716 }, + { z: zoom, x: 1, y: 0, px: 133, py: -52 }, + { z: zoom, x: 1, y: 1, px: 133, py: 204 }, + { z: zoom, x: 1, y: 2, px: 133, py: 460 }, + { z: zoom, x: 1, y: 3, px: 133, py: 716 }, + { z: zoom, x: 2, y: 0, px: 389, py: -52 }, + { z: zoom, x: 2, y: 1, px: 389, py: 204 }, + { z: zoom, x: 2, y: 2, px: 389, py: 460 }, + { z: zoom, x: 2, y: 3, px: 389, py: 716 }, + { z: zoom, x: 3, y: 0, px: 645, py: -52 }, + { z: zoom, x: 3, y: 1, px: 645, py: 204 }, + { z: zoom, x: 3, y: 2, px: 645, py: 460 }, + { z: zoom, x: 3, y: 3, px: 645, py: 716 }, + { z: zoom, x: 0, y: 0, px: 901, py: -52 }, + { z: zoom, x: 0, y: 1, px: 901, py: 204 }, + { z: zoom, x: 0, y: 2, px: 901, py: 460 }, + { z: zoom, x: 0, y: 3, px: 901, py: 716 } + ], + dimensions: {x: width, y: height}, + center: {row: 2, column: 2, zoom: zoom}, + scale: scale + }; + var coords = printer.tileList(zoom, scale, center); + assert.deepEqual(JSON.stringify(coords), JSON.stringify(expectedCoords)); + }); + + it('should return a tiles object with correct coords when image is much bigger than world', function() { + var zoom = 1, + scale = 1, + width = 2000, + height = 2100, + center = {x: 100, y: 100, w: width, h: height}; + + var expectedCoords = { + tiles: [ + {z: zoom, x: 0, y: 0, px: -124, py: 950}, + {z: zoom, x: 0, y: 1, px: -124, py: 1206}, + {z: zoom, x: 1, y: 0, px: 132, py: 950}, + {z: zoom, x: 1, y: 1, px: 132, py: 1206}, + {z: zoom, x: 0, y: 0, px: 388, py: 950}, + {z: zoom, x: 0, y: 1, px: 388, py: 1206}, + {z: zoom, x: 1, y: 0, px: 644, py: 950}, + {z: zoom, x: 1, y: 1, px: 644, py: 1206}, + {z: zoom, x: 0, y: 0, px: 900, py: 950}, + {z: zoom, x: 0, y: 1, px: 900, py: 1206}, + {z: zoom, x: 1, y: 0, px: 1156, py: 950}, + {z: zoom, x: 1, y: 1, px: 1156, py: 1206}, + {z: zoom, x: 0, y: 0, px: 1412, py: 950}, + {z: zoom, x: 0, y: 1, px: 1412, py: 1206}, + {z: zoom, x: 1, y: 0, px: 1668, py: 950}, + {z: zoom, x: 1, y: 1, px: 1668, py: 1206}, + {z: zoom, x: 0, y: 0, px: 1924, py: 950}, + {z: zoom, x: 0, y: 1, px: 1924, py: 1206} + ], + dimensions: {x: width, y: height}, + center: {row: 0, column: 0, zoom: zoom}, + scale: scale + }; var coords = printer.tileList(zoom, scale, center); assert.deepEqual(JSON.stringify(coords), JSON.stringify(expectedCoords)); - done(); }); });