function nearestNeighbor(neighbors) { var xValue = function(d) { return d[0]; }, yValue = function(d) { return d[1]; }, voronoi = d3.geom.voronoi().x(xValue).y(yValue), polygons = voronoi(neighbors); function nearest(point) { return polygons.filter(function(polygon) { return polygonContainsPoint(polygon, normalize(point)); })[0].point; } function normalize(point) { return [xValue(point), yValue(point)] } function polygonContainsPoint(points, test) { var result = false; for (i = 0, j = points.length - 1; i < points.length; j = i++) { if ((points[i][1] > test[1]) != (points[j][1] > test[1]) && (test[0] < (points[j][0] - points[i][0]) * (test[1] - points[i][1]) / (points[j][1]-points[i][1]) + points[i][0])) { result = !result; } } return result; } nearest.x = function(_) { if (!arguments.length) return xValue; xValue = _; voronoi = voronoi.x(xValue); polygons = voronoi(neighbors); return nearest; }; nearest.y = function(_) { if (!arguments.length) return yValue; yValue = _; voronoi = voronoi.y(yValue); polygons = voronoi(neighbors); return nearest; }; nearest.clipExtent = function(_) { if(!arguments.length) return voronoi.clipExtent(); voronoi = voronoi.clipExtent(_); polygons = voronoi(neighbors); return nearest; } return nearest; }