Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Significantly improve zoom performance #220

Merged
merged 2 commits into from
Dec 16, 2013
Merged
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
105 changes: 47 additions & 58 deletions js/ui/datasource.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ Layer.prototype._getCoveringTiles = function() {
this.map.transform.pointCoordinate(tileCenter, {x:this.map.transform.width, y:0}),
this.map.transform.pointCoordinate(tileCenter, {x:this.map.transform.width, y:this.map.transform.height}),
this.map.transform.pointCoordinate(tileCenter, {x:0, y:this.map.transform.height})
], t = [];
], t = {};

points.forEach(function(p) {
Coordinate.izoomTo(p, z);
Expand All @@ -161,28 +161,23 @@ Layer.prototype._getCoveringTiles = function() {
this._scanTriangle(points[0], points[1], points[2], 0, tiles, scanLine);
this._scanTriangle(points[2], points[3], points[0], 0, tiles, scanLine);

var uniques = util.unique(t);

var first = true;
uniques.sort(fromCenter);

return uniques;
return Object.keys(t).sort(fromCenter);

function fromCenter(a, b) {
var at = Tile.fromID(a),
bt = Tile.fromID(b),
ad = Math.abs(at.x - tileCenter.column) +
Math.abs(at.y - tileCenter.row),
bd = Math.abs(bt.x - tileCenter.column) +
Math.abs(bt.y - tileCenter.row);
var ad = Math.abs(a.x - tileCenter.column) +
Math.abs(a.y - tileCenter.row),
bd = Math.abs(b.x - tileCenter.column) +
Math.abs(b.y - tileCenter.row);

return ad - bd;
}

function scanLine(x0, x1, y) {
var x, wx;
if (y >= 0 && y <= tiles) {
for (var x = x0; x < x1; x++) {
t.push(Tile.toID(z, (x + tiles) % tiles, y, Math.floor(x/tiles)));
for (x = x0; x < x1; x++) {
wx = (x + tiles) % tiles;
t[Tile.toID(z, wx, y, Math.floor(x/tiles))] = {x: wx, y: y};
}
}
}
Expand Down Expand Up @@ -221,7 +216,7 @@ Layer.prototype._updateTiles = function() {

var map = this,
zoom = this.map.transform.zoom,
required = this._getCoveringTiles(),
covering = this._getCoveringTiles(),
panTile = this._getPanTile(zoom),
missing = [],
i,
Expand All @@ -236,15 +231,19 @@ Layer.prototype._updateTiles = function() {
else maxCoveringZoom = level;
}

var required = {};

// Add every tile, and add parent/child tiles if they are not yet loaded.
for (i = 0; i < required.length; i++) {
id = required[i];
for (i = 0; i < covering.length; i++) {
id = +covering[i];
var tile = this._addTile(id);

if (!tile.loaded) {
// We need either parent or child tiles that are available immediately
missing.push(id);
}

required[id] = true;
}

findTile: for (i = 0; i < missing.length; i++) {
Expand All @@ -260,61 +259,50 @@ Layer.prototype._updateTiles = function() {
// Potentially add items from the MRU cache.
if (this.cache.has(parent)) {
this._addTile(parent);
}
else if (this.tiles[parent] && this.tiles[parent].loaded) {
continue findTile;
} else if (this.tiles[parent] && this.tiles[parent].loaded) {
// Retain the existing parent tile
if (required.indexOf(parent) < 0) {
required.push(parent);
}
required[parent] = true;
continue findTile;
}
}


// Go down for max 1 zoom levels to find child tiles.
z = missingZoom;
while (z <= maxCoveringZoom && z !== null) {
z = this._childZoomLevel(z);
var childID, parentID;

// Go through the MRU cache and try to find existing tiles that are
// children of this tile.
var keys = this.cache.keys();
var childID, parentID;
for (var j = 0; j < keys.length; j++) {
childID = keys[j];
parentID = Tile.parentWithZoom(childID, missingZoom);
if (parentID == id) {
// Go through the MRU cache and try to find existing tiles that are
// children of this tile.
for (childID in this.cache.list) {
if (this.cache.list[childID].zoom <= maxCoveringZoom) {
parentID = Tile.parentWithZoom(+childID, missingZoom);
if (parentID === id) {
this._addTile(childID);
}
}
}

// Go through all existing tiles and retain those that are children
// of the current missing tile.
for (var child in this.tiles) {
child = +child;
parentID = Tile.parentWithZoom(child, missingZoom);
if (parentID == id && this.tiles[child].loaded) {
// Go through all existing tiles and retain those that are children
// of the current missing tile.
for (childID in this.tiles) {
if (this.tiles[childID].zoom <= maxCoveringZoom) {
var parentID = Tile.parentWithZoom(+childID, missingZoom);
if (parentID === id && this.tiles[childID].loaded) {
// Retain the existing child tile
if (required.indexOf(child) < 0) {
required.push(child);
}
required[childID] = true;
}
}
}

// TODO: panTile causes severe flickering
// if (required.indexOf(panTile) < 0) {
// this._addTile(panTile);
// required.push(panTile);
// }
if (!required[panTile]) {
this._addTile(panTile);
required[panTile] = true;
}
}


var existing = Object.keys(this.tiles).map(parseFloat),
remove = util.difference(existing, required);
var remove = util.keysDifference(this.tiles, required);

for (i = 0; i < remove.length; i++) {
id = remove[i];
id = +remove[i];
map._removeTile(id);
}
};
Expand Down Expand Up @@ -354,9 +342,9 @@ Layer.prototype._addTile = function(id) {
var tile;
if (this.tiles[id]) {
tile = this.tiles[id];
// } else if (this.cache.has(id)) {
// this.tiles[id] = this.cache.get(id);
// return this.tiles[id];
} else if (this.cache.has(id)) {
tile = this.tiles[id] = this.cache.get(id);
return tile;
} else {
tile = this._loadTile(id);
this.fire('tile.add', tile);
Expand All @@ -381,13 +369,14 @@ Layer.prototype._removeTile = function(id) {
// Only add it to the MRU cache if it's already available.
// Otherwise, there's no point in retaining it.
if (tile.loaded) {
// this.cache.add(id, tile);
this.cache.add(id, tile);
} else {
tile.abort();
tile.remove();
}

this.map.removeTile(tile);
tile.remove();

this.fire('tile.remove', tile);
}
}
Expand Down
10 changes: 10 additions & 0 deletions js/util/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ exports.difference = function difference(arr, other) {
});
};

exports.keysDifference = function keysDifference(obj, other) {
var difference = [];
for (var i in obj) {
if (!(i in other)) {
difference.push(i);
}
}
return difference;
}

exports.pluck = function pluck(arr, prop) {
return arr.map(function(el) {
return el[prop];
Expand Down