#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) | |
} |