Skip to content

Instantly share code, notes, and snippets.

@enjalot
Created January 5, 2014 01:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enjalot/8263288 to your computer and use it in GitHub Desktop.
Save enjalot/8263288 to your computer and use it in GitHub Desktop.
polygon clipping
[
{
"x": 682,
"y": 601,
"value": 10
},
{
"x": 589,
"y": 252,
"value": 10
},
{
"x": 236,
"y": 94.8125,
"value": 10
},
{
"x": 130,
"y": 591.8125,
"value": 10
}
]
{"description":"polygon clipping","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},"clip.json":{"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/RLJOYb0.png"}
/*
Double click to add a point
Drag a point to move it around
Double click a point to remove it
*/
var geomPoints, polygon, clipPoints;
var svg = d3.select("svg").append("g")
var n = tributary.points.length;
function process() {
geomPoints = tributary.points.map(function(d) {
return [d.x, d.y];
});
clipPoints = tributary.clip.map(function(d) {
return [d.x, d.y];
})
//this is where we clip.
//i'm makeing a copy of the clipPoints otherwise they will be modified in place
clipped = d3.geom.polygon(clipPoints).clip(geomPoints.concat([]));
}
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 clipped
var cdpaths = svg.selectAll("path.clipped")
.data([clipped])
cdpaths.enter()
.append("path").classed("clipped", true)
cdpaths.exit().remove();
cdpaths.attr("d", function(d) { return path(d) + "Z" });
//draw polygon
var ppaths = svg.selectAll("path.polygon")
.data([geomPoints])
ppaths.enter()
.append("path").classed("polygon", true);
ppaths.exit().remove();
if(tributary.state.useV) {
ppaths.attr("d", function(d) { return path(d) + "Z";});
} else {
ppaths.remove();
}
//draw clip
var cpaths = svg.selectAll("path.clip")
.data([clipPoints])
cpaths.enter()
.append("path").classed("clip", true)
cpaths.exit().remove();
if(tributary.state.useD) {
cpaths.attr("d", function(d) { return path(d) + "Z" });
} else {
cpaths.remove()
}
//draw points
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);
}
//draw points
var circles = svg.selectAll("circle.clippoint")
.data(tributary.clip)
circles.enter()
.append("circle").classed("clippoint", true)
.call(drag)
.on("dblclick", function(d) {
d3.event.cancelBubble = true;
var ind = tributary.clip.indexOf(d);
tributary.clip.splice(ind, 1);
n = tributary.clip.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();
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));
var cm = tributary.getCodeEditor("clip.json");
cm.setValue(JSON.stringify(tributary.clip, null, 2));
}
tributary.drawUI();
tributary.update = update;
tributary.save = save;
[
{
"x": 113,
"y": 236,
"value": 10
},
{
"x": 55,
"y": 388,
"value": 10
},
{
"x": 241,
"y": 452.8125,
"value": 10
},
{
"x": 220,
"y": 711.8125,
"value": 10
},
{
"x": 416,
"y": 524.8125,
"value": 10
},
{
"x": 550,
"y": 704.8125,
"value": 10
},
{
"x": 727,
"y": 453.8125,
"value": 10
},
{
"x": 450,
"y": 414.8125,
"value": 10
},
{
"x": 706,
"y": 357.8125,
"value": 10
},
{
"x": 688,
"y": 192.8125,
"value": 10
},
{
"x": 468,
"y": 94.8125,
"value": 10
}
]
{
"useD": true,
"useV": true,
"useP": true
}
#display {
background-color: #000000
}
.polygon {
fill: none;
pointer-events: none;
}
.polygon, .voronoiButton {
stroke: #1FADAD;
stroke-width: 2;
}
.clip {
fill: none;
pointer-events: none;
}
.clip, .delaunayButton {
stroke: #D37023;
stroke-width: 2;
}
.clipped {
fill: none;
stroke: #fff;
stroke-width: 8;
}
.point {
fill: #7183DD;
}
.point, .pointButton {
stroke: #7183DD;
stroke-width: 2;
}
.clippoint {
fill: #DD71D9;
stroke: #DD71D0;
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 polygon").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 clip path").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();
d3.selectAll("circle").transition()
.attr("r", 15)
.transition()
.attr("r", 10)
})
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