Skip to content

Commit

Permalink
add source.removeFeature()
Browse files Browse the repository at this point in the history
Eventually for #200. Currently only works for fills
  • Loading branch information
ansis committed Feb 21, 2014
1 parent 1ed9dbe commit bfa5546
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 13 deletions.
17 changes: 16 additions & 1 deletion debug/site.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var map = new llmr.Map({
sources: {
"mapbox streets": {
type: 'vector',
id: 'streets',
id: 'mapbox streets',
urls: ['http://a.gl-api-us-east-1.tilestream.net/v3/mapbox.mapbox-streets-v4/{z}/{x}/{y}.gl.pbf'],
// urls: ['http://api.tiles.mapbox.com/v3/mapbox.mapbox-streets-v4/{z}/{x}/{y}.vector.pbf'],
zooms: [0, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 14],
Expand All @@ -25,6 +25,21 @@ var map = new llmr.Map({
hash: true
});

document.body.onmousemove = function(e) {
map.featuresAt(e.clientX, e.clientY, {
radius: 1
}, function(err, features) {
features = features.filter(function(f) {
return f._bucket === 'building';
});
features.forEach(function(f) {
map.sources['mapbox streets'].removeFeature(f);
map.update();
});
});

};

// add geojson overlay
var geojson = new llmr.GeoJSONSource({ type: 'Feature', properties: {}, geometry: route.routes[0].geometry});
map.addSource('geojson', geojson);
35 changes: 32 additions & 3 deletions js/geometry/bucket.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

module.exports = Bucket;

function Bucket(info, geometry, placement, indices) {
function Bucket(info, geometry, placement, indices, featureIndices) {

this.info = info;
this.geometry = geometry;
this.placement = placement;
this.indices = indices; // only used after transfer from worker
this.featureIndices = featureIndices || []; // after transfer
this.index = 0;

if (info.type === 'text') {
this.addFeature = this.addText;
Expand Down Expand Up @@ -43,9 +45,13 @@ function Bucket(info, geometry, placement, indices) {
}

Bucket.prototype.start = function() {
this.indices = this.getIndices();
};

Bucket.prototype.getIndices = function() {
var geometry = this.geometry;

this.indices = {
return {
lineVertexIndex: geometry.lineVertex.index,

fillBufferIndex: geometry.fillBufferIndex,
Expand Down Expand Up @@ -77,7 +83,8 @@ Bucket.prototype.end = function() {

Bucket.prototype.toJSON = function() {
return {
indices: this.indices
indices: this.indices,
featureIndices: this.featureIndices
};
};

Expand All @@ -95,6 +102,15 @@ Bucket.prototype.addLine = function(lines) {
};

Bucket.prototype.addFill = function(lines) {

var geometry = this.geometry;
this.featureIndices[this.index] = {
fillBufferIndex: geometry.fillBufferIndex,
fillVertexIndex: geometry.fillVertex.index,
fillElementsIndex: geometry.fillElements.index
};
this.index++;

for (var i = 0; i < lines.length; i++) {
this.geometry.addFill(lines[i]);
}
Expand All @@ -112,6 +128,19 @@ Bucket.prototype.addText = function(lines, faces, shaping) {
}
};

Bucket.prototype.clear = function(start, end) {
// currently only works for fills
var vertex = this.geometry.fillBuffers[start.fillBufferIndex].vertex;

vertex.startUpdate(start.fillVertexIndex);

var numVertices = end.fillVertexIndex - start.fillVertexIndex;
for (var i = 0; i < numVertices; i++) {
vertex.addDegenerate();
}
vertex.endUpdate();
};

// Builds a function body from the JSON specification. Allows specifying other compare operations.
var comparators = {
'==': function(bucket) {
Expand Down
33 changes: 32 additions & 1 deletion js/geometry/buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ function Buffer(buffer) {
this.array = buffer.array;
this.pos = buffer.pos;
}

this.positions = [];
}

Buffer.prototype = {
Expand Down Expand Up @@ -43,14 +45,43 @@ Buffer.prototype = {
this.buffer = gl.createBuffer();
gl.bindBuffer(type, this.buffer);
gl.bufferData(type, new DataView(this.array, 0, this.pos), gl.STATIC_DRAW);
this.glBufferSize = this.pos;
this.positions = [];

// dump array buffer once it's bound to gl
this.array = null;
this.array = new ArrayBuffer(this.defaultLength);
this.length = this.defaultLength;
this.pos = 0;
this.setupViews();

} else {
gl.bindBuffer(type, this.buffer);

// If the buffer has been updated since it was last bound, upload those changes
if (this.positions.length) {
// todo merge before uploading where possible
for (var i = 0; i < this.positions.length; i++) {
var p = this.positions[i];
gl.bufferSubData(type, p.pos, new DataView(this.array, p.start, p.end - p.start));
}
this.positions = [];
}
}
},

startUpdate: function(index) {
this._add = this.add;
if (this.buffer) this.positions.push({ pos: index * this.itemSize, start: this.pos });
this.add = function() {
this._add.apply(this, arguments);
};
},

endUpdate: function() {
this.positions[this.positions.length - 1].end = this.pos;
this.add = this._add;
},

// increase the buffer size by 50% if a new item doesn't fit
resize: function() {
if (this.length < this.pos + this.itemSize) {
Expand Down
5 changes: 3 additions & 2 deletions js/render/drawfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ function drawFill(gl, painter, bucket, layerStyle, stats, params, imageSprite, b
elements.bind(gl);

begin = buffer == bucket.indices.fillBufferIndex ? bucket.indices.fillElementsIndex : 0;
end = buffer == bucket.indices.fillBufferIndexEnd ? bucket.indices.fillElementsIndexEnd : elements.index;
end = buffer == bucket.indices.fillBufferIndexEnd ? bucket.indices.fillElementsIndexEnd : elements.glBufferSize / elements.itemSize;

gl.vertexAttribPointer(painter.fillShader.a_pos, vertex.itemSize / 2, gl.SHORT, false, 0, 0);
gl.drawElements(gl.TRIANGLES, (end - begin) * 3, gl.UNSIGNED_SHORT, begin * 6);
Expand Down Expand Up @@ -104,7 +104,8 @@ function drawFill(gl, painter, bucket, layerStyle, stats, params, imageSprite, b
vertex.bind(gl);

begin = buffer == bucket.indices.fillBufferIndex ? bucket.indices.fillVertexIndex : 0;
end = buffer == bucket.indices.fillBufferIndexEnd ? bucket.indices.fillVertexIndexEnd : vertex.index;
end = buffer == bucket.indices.fillBufferIndexEnd ? bucket.indices.fillVertexIndexEnd : vertex.glBufferSize / vertex.itemSize;

gl.vertexAttribPointer(painter.outlineShader.a_pos, 2, gl.SHORT, false, 0, 0);
gl.drawArrays(gl.LINE_STRIP, begin, (end - begin));

Expand Down
13 changes: 10 additions & 3 deletions js/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,19 @@ util.extend(Map.prototype, {
featuresAt: function(x, y, params, callback) {
var features = [];
var error = null;
util.asyncEach(Object.values(this.sources), function(source, callback) {
source.featuresAt(x, y, params, function(err, result) {
if (result) features = features.concat(result);
var sources = this.sources;
util.asyncEach(Object.keys(sources), function(id, callback) {
sources[id].featuresAt(x, y, params, function(err, result) {
if (result) features = features.concat(result.map(addSource));
if (err) error = err;
callback();
});

function addSource(feature) {
feature._source = id;
return feature;
}

}, function() {
callback(error, features);
});
Expand Down
20 changes: 19 additions & 1 deletion js/ui/source.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,31 @@ util.extend(Source.prototype, {
if (pos.x >= 0 && pos.x < 4096 && pos.y >= 0 && pos.y < 4096) {
// The click is within the viewport. There is only ever one tile in
// a layer that has this property.
return tile.featuresAt(pos, params, callback);
return tile.featuresAt(pos, params, cb);
}
}

function cb(err, features) {
if (err) return callback(err);
for (var k = 0; k < features.length; k++) {
features[k]._tile = id;
}
callback(err, features);
}

callback(null, []);
},

removeFeature: function(feature) {
if (feature._source !== this.id) throw('feature not from this datasource');
var tileID = feature._tile;

// todo update mru cache once that has been reimlemented
if (this.tiles[tileID]) {
this.tiles[tileID].removeFeature(feature);
}
},

_coveringZoomLevel: function(zoom) {
for (var i = this.zooms.length - 1; i >= 0; i--) {
if (this.zooms[i] <= zoom) {
Expand Down
14 changes: 13 additions & 1 deletion js/ui/tile.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ Tile.prototype.onTileLoad = function(data) {

this.buckets = {};
for (var b in data.buckets) {
this.buckets[b] = new Bucket(this.map.style.stylesheet.buckets[b], this.geometry, undefined, data.buckets[b].indices);
this.buckets[b] = new Bucket(this.map.style.stylesheet.buckets[b], this.geometry,
undefined, data.buckets[b].indices, data.buckets[b].featureIndices);
}

this.loaded = true;
Expand Down Expand Up @@ -218,3 +219,14 @@ Tile.prototype.remove = function() {
Tile.prototype.abort = function() {
this.map.dispatcher.send('abort tile', this.id, null, this.workerID);
};

Tile.prototype.removeFeature = function(feature) {
var bucket = this.buckets[feature._bucket];
if (!bucket) throw('missing bucket');
var featureIndices = bucket.featureIndices;
var start = featureIndices[feature.index];
var end = featureIndices[feature.index + 1];
if (!end) throw('implement it');

bucket.clear(start, end);
};
3 changes: 2 additions & 1 deletion js/worker/workertile.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,9 @@ WorkerTile.prototype.parseBucket = function(bucket_name, features, info, faces,
} else {
for (var i = 0; i < features.length; i++) {
var feature = features[i];
bucket.addFeature(feature.loadGeometry());

feature.index = bucket.index;
bucket.addFeature(feature.loadGeometry());
this.featureTree.insert(feature.bbox(), bucket_name, feature);
}
}
Expand Down

0 comments on commit bfa5546

Please sign in to comment.