Skip to content

Instantly share code, notes, and snippets.

@lsquaredleland
Last active November 8, 2019 09:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lsquaredleland/794a924bc3cf2ed1c401 to your computer and use it in GitHub Desktop.
Save lsquaredleland/794a924bc3cf2ed1c401 to your computer and use it in GitHub Desktop.
Overlaying D3: hull, voronoi, voronoi.triangle, and quadtree

#D3.geom

Wondered what it would be like to lay all the different geometries on top of each other...

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Geom</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
</head>
<body>
<div id="chartArea">
</div>
<script src="main.js"></script>
</body>
</html>
generate();
function generate(){
var height = window.innerHeight;
var width = window.innerWidth;
var svg = d3.select("#chartArea").append("svg")
.attr("width", width)
.attr("height", height)
coords = []
for(var i = 0; i < 50; i++){
var cy = Math.random()*(height-100) + 50
var cx = Math.random()*(width-100) + 50
coords.push([cx, cy])
}
//Hull
var hull = svg.append("path")
.attr("class", "hull");
hull.data([d3.geom.hull(coords)])
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.attr("opacity", .3)
console.log('area', d3.geom.polygon(d3.geom.hull(coords)).area())
//Voronoi -> how to make a weighted version of this depending on the node in the center?
var voronoi = d3.geom.voronoi()
.clipExtent([[0, 0], [width, height]]);
//voronoi.triangles seems very similar to the outside of a hull?
var path = svg.append("g").selectAll("path");
path = path.data(voronoi.triangles(coords), polygon);
path.enter().append("path")
.attr("class", function(d, i) { return "q" + (i % 9) + "-9" + " voronoiTriangles"; })
.attr("fill", 'none')
.attr("stroke", "maroon")
.attr("d", polygon)
.on('mouseover', function() {
d3.selectAll('.voronoiTriangles').style('stroke-width', 3)
})
.on('mouseout', function() {
d3.selectAll('.voronoiTriangles').style('stroke-width', 1)
})
function polygon(d) {
return "M" + d.join("L") + "Z";
}
//Voronoi
path = path.data(voronoi(coords), polygon);
path.enter().append("path")
.attr("class", function(d, i) { return "q" + (i % 9) + "-9" + " voronoi"; })
.attr("fill", 'none')
.attr("stroke", "#3CA1A5")
.attr("d", polygon)
.on('mouseover', function() {
d3.selectAll('.voronoi').style('stroke-width', 3)
})
.on('mouseout', function() {
d3.selectAll('.voronoi').style('stroke-width', 1)
})
//QuadTrees
var quadtree = d3.geom.quadtree()
.extent([[0, 0], [width, height]]);
var rect = svg.selectAll(".node")
.data(nodes(quadtree(coords)))
.enter().append("rect")
.attr("class", "node quadTrees")
.attr("fill", 'none')
.attr("stroke", "#7D9B47")
.attr("x", function(d) { return d.x1; })
.attr("y", function(d) { return d.y1; })
.attr("width", function(d) { return d.x2 - d.x1; })
.attr("height", function(d) { return d.y2 - d.y1; })
.on('mouseover', function() {
d3.selectAll('.quadTrees').style('stroke-width', 3)
})
.on('mouseout', function() {
d3.selectAll('.quadTrees').style('stroke-width', 1)
})
function nodes(quadtree) {
var nodes = [];
quadtree.depth = 0; // root
quadtree.visit(function(node, x1, y1, x2, y2) {
node.x1 = x1;
node.y1 = y1;
node.x2 = x2;
node.y2 = y2;
nodes.push(node);
for (var i=0; i<4; i++) {
if (node.nodes[i]) node.nodes[i].depth = node.depth+1;
}
});
return nodes;
}
//Circles
svg.selectAll('circle')
.data(coords).enter().append('circle')
.classed('circle', true)
.attr('cx', function(d) { return d[0]; })
.attr('cy', function(d) { return d[1]; })
.attr('r', 5)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment