Skip to content

Commit

Permalink
Fix polygon.centroid for open polygons.
Browse files Browse the repository at this point in the history
The implementation assumed closed polygons, but it should work on either. This
is a partial fix for #443.
  • Loading branch information
mbostock committed Jan 29, 2012
1 parent f67e895 commit 85ad3c1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 25 deletions.
8 changes: 4 additions & 4 deletions d3.geom.js
Expand Up @@ -192,16 +192,16 @@ d3.geom.polygon = function(coordinates) {

coordinates.centroid = function(k) {
var i = -1,
n = coordinates.length - 1,
n = coordinates.length,
x = 0,
y = 0,
a,
b,
b = coordinates[n - 1],
c;
if (!arguments.length) k = -1 / (6 * coordinates.area());
while (++i < n) {
a = coordinates[i];
b = coordinates[i + 1];
a = b;
b = coordinates[i];
c = a[0] * b[1] - b[0] * a[1];
x += (a[0] + b[0]) * c;
y += (a[1] + b[1]) * c;
Expand Down
2 changes: 1 addition & 1 deletion d3.geom.min.js

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

8 changes: 4 additions & 4 deletions src/geom/polygon.js
Expand Up @@ -15,16 +15,16 @@ d3.geom.polygon = function(coordinates) {

coordinates.centroid = function(k) {
var i = -1,
n = coordinates.length - 1,
n = coordinates.length,
x = 0,
y = 0,
a,
b,
b = coordinates[n - 1],
c;
if (!arguments.length) k = -1 / (6 * coordinates.area());
while (++i < n) {
a = coordinates[i];
b = coordinates[i + 1];
a = b;
b = coordinates[i];
c = a[0] * b[1] - b[0] * a[1];
x += (a[0] + b[0]) * c;
y += (a[1] + b[1]) * c;
Expand Down
58 changes: 42 additions & 16 deletions test/geom/polygon-test.js
Expand Up @@ -8,49 +8,75 @@ var vows = require("vows"),
var suite = vows.describe("d3.geom.polygon");

suite.addBatch({
"counterclockwise polygon (last point equal to start point)": {
"closed counterclockwise unit square": {
topic: function() {
return d3.geom.polygon([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]);
},
"area": function(polygon) {
"has area 1": function(polygon) {
assert.equal(polygon.area(), 1);
},
"centroid": function(polygon) {
"has centroid ⟨.5,.5⟩": function(polygon) {
assert.deepEqual(polygon.centroid(), [.5, .5]);
}
},
"counterclockwise polygon (implicitly ending at start point)": {
"closed clockwise unit square": {
topic: function() {
return d3.geom.polygon([[0, 0], [0, 1], [1, 1], [1, 0]]);
return d3.geom.polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]);
},
"area": function(polygon) {
assert.equal(polygon.area(), 1);
"has area 1": function(polygon) {
assert.equal(polygon.area(), -1);
},
"centroid": function(polygon) {
"has centroid ⟨.5,.5⟩": function(polygon) {
assert.deepEqual(polygon.centroid(), [.5, .5]);
}
},
"clockwise polygon (last point equal to start point)": {
"closed clockwise triangle": {
topic: function() {
return d3.geom.polygon([[0, 0], [1, 0], [1, 1], [0, 1], [0, 0]]);
return d3.geom.polygon([[1, 1], [3, 2], [2, 3], [1, 1]]);
},
"area": function(polygon) {
assert.equal(polygon.area(), -1);
"has area 1.5": function(polygon) {
assert.equal(polygon.area(), -1.5);
},
"has centroid ⟨2,2⟩": function(polygon) {
var centroid = polygon.centroid();
assert.inDelta(centroid[0], 2, 1e-6);
assert.inDelta(centroid[1], 2, 1e-6);
}
},
"open counterclockwise unit square": {
topic: function() {
return d3.geom.polygon([[0, 0], [0, 1], [1, 1], [1, 0]]);
},
"centroid": function(polygon) {
"has area 1": function(polygon) {
assert.equal(polygon.area(), 1);
},
"has centroid ⟨.5,.5⟩": function(polygon) {
assert.deepEqual(polygon.centroid(), [.5, .5]);
}
},
"clockwise polygon (implicitly ending at start point)": {
"open clockwise unit square": {
topic: function() {
return d3.geom.polygon([[0, 0], [1, 0], [1, 1], [0, 1]]);
},
"area": function(polygon) {
"has area 1": function(polygon) {
assert.equal(polygon.area(), -1);
},
"centroid": function(polygon) {
"has centroid ⟨.5,.5⟩": function(polygon) {
assert.deepEqual(polygon.centroid(), [.5, .5]);
}
},
"open clockwise triangle": {
topic: function() {
return d3.geom.polygon([[1, 1], [3, 2], [2, 3]]);
},
"has area 1.5": function(polygon) {
assert.equal(polygon.area(), -1.5);
},
"has centroid ⟨2,2⟩": function(polygon) {
var centroid = polygon.centroid();
assert.inDelta(centroid[0], 2, 1e-6);
assert.inDelta(centroid[1], 2, 1e-6);
}
}
});

Expand Down

0 comments on commit 85ad3c1

Please sign in to comment.