Skip to content

Commit

Permalink
combine featuresIn and featuresAt internally
Browse files Browse the repository at this point in the history
fix #1822
  • Loading branch information
ansis committed Feb 17, 2016
1 parent dba30d2 commit 7c69069
Show file tree
Hide file tree
Showing 14 changed files with 308 additions and 332 deletions.
43 changes: 21 additions & 22 deletions js/data/feature_tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,6 @@ FeatureTree.prototype.query = function(args, styleLayersByID) {
if (this.toBeInserted.length) this._load();

var params = args.params || {},
x = args.x,
y = args.y,
pixelsToTileUnits = EXTENT / args.tileSize / args.scale,
result = [];

Expand All @@ -73,25 +71,25 @@ FeatureTree.prototype.query = function(args, styleLayersByID) {
additionalRadius = Math.max(additionalRadius, styleLayerDistance * pixelsToTileUnits);
}

var bounds, symbolQueryBox, queryPolygon;
if (x !== undefined && y !== undefined) {
// a point query
bounds = [x - additionalRadius, y - additionalRadius, x + additionalRadius, y + additionalRadius];
symbolQueryBox = new CollisionBox(new Point(x, y), 0, 0, 0, 0, args.scale, null);
queryPolygon = [new Point(x, y)];
} else {
// a rectangle query
bounds = [ args.minX, args.minY, args.maxX, args.maxY ];
symbolQueryBox = new CollisionBox(new Point(args.minX, args.minY), 0, 0, args.maxX - args.minX, args.maxY - args.minY, args.scale, null);
queryPolygon = [
new Point(args.minX, args.minY),
new Point(args.maxX, args.minY),
new Point(args.maxX, args.maxY),
new Point(args.minX, args.maxY),
new Point(args.minX, args.minY)
];
var queryGeometry = args.queryGeometry.map(function(p) {
return new Point(p.x, p.y);
});

var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
for (var i = 0; i < queryGeometry.length; i++) {
var p = queryGeometry[i];
minX = Math.min(minX, p.x);
minY = Math.min(minY, p.y);
maxX = Math.max(maxX, p.x);
maxY = Math.max(maxY, p.y);
}

var bounds = [minX - additionalRadius, minY - additionalRadius, maxX + additionalRadius, maxY + additionalRadius];
var symbolQueryBox = new CollisionBox(new Point(minX, minY), 0, 0, maxX - minX, maxY - minY, args.scale, null);

var matching = this.rtree.search(bounds).concat(this.collisionTile.getFeaturesAt(symbolQueryBox, args.scale));

for (var k = 0; k < matching.length; k++) {
Expand Down Expand Up @@ -146,7 +144,7 @@ FeatureTree.prototype.query = function(args, styleLayersByID) {

function translate(translate, translateAnchor) {
if (!translate[0] && !translate[1]) {
return queryPolygon;
return queryGeometry;
}

translate = Point.convert(translate);
Expand All @@ -156,8 +154,8 @@ FeatureTree.prototype.query = function(args, styleLayersByID) {
}

var translated = [];
for (var i = 0; i < queryPolygon.length; i++) {
translated.push(queryPolygon[i].sub(translate._mult(pixelsToTileUnits)));
for (var i = 0; i < queryGeometry.length; i++) {
translated.push(queryGeometry[i].sub(translate._mult(pixelsToTileUnits)));
}
return translated;
}
Expand Down Expand Up @@ -199,6 +197,7 @@ function polygonIntersectsBufferedMultiPoint(polygon, rings, radius) {
if (pointIntersectsBufferedLine(point, polygon, radius)) return true;
}
}
return false;
}

function polygonIntersectsMultiPolygon(polygon, multiPolygon) {
Expand Down
3 changes: 1 addition & 2 deletions js/source/geojson_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,7 @@ GeoJSONSource.prototype = util.inherit(Evented, /** @lends GeoJSONSource.prototy
getVisibleCoordinates: Source._getVisibleCoordinates,
getTile: Source._getTile,

featuresAt: Source._vectorFeaturesAt,
featuresIn: Source._vectorFeaturesIn,
queryFeatures: Source._queryVectorFeatures,
getTileData: Source._getVectorTileData,

_updateData: function() {
Expand Down
6 changes: 1 addition & 5 deletions js/source/image_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,7 @@ ImageSource.prototype = util.inherit(Evented, {
* be selectable, so always return an empty array.
* @private
*/
featuresAt: function(point, params, callback) {
return callback(null, []);
},

featuresIn: function(bbox, params, callback) {
queryFeatures: function(point, params, callback) {
return callback(null, []);
},

Expand Down
6 changes: 1 addition & 5 deletions js/source/raster_tile_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,7 @@ RasterTileSource.prototype = util.inherit(Evented, {
if (tile.texture) this.map.painter.saveTexture(tile.texture);
},

featuresAt: function(point, params, callback) {
callback(null, []);
},

featuresIn: function(bbox, params, callback) {
queryFeatures: function(point, params, callback) {
callback(null, []);
},

Expand Down
34 changes: 4 additions & 30 deletions js/source/source.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,47 +68,21 @@ exports._getVisibleCoordinates = function() {
else return this._pyramid.renderedIDs().map(TileCoord.fromID);
};

exports._vectorFeaturesAt = function(coord, params, classes, zoom, bearing, callback) {
exports._queryVectorFeatures = function(queryGeometry, params, classes, zoom, bearing, callback) {
if (!this._pyramid)
return callback(null, []);

var result = this._pyramid.tileAt(coord);
if (!result)
return callback(null, []);

this.dispatcher.send('query features', {
uid: result.tile.uid,
x: result.x,
y: result.y,
scale: result.scale,
tileSize: result.tileSize,
classes: classes,
zoom: zoom,
bearing: bearing,
source: this.id,
params: params
}, callback, result.tile.workerID);
};


exports._vectorFeaturesIn = function(bounds, params, classes, zoom, bearing, callback) {
if (!this._pyramid)
return callback(null, []);

var results = this._pyramid.tilesIn(bounds);
var results = this._pyramid.tilesIn(queryGeometry);
if (!results)
return callback(null, []);

util.asyncAll(results, function queryTile(result, cb) {
this.dispatcher.send('query features', {
uid: result.tile.uid,
source: this.id,
minX: result.minX,
maxX: result.maxX,
minY: result.minY,
maxY: result.maxY,
queryGeometry: result.queryGeometry,
scale: result.scale,
tileSize: result.tileSize,
tileSize: result.tile.tileSize,
classes: classes,
zoom: zoom,
bearing: bearing,
Expand Down
63 changes: 29 additions & 34 deletions js/source/tile_pyramid.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
var Tile = require('./tile');
var TileCoord = require('./tile_coord');
var Point = require('point-geometry');
var Coordinate = require('../geo/coordinate');
var Cache = require('../util/mru_cache');
var util = require('../util/util');
var EXTENT = require('../data/buffer').EXTENT;
Expand Down Expand Up @@ -349,57 +350,51 @@ TilePyramid.prototype = {
this._cache.reset();
},

/**
* For a given coordinate, search through our current tiles and attempt
* to find a tile at that point
* @param {Coordinate} coord
* @returns {Object} tile
* @private
*/
tileAt: function(coord) {
var ids = this.orderedIDs();
for (var i = 0; i < ids.length; i++) {
var tile = this._tiles[ids[i]];
var pos = tile.positionAt(coord);
if (pos && pos.x >= 0 && pos.x < EXTENT && pos.y >= 0 && pos.y < EXTENT) {
// The click is within the viewport. There is only ever one tile in
// a layer that has this property.
return {
tile: tile,
x: pos.x,
y: pos.y,
scale: Math.pow(2, this.transform.zoom - tile.coord.z),
tileSize: tile.tileSize
};
}
}
},

/**
* Search through our current tiles and attempt to find the tiles that
* cover the given bounds.
* @param {Array<Coordinate>} bounds [minxminy, maxxmaxy] coordinates of the corners of bounding rectangle
* @param {Array<Coordinate>} queryGeometry coordinates of the corners of bounding rectangle
* @returns {Array<Object>} result items have {tile, minX, maxX, minY, maxY}, where min/max bounding values are the given bounds transformed in into the coordinate space of this tile.
* @private
*/
tilesIn: function(bounds) {
tilesIn: function(queryGeometry) {
var result = [];
var ids = this.orderedIDs();

var minX = Infinity;
var minY = Infinity;
var maxX = -Infinity;
var maxY = -Infinity;
var z = queryGeometry[0].zoom;

for (var k = 0; k < queryGeometry.length; k++) {
var p = queryGeometry[k];
minX = Math.min(minX, p.column);
minY = Math.min(minY, p.row);
maxX = Math.max(maxX, p.column);
maxY = Math.max(maxY, p.row);
}

for (var i = 0; i < ids.length; i++) {
var tile = this._tiles[ids[i]];

var tileSpaceBounds = [
tile.positionAt(bounds[0]),
tile.positionAt(bounds[1])
tile.positionAt(new Coordinate(minX, minY, z)),
tile.positionAt(new Coordinate(maxX, maxY, z))
];

if (tileSpaceBounds[0].x < EXTENT && tileSpaceBounds[0].y < EXTENT &&
tileSpaceBounds[1].x >= 0 && tileSpaceBounds[1].y >= 0) {

var tileSpaceQueryGeometry = [];
for (var j = 0; j < queryGeometry.length; j++) {
tileSpaceQueryGeometry.push(tile.positionAt(queryGeometry[j]));
}

result.push({
tile: tile,
minX: tileSpaceBounds[0].x,
maxX: tileSpaceBounds[1].x,
minY: tileSpaceBounds[0].y,
maxY: tileSpaceBounds[1].y
queryGeometry: tileSpaceQueryGeometry,
scale: Math.pow(2, this.transform.zoom - tile.coord.z)
});
}
}
Expand Down
3 changes: 1 addition & 2 deletions js/source/vector_tile_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ VectorTileSource.prototype = util.inherit(Evented, {
getVisibleCoordinates: Source._getVisibleCoordinates,
getTile: Source._getTile,

featuresAt: Source._vectorFeaturesAt,
featuresIn: Source._vectorFeaturesIn,
queryFeatures: Source._queryVectorFeatures,
getTileData: Source._getVectorTileData,

_loadTile: function(tile) {
Expand Down
6 changes: 1 addition & 5 deletions js/source/video_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -165,11 +165,7 @@ VideoSource.prototype = util.inherit(Evented, /** @lends VideoSource.prototype *
return this.tile;
},

featuresAt: function(point, params, callback) {
return callback(null, []);
},

featuresIn: function(bbox, params, callback) {
queryFeatures: function(point, params, callback) {
return callback(null, []);
},

Expand Down
12 changes: 2 additions & 10 deletions js/style/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,7 @@ Style.prototype = util.inherit(Evented, {
}, function(value) { return value !== undefined; });
},

featuresAt: function(coord, params, classes, zoom, bearing, callback) {
this._queryFeatures('featuresAt', coord, params, classes, zoom, bearing, callback);
},

featuresIn: function(bbox, params, classes, zoom, bearing, callback) {
this._queryFeatures('featuresIn', bbox, params, classes, zoom, bearing, callback);
},

_queryFeatures: function(queryType, bboxOrCoords, params, classes, zoom, bearing, callback) {
queryFeatures: function(queryGeometry, params, classes, zoom, bearing, callback) {
var features = [];
var error = null;

Expand All @@ -420,7 +412,7 @@ Style.prototype = util.inherit(Evented, {

util.asyncAll(Object.keys(this.sources), function(id, callback) {
var source = this.sources[id];
source[queryType](bboxOrCoords, params, classes, zoom, bearing, function(err, result) {
source.queryFeatures(queryGeometry, params, classes, zoom, bearing, function(err, result) {
if (result) features = features.concat(result);
if (err) error = err;
callback();
Expand Down
21 changes: 9 additions & 12 deletions js/ui/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ util.extend(Map.prototype, /** @lends Map.prototype */{
featuresAt: function(point, params, callback) {
var location = this.unproject(point).wrap();
var coord = this.transform.locationCoordinate(location);
this.style.featuresAt(coord, params, this._classes, this.transform.zoom, this.transform.angle, callback);
this.style.queryFeatures([coord], params, this._classes, this.transform.zoom, this.transform.angle, callback);
return this;
},

Expand Down Expand Up @@ -357,17 +357,14 @@ util.extend(Map.prototype, /** @lends Map.prototype */{
];
}
bounds = bounds.map(Point.convert.bind(Point));
bounds = [
new Point(
Math.min(bounds[0].x, bounds[1].x),
Math.min(bounds[0].y, bounds[1].y)
),
new Point(
Math.max(bounds[0].x, bounds[1].x),
Math.max(bounds[0].y, bounds[1].y)
)
].map(this.transform.pointCoordinate.bind(this.transform));
this.style.featuresIn(bounds, params, this._classes, this.transform.zoom, this.transform.angle, callback);

var queryGeometry = [
bounds[0],
new Point(bounds[1].x, bounds[0].y),
bounds[1],
new Point(bounds[0].x, bounds[1].y),
bounds[0]].map(this.transform.pointCoordinate.bind(this.transform));
this.style.queryFeatures(queryGeometry, params, this._classes, this.transform.zoom, this.transform.angle, callback);
return this;
},

Expand Down
Loading

0 comments on commit 7c69069

Please sign in to comment.