Build as you go quadtrees! Click anywhere on the svg
to add a point to the quadtree. Rectangles showing partitions automatically draw around it to show which node the point is stored in. Tree is also responsive and can resize to desired viewport width and height.
Last active
June 11, 2019 03:42
-
-
Save meowteusz/dd34949868808647aad759a1f52548d5 to your computer and use it in GitHub Desktop.
D3 Clickable Quadtrees
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>Clickable Quadtree</title> | |
<style> | |
cirlce { | |
fill: #4682b4; | |
fill-opacity: 0.4; | |
} | |
.node { | |
fill: none; | |
stroke: #ccc; | |
shape-rendering: crispEdges; | |
} | |
</style> | |
</head> | |
<body> | |
<svg width="960" height="500"></svg> | |
</body> | |
<script src="https://d3js.org/d3.v4.js"></script> | |
<script> | |
let svg = d3.select("svg"), | |
width = 960, | |
height = 500, | |
radius = 4; | |
let dataset = d3.range(2).map( () => [Math.floor(Math.random() * 1024), Math.floor(Math.random() * 1024)]); | |
let quadtree = d3.quadtree() | |
.extent([[0, 0], [width, height]]) | |
.addAll(dataset); | |
svg.selectAll(".node") | |
.data(nodes(quadtree)) | |
.enter() | |
.append("rect") | |
.transition() | |
.duration(1000) | |
.attr("class", "node") | |
.attr("x", d => (d.x0/1024)*width) | |
.attr("y", d => (d.y0/1024)*height) | |
.attr("width", d => ((width/1024)*d.y1) - ((width/1024)*d.y0)) | |
.attr("height", d => ((height/1024)*d.x1) - ((height/1024)*d.x0)); | |
let xScale = d3.scaleLinear() | |
.domain([0, 1024]) | |
.range([0, width]), | |
yScale = d3.scaleLinear() | |
.domain([0, 1024]) | |
.range([0, height]); | |
svg.selectAll("circle") | |
.data(dataset) | |
.enter() | |
.append("circle") | |
.attr("cx", d => xScale(d[0])) | |
.attr("cy", d => yScale(d[1])) | |
.attr("r", radius) | |
.style("fill", "#4682b4"); | |
svg.on("click", function () { | |
let coords = d3.mouse(this); | |
let newData = [ | |
Math.floor(xScale.invert(coords[0])), | |
Math.floor(yScale.invert(coords[1])) | |
]; | |
dataset.push(newData); | |
quadtree.add(newData); | |
svg.selectAll("circle") | |
.data(dataset) | |
.enter() | |
.append("circle") | |
.attr("cx", d => xScale(d[0])) | |
.attr("cy", d => yScale(d[1])) | |
.attr("r", radius) | |
.style("fill", "#4682b4"); | |
svg.selectAll(".node").remove(); | |
svg.selectAll(".node") | |
.data(nodes(quadtree)) | |
.enter() | |
.append("rect") | |
.attr("class", "node") | |
.attr("x", d => (d.x0 / 1024) * width) | |
.attr("y", d => (d.y0 / 1024) * height) | |
.attr("width", d => ((width / 1024) * d.y1) - ((width / 1024) * d.y0)) | |
.attr("height", d => ((height / 1024) * d.x1) - ((height / 1024) * d.x0)); | |
}); | |
function nodes(quadtree) { | |
let nodes = []; | |
quadtree.visit(function(node, x0, y0, x1, y1) { | |
node.x0 = x0, | |
node.y0 = y0, | |
node.x1 = x1, | |
node.y1 = y1; | |
nodes.push(node); | |
}); | |
return nodes; | |
} | |
</script> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment