Built with blockbuilder.org
forked from anonymous's block: Finding adjacent voronoi cells
| license: mit |
Built with blockbuilder.org
forked from anonymous's block: Finding adjacent voronoi cells
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <style> | |
| .links { | |
| stroke: #000; | |
| stroke-opacity: 0.2; | |
| } | |
| .polygons { | |
| fill: none; | |
| stroke: #000; | |
| } | |
| .sites { | |
| fill: #000; | |
| stroke: #fff; | |
| } | |
| </style> | |
| <svg width="960" height="500"></svg> | |
| <script src="https://d3js.org/d3.v4.min.js"></script> | |
| <script> | |
| var svg = d3.select("svg").on("touchmove mousemove", moved), | |
| width = +svg.attr("width"), | |
| height = +svg.attr("height"); | |
| var sites = d3.range(30) | |
| .map(function(d) { return [Math.random() * width, Math.random() * height]; }); | |
| var voronoi = d3.voronoi() | |
| .extent([[-1, -1], [width + 1, height + 1]]); | |
| var polygon = svg.append("g") | |
| .attr("class", "polygons") | |
| .selectAll("path") | |
| .data(voronoi.polygons(sites)) | |
| .enter().append("path") | |
| .call(redrawPolygon); | |
| var link = svg.append("g") | |
| .attr("class", "links") | |
| .selectAll("line") | |
| .data(voronoi.links(sites)) | |
| .enter().append("line") | |
| .call(redrawLink); | |
| var site = svg.append("g") | |
| .attr("class", "sites") | |
| .selectAll("circle") | |
| .data(sites) | |
| .enter().append("circle") | |
| .attr("r", 2.5) | |
| .call(redrawSite); | |
| function moved() { | |
| sites[0] = d3.mouse(this); | |
| redraw(); | |
| } | |
| function redraw() { | |
| //Aim is to find all cells which are adjacent to the current one | |
| //Then we can select them | |
| var diagram = voronoi(sites); | |
| var links = diagram.links() | |
| var polygons = diagram.polygons() | |
| polygons.forEach(function(p) { | |
| p.adjacent = false | |
| }) | |
| var this_site = sites[0] //array[2] | |
| var this_polygon = polygons[0] //set of coordinates and data attribute | |
| var counter = 1 | |
| links.forEach(function(l) { | |
| if (l.source == this_site || l.target == this_site) { | |
| //get corresponding polygons | |
| polygons.forEach(function(p) { | |
| if (p.data == l.target || p.data == l.source) { | |
| p["adjacent"] = true | |
| } | |
| }) | |
| } | |
| }) | |
| //this site corresponds to polygon[0] | |
| // | |
| polygon = polygon.data(polygons).call(redrawPolygon); | |
| link = link.data(links), link.exit().remove(); | |
| link = link.enter().append("line").merge(link).call(redrawLink); | |
| site = site.data(sites).call(redrawSite); | |
| } | |
| function redrawPolygon(polygon) { | |
| polygon | |
| .attr("d", function(d) { return d ? "M" + d.join("L") + "Z" : null; }) | |
| .style("fill", function(d){ | |
| if (d.adjacent == 1) { | |
| return "#F1F" | |
| } else { | |
| return "#FF1" | |
| } | |
| }) | |
| } | |
| function redrawLink(link) { | |
| link | |
| .attr("x1", function(d) { return d.source[0]; }) | |
| .attr("y1", function(d) { return d.source[1]; }) | |
| .attr("x2", function(d) { return d.target[0]; }) | |
| .attr("y2", function(d) { return d.target[1]; }); | |
| } | |
| function redrawSite(site) { | |
| site | |
| .attr("cx", function(d) { return d[0]; }) | |
| .attr("cy", function(d) { return d[1]; }); | |
| } | |
| </script> |