tile-cover
Advanced tools
Comparing version 2.1.0 to 2.1.1
17
bench.js
@@ -5,6 +5,7 @@ var Benchmark = require('benchmark'); | ||
var polygon = JSON.parse(fs.readFileSync('./test/fixtures/building.geojson')); | ||
var building = JSON.parse(fs.readFileSync('./test/fixtures/building.geojson')); | ||
var line = JSON.parse(fs.readFileSync('./test/fixtures/road.geojson')); | ||
var point = JSON.parse(fs.readFileSync('./test/fixtures/point.geojson')); | ||
var zooms = [6,12,18,20,22,25,28]; | ||
var russia = JSON.parse(fs.readFileSync('./test/fixtures/russia.geojson')); | ||
var zooms = [6,8,10,12,18]; | ||
@@ -17,11 +18,13 @@ var suite = new Benchmark.Suite('tile-cover',{ | ||
addBench(suite, point, 'point', zooms[0], zooms[0]); | ||
zooms.forEach(function(zoom){ | ||
addBench(suite, point, 'point', zoom, zoom); | ||
}); | ||
zooms.forEach(function(zoom){ | ||
addBench(suite, line, 'road', zoom, zoom); | ||
}); | ||
zooms.forEach(function(zoom){ | ||
addBench(suite, polygon, 'building', zoom, zoom); | ||
addBench(suite, building, 'building', zoom, zoom); | ||
}); | ||
zooms.slice(0, 3).forEach(function(zoom){ | ||
addBench(suite, russia, 'russia', zoom, zoom); | ||
}); | ||
@@ -39,2 +42,2 @@ suite.on('cycle', function(event) { | ||
}); | ||
} | ||
} |
116
index.js
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
var tilebelt = require('tilebelt'); | ||
@@ -27,5 +29,8 @@ | ||
function getLocked (geom, limits) { | ||
var locked = []; | ||
var locked = [], | ||
tileHash = {}; | ||
if (geom.type === 'Point') { | ||
locked.push(tilebelt.pointToTile(geom.coordinates[0], geom.coordinates[1], limits.max_zoom)); | ||
} else if (geom.type === 'MultiPoint') { | ||
@@ -41,26 +46,28 @@ var quadkeys = {}; | ||
} | ||
} else if (geom.type === 'LineString') { | ||
locked = hashToArray(lineCover(geom.coordinates, limits.max_zoom)); | ||
lineCover(tileHash, geom.coordinates, limits.max_zoom); | ||
locked = hashToArray(tileHash); | ||
} else if (geom.type === 'MultiLineString') { | ||
var tileHash = {}; | ||
for(var i = 0; i < geom.coordinates.length; i++) { | ||
tileHash = hashMerge(tileHash, lineCover(geom.coordinates[i], limits.max_zoom)); | ||
lineCover(tileHash, geom.coordinates[i], limits.max_zoom); | ||
} | ||
locked = hashToArray(tileHash); | ||
} else if (geom.type === 'Polygon') { | ||
var tileHash = polyRingCover(geom.coordinates, limits.max_zoom); | ||
polyRingCover(tileHash, geom.coordinates, limits.max_zoom); | ||
locked = hashToArray(tileHash); | ||
} else if (geom.type === 'MultiPolygon') { | ||
var tileHash = {}; | ||
for(var i = 0; i < geom.coordinates.length; i++) { | ||
var polyHash = Object.keys(polyRingCover(geom.coordinates[i], limits.max_zoom)); | ||
for(var k = 0; k < polyHash.length; k++) { | ||
tileHash[polyHash[k]] = true; | ||
} | ||
polyRingCover(tileHash, geom.coordinates[i], limits.max_zoom); | ||
} | ||
locked = hashToArray(tileHash); | ||
} else { | ||
throw new Error('Geoemtry type not implemented'); | ||
} | ||
if(limits.min_zoom !== limits.max_zoom){ | ||
if (limits.min_zoom !== limits.max_zoom){ | ||
locked = mergeTiles(locked, limits); | ||
@@ -97,8 +104,7 @@ } | ||
function polyRingCover(ring, max_zoom) { | ||
function polyRingCover(tileHash, ring, max_zoom) { | ||
var segments = getTileSegments(ring, max_zoom); | ||
var tileHash = {}; | ||
var min = [null,Infinity]; | ||
var max = [null,-Infinity]; | ||
for(var i = 0; i < ring[0].length; i++) { | ||
for(var i = 0; i < ring[0].length; i++) { | ||
if(ring[0][i][1] < min[1]) { | ||
@@ -135,5 +141,3 @@ min = ring[0][i]; | ||
// sort intersections by x | ||
intersections = intersections.sort(function(a, b) { | ||
return a[0] - b[0]; | ||
}); | ||
intersections.sort(compareX); | ||
// add tiles between intersection pairs | ||
@@ -146,3 +150,3 @@ for(var i = 0; i < intersections.length - 1; i++) { | ||
while (x <= exit) { | ||
tileHash[x+'/'+y+'/'+max_zoom] = true; | ||
tileHash[toID(x, y, max_zoom)] = true; | ||
x++; | ||
@@ -156,8 +160,12 @@ } | ||
for(var i = 0; i < ring.length; i++) { | ||
tileHash = hashMerge(tileHash, lineCover(ring[i], max_zoom)); | ||
lineCover(tileHash, ring[i], max_zoom); | ||
} | ||
return tileHash; | ||
} | ||
function compareX(a, b) { | ||
return a[0] - b[0]; | ||
} | ||
// Convert a set of rings into segments connecting tile coordinates. | ||
@@ -254,3 +262,3 @@ // Drops degenerate segments and merges sequential horizontal segments. | ||
var denominator, | ||
a, | ||
a, | ||
b, | ||
@@ -292,4 +300,3 @@ numerator1, | ||
function lineCover(coordinates, max_zoom) { | ||
var tileHash = {}; | ||
function lineCover(tileHash, coordinates, max_zoom) { | ||
// break into segments and calculate bbox | ||
@@ -300,4 +307,4 @@ var segments = []; | ||
// add endpoint tiles in case line is contained withing a single tile | ||
tileHash[tilebelt.pointToTile(coordinates[i][0], coordinates[i][1], max_zoom).join('/')] = true; | ||
tileHash[tilebelt.pointToTile(coordinates[iNext][0], coordinates[iNext][1], max_zoom).join('/')] = true; | ||
tileHash[toID.apply(null, tilebelt.pointToTile(coordinates[i][0], coordinates[i][1], max_zoom))] = true; | ||
tileHash[toID.apply(null, tilebelt.pointToTile(coordinates[iNext][0], coordinates[iNext][1], max_zoom))] = true; | ||
// encode segments as tile fractions | ||
@@ -308,6 +315,6 @@ var start = pointToTileFraction(coordinates[i][0], coordinates[i][1], max_zoom); | ||
} | ||
for (var i = 0; i < segments.length; i++) { | ||
var x0 = segments[i][0][0]; | ||
y0 = segments[i][0][1]; | ||
x1 = segments[i][1][0]; | ||
for (var i = 0; i < segments.length; i++) { | ||
var x0 = segments[i][0][0], | ||
y0 = segments[i][0][1], | ||
x1 = segments[i][1][0], | ||
y1 = segments[i][1][1]; | ||
@@ -328,3 +335,3 @@ // verify x0,y0 is far left | ||
/* | ||
vertical intersects: | ||
vertical intersects: | ||
@@ -338,3 +345,3 @@ | | | | | ||
while(x0+x <= x1Floor+1) { | ||
var intersection = lineIntersects(Math.floor(x0+x), y0-10000, Math.floor(x0+x), y0+10000, | ||
var intersection = lineIntersects(Math.floor(x0+x), y0-10000, Math.floor(x0+x), y0+10000, | ||
x0, y0, x1, y1); | ||
@@ -345,4 +352,4 @@ | ||
if(intersection){ | ||
tileHash[Math.floor(intersection[0]-1)+'/'+Math.floor(intersection[1])+'/'+max_zoom] = true; | ||
tileHash[Math.floor(intersection[0])+'/'+Math.floor(intersection[1])+'/'+max_zoom] = true; | ||
tileHash[toID(Math.floor(intersection[0]-1), Math.floor(intersection[1]), max_zoom)] = true; | ||
tileHash[toID(Math.floor(intersection[0]), Math.floor(intersection[1]), max_zoom)] = true; | ||
} | ||
@@ -375,3 +382,3 @@ x++; | ||
while(y0+y >= y1Floor) { | ||
var intersection = lineIntersects(x0-1000, Math.floor(y0+y), x0+1000, Math.floor(y0+y), | ||
var intersection = lineIntersects(x0-1000, Math.floor(y0+y), x0+1000, Math.floor(y0+y), | ||
x0, y0, x1, y1); | ||
@@ -381,4 +388,4 @@ | ||
if(intersection){ | ||
tileHash[Math.floor(intersection[0])+'/'+Math.floor(intersection[1])+'/'+max_zoom] = true; | ||
tileHash[Math.floor(intersection[0])+'/'+Math.floor(intersection[1]-1)+'/'+max_zoom] = true; | ||
tileHash[toID(Math.floor(intersection[0]), Math.floor(intersection[1]), max_zoom)] = true; | ||
tileHash[toID(Math.floor(intersection[0]), Math.floor(intersection[1]-1), max_zoom)] = true; | ||
} | ||
@@ -394,11 +401,9 @@ y--; | ||
var bbox = tilebelt.tileToBBOX(tile); | ||
var tileNW = [bbox[0], bbox[3]]; | ||
var tileSE = [bbox[2], bbox[1]]; | ||
var xTileOffset = tileSE[0] - tileNW[0]; | ||
var xPointOffset = lon - tileNW[0]; | ||
var xTileOffset = bbox[2] - bbox[0]; | ||
var xPointOffset = lon - bbox[0]; | ||
var xPercentOffset = xPointOffset / xTileOffset; | ||
var yTileOffset = tileSE[1] - tileNW[1]; | ||
var yPointOffset = lat - tileNW[1]; | ||
var yTileOffset = bbox[1] - bbox[3]; | ||
var yPointOffset = lat - bbox[3]; | ||
var yPercentOffset = yPointOffset / yTileOffset; | ||
@@ -409,16 +414,7 @@ | ||
function hashMerge(hash1, hash2) { | ||
var keys = Object.keys(hash2); | ||
for(var i = 0; i < keys.length; i++) { | ||
hash1[keys[i]] = true; | ||
} | ||
return hash1; | ||
} | ||
function hashToArray(hash) { | ||
keys = Object.keys(hash); | ||
var keys = Object.keys(hash); | ||
var tiles = []; | ||
for(var i = 0; i < keys.length; i++) { | ||
var tileStrings = keys[i].split('/'); | ||
tiles.push([parseInt(tileStrings[0]), parseInt(tileStrings[1]), parseInt(tileStrings[2])]); | ||
tiles.push(fromID(+keys[i])); | ||
} | ||
@@ -442,1 +438,15 @@ return tiles; | ||
} | ||
function toID(x, y, z) { | ||
var dim = 2 * (1 << z); | ||
return ((dim * y + x) * 32) + z; | ||
} | ||
function fromID(id) { | ||
var z = id % 32, | ||
dim = 2 * (1 << z), | ||
xy = ((id - z) / 32), | ||
x = xy % dim, | ||
y = ((xy - x) / dim) % dim; | ||
return [x, y, z]; | ||
} |
{ | ||
"name": "tile-cover", | ||
"version": "2.1.0", | ||
"version": "2.1.1", | ||
"description": "generate the minimum number of tiles to cover a geojson geometry", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
4169
4313688