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

findInCircle(x, y, radius, filter) #32

Closed
wants to merge 1 commit into from
Closed
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
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ Returns the total number of data in the quadtree.

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.

<a name="quadtree_findInCircle" href="#quadtree_findInCircle">#</a> <i>quadtree</i>.<b>findInCircle</b>(<i>x</i>, <i>y</i>[, <i>radius</i>][, <i>filter</i>])
[<>](https://github.com/d3/d3-quadtree/blob/master/src/findInCircle.js "Source")

Returns all the data within the given search *radius* of the position ⟨*x*,*y*⟩ that satisfy the filter *filter*, if specified. If *radius* is not specified, it defaults to infinity. If there is no acceptable datum within the search area, returns an empty array.

<a name="quadtree_visit" href="#quadtree_visit">#</a> <i>quadtree</i>.<b>visit</b>(<i>callback</i>)
[<>](https://github.com/d3/d3-quadtree/blob/master/src/visit.js "Source")

Expand Down
22 changes: 22 additions & 0 deletions src/findInCircle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export default function(x, y, radius, filter) {
const quadtree = this,
result = [],
radius2 = radius * radius,
accept = filter
? d => filter(d) && result.push(d)
: d => result.push(d);

quadtree.visit(function(node, x1, y1, x2, y2) {
if (node.length) {
return x1 >= x + radius || y1 >= y + radius || x2 < x - radius || y2 < y - radius;
}

const dx = +quadtree._x.call(null, node.data) - x,
dy = +quadtree._y.call(null, node.data) - y;
if (dx * dx + dy * dy < radius2) {
do { accept(node.data); } while (node = node.next);
}
});

return result;
}
2 changes: 2 additions & 0 deletions src/quadtree.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import tree_cover from "./cover.js";
import tree_data from "./data.js";
import tree_extent from "./extent.js";
import tree_find from "./find.js";
import tree_findInCircle from "./findInCircle.js";
import tree_remove, {removeAll as tree_removeAll} from "./remove.js";
import tree_root from "./root.js";
import tree_size from "./size.js";
Expand Down Expand Up @@ -63,6 +64,7 @@ treeProto.cover = tree_cover;
treeProto.data = tree_data;
treeProto.extent = tree_extent;
treeProto.find = tree_find;
treeProto.findInCircle = tree_findInCircle;
treeProto.remove = tree_remove;
treeProto.removeAll = tree_removeAll;
treeProto.root = tree_root;
Expand Down
21 changes: 21 additions & 0 deletions test/findInCircle-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
var tape = require("tape"),
d3_quadtree = require("../");

tape("quadtree.findInCircle(x, y, radius) returns all the points within the search radius of the given [x, y]", function(test) {
const points = [[0, 0], [100, 0], [0, 100], [100, 100]];
const q = d3_quadtree.quadtree(points);
test.deepEqual(q.findInCircle(20, 20, Infinity), points);
test.deepEqual(q.findInCircle(20, 20, 20 * Math.SQRT2 + 1e-6), [points[0]]);
test.deepEqual(q.findInCircle(20, 20, 20 * Math.SQRT2 - 1e-6), []);
test.deepEqual(q.findInCircle(50, 0, 51), [points[0], points[1]]);
test.end();
});

tape("quadtree.findInCircle(x, y, radius, filter) returns all the points within the search radius of the given [x, y] and passing filter", function(test) {
const points = [[0, 0, "a"], [0, 0, "b"], [100, 0, "a"], [0, 100, "b"], [100, 100, "a"]];
const q = d3_quadtree.quadtree(points);
const filter = d => d[2] === "a";
test.deepEqual(q.findInCircle(20, 20, Infinity, filter), points.filter(filter));
test.deepEqual(q.findInCircle(0, 0, 2, filter), [points[0]]);
test.end();
});