Skip to content

Commit

Permalink
better tile drill-down strategy, closes #21
Browse files Browse the repository at this point in the history
when we drill-down to a specific tile, we now always cut each tile on
the path to 4 tiles instead of cutting out only one child; this makes
batch on-demand tiling faster in dynamic applications, avoids
unnecessary clipping, and makes sure we never keep references to
geometry we no longer need, which leads to better memory footprint
  • Loading branch information
mourner committed Mar 19, 2015
1 parent 1e5adfb commit 6f82954
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 23 deletions.
18 changes: 18 additions & 0 deletions debug/viz.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,21 @@ backButton.onclick = function () {
drawTile();
if (z === 0) backButton.style.display = 'none';
};

/*eslint-disable no-unused-vars */
function drillDown() {
var i, j;
console.time('drill down');
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
tileIndex.getTile(7, 30 + i, 45 + j);
}
}
for (i = 0; i < 10; i++) {
for (j = 0; j < 10; j++) {
tileIndex.getTile(8, 70 + i, 100 + j);
}
}
console.timeEnd('drill down');
}
/*eslint-enable no-unused-vars */
51 changes: 29 additions & 22 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,29 @@ GeoJSONVT.prototype.splitTile = function (features, z, x, y, cz, cx, cy) {
}
}

if (!cz && (z === options.maxZoom || tile.numPoints <= options.maxPoints ||
isClippedSquare(tile.features, extent, buffer)) || z === options.baseZoom || z === cz) {
tile.source = features;
continue; // stop tiling
// save reference to original geometry in tile so that we can drill down later if we stop now
tile.source = features;

// stop tiling if the tile is degenerate
if (isClippedSquare(tile.features, extent, buffer)) continue;

// if it's the first-pass tiling
if (!cz) {
// stop tiling if we reached max zoom, or if the tile is too simple
if (z === options.maxZoom || tile.numPoints <= options.maxPoints) continue;

// if a drilldown to a specific tile
} else {
// stop tiling if we reached base zoom or our target tile zoom
if (z === options.baseZoom || z === cz) continue;

// stop tiling if it's not an ancestor of the target tile
var m = 1 << (cz - z);
if (x !== Math.floor(cx / m) && y !== Math.floor(cy / m)) continue;
}

if (cz) tile.source = features;
else tile.source = null;
// if we slice further down, no need to keep source geometry
tile.source = null;

if (debug > 1) console.time('clipping');

Expand All @@ -103,29 +118,21 @@ GeoJSONVT.prototype.splitTile = function (features, z, x, y, cz, cx, cy) {
k2 = 0.5 - k1,
k3 = 0.5 + k1,
k4 = 1 + k1,
tl, bl, tr, br, left, right;

tl, bl, tr, br, left, right,
m, goLeft, goTop;

if (cz) { // if we have a specific tile to drill down to, calculate where to go
m = 1 << (cz - z);
goLeft = cx / m - x < 0.5;
goTop = cy / m - y < 0.5;
}

tl = bl = tr = br = left = right = null;
tl = bl = tr = br = null;

if (!cz || goLeft) left = clip(features, z2, x - k1, x + k3, 0, intersectX);
if (!cz || !goLeft) right = clip(features, z2, x + k2, x + k4, 0, intersectX);
left = clip(features, z2, x - k1, x + k3, 0, intersectX);
right = clip(features, z2, x + k2, x + k4, 0, intersectX);

if (left) {
if (!cz || goTop) tl = clip(left, z2, y - k1, y + k3, 1, intersectY);
if (!cz || !goTop) bl = clip(left, z2, y + k2, y + k4, 1, intersectY);
tl = clip(left, z2, y - k1, y + k3, 1, intersectY);
bl = clip(left, z2, y + k2, y + k4, 1, intersectY);
}

if (right) {
if (!cz || goTop) tr = clip(right, z2, y - k1, y + k3, 1, intersectY);
if (!cz || !goTop) br = clip(right, z2, y + k2, y + k4, 1, intersectY);
tr = clip(right, z2, y - k1, y + k3, 1, intersectY);
br = clip(right, z2, y + k2, y + k4, 1, intersectY);
}

if (debug > 1) console.timeEnd('clipping');
Expand Down
3 changes: 2 additions & 1 deletion src/simplify.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ function simplify(points, tolerance) {

if (maxSqDist > sqTolerance) {
points[index][2] = maxSqDist; // save the point importance in squared pixels as a z coordinate
stack.push(first, index);
stack.push(first);
stack.push(index);
first = index;

} else {
Expand Down

0 comments on commit 6f82954

Please sign in to comment.