diff --git a/README.md b/README.md index 05692ff..a76923f 100644 --- a/README.md +++ b/README.md @@ -121,10 +121,10 @@ Returns an array of all data in the quadtree. Returns the total number of data in the quadtree. -# quadtree.find(x, y[, radius]) +# quadtree.find(x, y[, radius][, filter]) [<>](https://github.com/d3/d3-quadtree/blob/master/src/find.js "Source") -Returns the datum closest to the position ⟨*x*,*y*⟩ with the given search *radius*. If *radius* is not specified, it defaults to infinity. If there is no datum within the search area, returns undefined. +Returns the datum closest to the position ⟨*x*,*y*⟩ with the given search *radius* that satisfies the *filter*. If *radius* is not specified, it defaults to infinity. If *filter* is not specified, all data are considered. If there is no acceptable datum within the search area, returns undefined. # quadtree.visit(callback) [<>](https://github.com/d3/d3-quadtree/blob/master/src/visit.js "Source") diff --git a/src/find.js b/src/find.js index e9db6c4..94c412e 100644 --- a/src/find.js +++ b/src/find.js @@ -1,6 +1,6 @@ import Quad from "./quad.js"; -export default function(x, y, radius) { +export default function(x, y, radius, filter) { var data, x0 = this._x0, y0 = this._y0, @@ -58,10 +58,16 @@ export default function(x, y, radius) { dy = y - +this._y.call(null, node.data), d2 = dx * dx + dy * dy; if (d2 < radius) { - var d = Math.sqrt(radius = d2); - x0 = x - d, y0 = y - d; - x3 = x + d, y3 = y + d; - data = node.data; + var f, d; + do { + if (!filter || filter(node.data)) f = node; + } while (!f && (node = node.next)); + if (f) { + d = Math.sqrt(radius = d2); + x0 = x - d, y0 = y - d; + x3 = x + d, y3 = y + d; + data = f.data; + } } } } diff --git a/test/find-test.js b/test/find-test.js index 82fc217..977a79f 100644 --- a/test/find-test.js +++ b/test/find-test.js @@ -32,3 +32,12 @@ tape("quadtree.find(x, y, null) treats the given radius as Infinity", function(t test.deepEqual(q.find(20, 20, undefined), [0, 0]); test.end(); }); + +tape("quadtree.find(x, y, radius, filter) considers only filtered points", function(test) { + var q = d3_quadtree.quadtree([[0, 0, "red"], [100, 0, "blue"], [100, 0, "blue"], [0, 100, "red"], [100, 100, "red"], [100, 100, "blue"]]); + test.deepEqual(q.find(20, 0, null, d => d[2] == "red"), [0, 0, "red"]); + test.deepEqual(q.find(20, 0, null, d => d[2] == "blue"), [100, 0, "blue"]); + test.deepEqual(q.find(20, 0, 50, d => d[2] == "blue"), undefined); + test.deepEqual(q.find(20, 0, null, d => d[2] == "green"), undefined); + test.end(); +});