Skip to content

Commit

Permalink
Minor beautification.
Browse files Browse the repository at this point in the history
  • Loading branch information
mbostock committed Nov 23, 2010
1 parent bbe029f commit 46b5d54
Show file tree
Hide file tree
Showing 7 changed files with 74 additions and 89 deletions.
47 changes: 22 additions & 25 deletions d3.geom.js
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
d3.geom = {};
/**
* Computes the 2D convex hull of a set of points using Graham's
* scanning algorithm. The algorithm has been implemented as described
* in Cormen, Leiserson, and Rivest's Introduction to Algorithms.
*
* The running time of this algorithm is O(n log n), where n is
* the number of input points.
* Computes the 2D convex hull of a set of points using Graham's scanning
* algorithm. The algorithm has been implemented as described in Cormen,
* Leiserson, and Rivest's Introduction to Algorithms. The running time of
* this algorithm is O(n log n), where n is the number of input points.
*
* @param vertices [[x1, y1], [x2, y2], …]
* @returns polygon [[x1, y1], [x2, y2], …],
*/
d3.geom.hull = function(vertices) {

// helper method to detect a non-left turn about 3 points
var isNonLeft = function(i0, i1, i2, i3, v) {
var x, y, l1, l2, l4, l5, l6, a1, a2;
y = v[i2][1]-v[i1][1]; x = v[i2][0]-v[i1][0]; l1 = x*x + y*y;
y = v[i3][1]-v[i2][1]; x = v[i3][0]-v[i2][0]; l2 = x*x + y*y;
y = v[i3][1]-v[i0][1]; x = v[i3][0]-v[i0][0]; l4 = x*x + y*y;
y = v[i1][1]-v[i0][1]; x = v[i1][0]-v[i0][0]; l5 = x*x + y*y;
y = v[i2][1]-v[i0][1]; x = v[i2][0]-v[i0][0]; l6 = x*x + y*y;
a1 = Math.acos((l2+l6-l4) / (2*Math.sqrt(l2*l6)));
a2 = Math.acos((l6+l1-l5) / (2*Math.sqrt(l6*l1)));
return ((Math.PI-a1) - a2) <= 0.0;
}

if (vertices.length < 3) return [];

var len = vertices.length,
Expand All @@ -38,7 +22,7 @@ d3.geom.hull = function(vertices) {
if (vertices[i][1] < vertices[h][1]) {
h = i;
} else if (vertices[i][1] == vertices[h][1]) {
h = (vertices[i][0] < vertices[h][0] ? i : h);
h = (vertices[i][0] < vertices[h][0] ? i : h);
}
}

Expand All @@ -47,9 +31,9 @@ d3.geom.hull = function(vertices) {
if (i == h) continue;
y1 = vertices[i][1] - vertices[h][1];
x1 = vertices[i][0] - vertices[h][0];
points.push({angle:Math.atan2(y1,x1), index:i});
points.push({angle: Math.atan2(y1, x1), index: i});
}
points.sort(function(a,b) { return a.angle-b.angle; });
points.sort(function(a, b) { return a.angle - b.angle; });

// toss out duplicate angles
a = points[0].angle;
Expand Down Expand Up @@ -87,11 +71,11 @@ d3.geom.hull = function(vertices) {
}
}
sp = stack.length;

// do graham's scan
for (; j<plen; ++j) {
if (points[j].index == -1) continue; // skip tossed out points
while (isNonLeft(h, stack[sp-2], stack[sp-1], points[j].index, vertices)) {
while (d3_geom_hullIsNonLeft(h, stack[sp-2], stack[sp-1], points[j].index, vertices)) {
--sp;
}
stack[sp++] = points[j].index;
Expand All @@ -104,6 +88,19 @@ d3.geom.hull = function(vertices) {
}
return poly;
}

// helper method to detect a non-left turn about 3 points
function d3_geom_hullIsNonLeft(i0, i1, i2, i3, v) {
var x, y, l1, l2, l4, l5, l6, a1, a2;
y = v[i2][1] - v[i1][1]; x = v[i2][0] - v[i1][0]; l1 = x * x + y * y;
y = v[i3][1] - v[i2][1]; x = v[i3][0] - v[i2][0]; l2 = x * x + y * y;
y = v[i3][1] - v[i0][1]; x = v[i3][0] - v[i0][0]; l4 = x * x + y * y;
y = v[i1][1] - v[i0][1]; x = v[i1][0] - v[i0][0]; l5 = x * x + y * y;
y = v[i2][1] - v[i0][1]; x = v[i2][0] - v[i0][0]; l6 = x * x + y * y;
a1 = Math.acos((l2 + l6 - l4) / (2 * Math.sqrt(l2 * l6)));
a2 = Math.acos((l6 + l1 - l5) / (2 * Math.sqrt(l6 * l1)));
return (Math.PI - a1 - a2) < 0;
}
// Note: requires coordinates to be counterclockwise and convex!
d3.geom.polygon = function(coordinates) {

Expand Down
30 changes: 15 additions & 15 deletions d3.geom.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion d3.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
d3 = {version: "0.19.1"}; // semver
d3 = {version: "0.20.0"}; // semver
if (!Date.now) Date.now = function() {
return +new Date();
};
Expand Down
2 changes: 1 addition & 1 deletion d3.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 12 additions & 21 deletions examples/hull/hull.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,19 @@
<script type="text/javascript" src="../../d3.geom.min.js"></script>
<style type="text/css">

@import url("../../lib/colorbrewer/colorbrewer.css");

svg {
border: solid 1px #666;
border: solid 1px #aaa;
background: #eee;
}

path {
fill: yellow;
fill: lightsteelblue;
stroke: #000;
stroke-width: .5px;
}

circle {
fill: #ccc;
fill: #fff;
stroke: #000;
pointer-events: none;
}

</style>
Expand All @@ -34,35 +31,29 @@
h = 500;

var vertices = d3.range(15).map(function(d) {
return [w/4 + Math.random() * w/2,
h/4 + Math.random() * h/2];
return [
w / 4 + Math.random() * w / 2,
h / 4 + Math.random() * h / 2
];
});
vertices[0] = [w/2,h/2];

var svg = d3.select("body")
.append("svg:svg")
.attr("width", w)
.attr("height", h)
.attr("class", "PiYG")
.attr("pointer-events", "all")
.on("mousemove", move)
.on("click", click);

// background rect to catch events
svg.append("svg:rect")
.attr("width", w)
.attr("height", h)
.attr("fill", "white");

update();

function update() {
svg.selectAll("path")
.data([d3.geom.hull(vertices)])
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.enter("svg:path")
.attr("class", "q3-9")
.attr("d", function(d) { return "M" + d.join("L") + "Z"; });

.enter("svg:path")
.attr("d", function(d) { return "M" + d.join("L") + "Z"; });

svg.selectAll("circle")
.data(vertices.slice(1))
.enter("svg:circle")
Expand Down
2 changes: 1 addition & 1 deletion src/core/core.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
d3 = {version: "0.19.1"}; // semver
d3 = {version: "0.20.0"}; // semver
Loading

0 comments on commit 46b5d54

Please sign in to comment.