Skip to content

Instantly share code, notes, and snippets.

@enjalot
Created June 15, 2013 22:16
Show Gist options
  • Save enjalot/5789785 to your computer and use it in GitHub Desktop.
Save enjalot/5789785 to your computer and use it in GitHub Desktop.
voronoi delaunay grid drawing
{"description":"voronoi delaunay grid drawing","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"points.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12},"state.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"ui.js":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"thumbnail":"http://i.imgur.com/9N1xurj.png"}
/*
Double click to add a point
Drag a point to move it around
Double click a point to remove it
*/
var geomPoints, voronoi, delaunay;
var svg = d3.select("svg").append("g")
var n = tributary.points.length;
var spacing = 92;
var nx = 10
var grid = d3.range(77).map(function(d,i) {
var x = (i % nx) * spacing;
var y = Math.floor(i/nx) * spacing
return {
x: x,
y: y
}
})
//comment this out if you want your changes to be saved
tributary.points = grid;
var drag = d3.behavior.drag()
.on("drag", function(d,i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
update();
})
.on("dragend", function() {
//save();
});
d3.select("svg").on("dblclick", function() {
var mouse = d3.mouse(this);
tributary.points.push({x: mouse[0], y: mouse[1], value: 10});
svg.selectAll("circle").remove()
svg.selectAll("path").remove();
update();
//save();
})
var path = d3.svg.line()
function update() {
process();
//draw voronoi
var vpaths = svg.selectAll("path.voronoi")
.data(voronoi)
vpaths.enter()
.append("path").classed("voronoi", true);
vpaths.exit().remove();
if(tributary.state.useV) {
vpaths.attr("d", path);
} else {
vpaths.remove();
//vpaths.attr("d", null);
}
//draw delaunay
var dpaths = svg.selectAll("path.delaunay")
.data(delaunay)
dpaths.enter()
.append("path").classed("delaunay", true)
dpaths.exit().remove();
if(tributary.state.useD) {
dpaths.attr("d", path);
} else {
dpaths.remove()
//dpaths.attr("d", null);
}
var circles = svg.selectAll("circle.point")
.data(tributary.points)
circles.enter()
.append("circle").classed("point", true)
.call(drag)
.on("dblclick", function(d) {
d3.event.cancelBubble = true;
var ind = tributary.points.indexOf(d);
tributary.points.splice(ind, 1);
n = tributary.points.length;
update();
//save();
})
circles.exit().remove();
circles
.attr({
cx: function(d) { return d.x },
cy: function(d) { return d.y },
r: 10
})
.each(function() {
this.parentNode.appendChild(this);
})
if(tributary.state.useP) {
circles.attr("opacity", 1);
} else {
circles.attr("opacity", 0);
}
}
update();
//progressively build out the voronoi/delaunay
//progressively draw the voronoi paths/delaunay
function process() {
geomPoints = tributary.points.map(function(d) {
return [d.x, d.y];
})
voronoi = d3.geom.voronoi(geomPoints);
delaunay = d3.geom.delaunay(geomPoints);
}
function save() {
var cm = tributary.getCodeEditor("points.json");
cm.setValue(JSON.stringify(tributary.points, null, 2));
cm = tributary.getCodeEditor("state.json");
cm.setValue(JSON.stringify(tributary.state, null, 2));
}
tributary.drawUI();
tributary.update = update;
tributary.save = save;
[
{
"x": 0,
"y": 0
},
{
"x": 92,
"y": 0
},
{
"x": 184,
"y": 0
},
{
"x": 276,
"y": 0
},
{
"x": 368,
"y": 0
},
{
"x": 460,
"y": 0
},
{
"x": 552,
"y": 0
},
{
"x": 644,
"y": 0
},
{
"x": 736,
"y": 0
},
{
"x": 828,
"y": 0
},
{
"x": 0,
"y": 92
},
{
"x": 92,
"y": 92
},
{
"x": 184,
"y": 92
},
{
"x": 276,
"y": 92
},
{
"x": 368,
"y": 92
},
{
"x": 460,
"y": 92
},
{
"x": 552,
"y": 92
},
{
"x": 644,
"y": 92
},
{
"x": 736,
"y": 92
},
{
"x": 828,
"y": 92
},
{
"x": 0,
"y": 184
},
{
"x": 92,
"y": 184
},
{
"x": 184,
"y": 184
},
{
"x": 276,
"y": 184
},
{
"x": 368,
"y": 184
},
{
"x": 460,
"y": 184
},
{
"x": 552,
"y": 184
},
{
"x": 644,
"y": 184
},
{
"x": 736,
"y": 184
},
{
"x": 828,
"y": 184
},
{
"x": 0,
"y": 276
},
{
"x": 92,
"y": 276
},
{
"x": 184,
"y": 276
},
{
"x": 276,
"y": 276
},
{
"x": 368,
"y": 276
},
{
"x": 460,
"y": 276
},
{
"x": 552,
"y": 276
},
{
"x": 644,
"y": 276
},
{
"x": 736,
"y": 276
},
{
"x": 828,
"y": 276
},
{
"x": 0,
"y": 368
},
{
"x": 92,
"y": 368
},
{
"x": 184,
"y": 368
},
{
"x": 276,
"y": 368
},
{
"x": 368,
"y": 368
},
{
"x": 460,
"y": 368
},
{
"x": 552,
"y": 368
},
{
"x": 644,
"y": 368
},
{
"x": 736,
"y": 368
},
{
"x": 828,
"y": 368
},
{
"x": 0,
"y": 460
},
{
"x": 92,
"y": 460
},
{
"x": 184,
"y": 460
},
{
"x": 276,
"y": 460
},
{
"x": 368,
"y": 460
},
{
"x": 460,
"y": 460
},
{
"x": 554,
"y": 457
},
{
"x": 644,
"y": 460
},
{
"x": 736,
"y": 460
},
{
"x": 828,
"y": 460
},
{
"x": 0,
"y": 552
},
{
"x": 92,
"y": 552
},
{
"x": 184,
"y": 552
},
{
"x": 276,
"y": 552
},
{
"x": 368,
"y": 552
},
{
"x": 460,
"y": 552
},
{
"x": 552,
"y": 552
},
{
"x": 644,
"y": 552
},
{
"x": 736,
"y": 552
},
{
"x": 828,
"y": 552
},
{
"x": 0,
"y": 644
},
{
"x": 92,
"y": 644
},
{
"x": 184,
"y": 644
},
{
"x": 276,
"y": 644
},
{
"x": 368,
"y": 644
},
{
"x": 460,
"y": 644
},
{
"x": 552,
"y": 644
},
{
"x": 724,
"y": 642.8125,
"value": 10
}
]
{
"useD": true,
"useV": false,
"useP": true
}
#display {
background-color: #000000
}
.voronoi {
fill: none;
pointer-events: none;
}
.voronoi, .voronoiButton {
stroke: #1FADAD;
stroke-width: 3;
}
.delaunay {
fill: none;
pointer-events: none;
}
.delaunay, .delaunayButton {
stroke: #4ABD8F;
stroke-width: 3;
}
.point {
fill: #7183DD;
}
.point, .pointButton {
stroke: #7183DD;
stroke-width: 3;
}
.saveButton {
stroke: #ffffff;
stroke-width: 3;
}
text {
font-size: 14px;
fill: #ffffff;
pointer-events: none;
}
.selected {
stroke: #ffffff;
stroke-width: 1;
}
tributary.drawUI = function() {
var svg = d3.select("svg");
var bw = 114;
var bh = 20;
svg.append("rect")
.classed("voronoiButton", true)
.attr({
x: tributary.sw - bw - 10,
y: tributary.sh - 3*bh - 20,
width: bw,
height: bh
}).on("click", function(d,i) {
tributary.state.useV = !tributary.state.useV;
d3.select(".voronoiText").classed("selected", tributary.state.useV);
d3.event.cancelBubble = true;
tributary.update();
})
svg.append("text")
.text("show voronoi").classed("voronoiText", true)
.attr({
x: tributary.sw - bw + 2,
y: tributary.sh - 3*bh -5
});
svg.append("rect")
.classed("delaunayButton", true)
.attr({
x: tributary.sw - bw - 10,
y: tributary.sh - 2*bh - 15,
width: bw,
height: bh
}).on("click", function(d,i) {
tributary.state.useD = !tributary.state.useD;
d3.select(".delaunayText").classed("selected", tributary.state.useD)
d3.event.cancelBubble = true;
tributary.update();
})
svg.append("text")
.text("show delaunay").classed("delaunayText", true)
.attr({
x: tributary.sw - bw - 1,
y: tributary.sh - 2*bh -1
});
svg.append("rect")
.classed("pointButton", true)
.attr({
x: tributary.sw - bw - 10,
y: tributary.sh - bh - 10,
width: bw,
height: bh
}).on("click", function(d,i) {
tributary.state.useP = !tributary.state.useP;
d3.select(".pointsText").classed("selected", tributary.state.useP)
d3.event.cancelBubble = true;
tributary.update();
})
svg.append("text")
.text("show points").classed("pointsText", true)
.attr({
x: tributary.sw - bw + 9,
y: tributary.sh - bh + 4
});
svg.append("rect")
.classed("saveButton", true)
.attr({
x: 10,
y: tributary.sh - bh - 10,
width: bw,
height: bh
}).on("click", function(d,i) {
d3.event.cancelBubble = true;
tributary.save();
})
svg.append("text")
.classed("write", true)
.text("write to json")
.attr({
x: 27,
y: tributary.sh - bh + 4
});
d3.select(".pointsText").classed("selected", tributary.state.useP)
d3.select(".voronoiText").classed("selected", tributary.state.useV)
d3.select(".delaunayText").classed("selected", tributary.state.useD)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment