Skip to content

Commit f58b5db

Browse files
committed
Fix path.centroid for polygons with holes.
The centroid was not being subtracted for interior polygon rings (holes), hence it was appearing too far to the right. The winding order is ignored.
1 parent 2eeb205 commit f58b5db

4 files changed

Lines changed: 43 additions & 7 deletions

File tree

d3.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6056,11 +6056,11 @@
60566056
return z;
60576057
}
60586058
function ringCentroid(centroid, ring, i) {
6059-
var polygon = d3.geom.polygon(ring.map(projection)), area = polygon.area(), point = polygon.centroid(area < 0 ? (area *= -1,
6060-
1) : -1);
6059+
var polygon = d3.geom.polygon(ring.map(projection)), area = polygon.area();
6060+
var point = polygon.centroid(area < 0 ^ i > 0 ? (area *= -1, 1) : -1);
60616061
centroid[0] += point[0];
60626062
centroid[1] += point[1];
6063-
return area * (i > 0 ? -6 : 6);
6063+
return area * 6;
60646064
}
60656065
path.bounds = function(object) {
60666066
return (bounds || (bounds = d3_geo_bounds(projection)))(object);

d3.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/geo/path.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,11 @@ d3.geo.path = function() {
101101

102102
function ringCentroid(centroid, ring, i) {
103103
var polygon = d3.geom.polygon(ring.map(projection)),
104-
area = polygon.area(),
105-
point = polygon.centroid(area < 0 ? (area *= -1, 1) : -1);
104+
area = polygon.area();
105+
var point = polygon.centroid(area < 0 ^ i > 0 ? (area *= -1, 1) : -1);
106106
centroid[0] += point[0];
107107
centroid[1] += point[1];
108-
return area * (i > 0 ? -6 : 6);
108+
return area * 6;
109109
}
110110

111111
path.bounds = function(object) {

test/geo/path-test.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,42 @@ suite.addBatch({
161161
},
162162
"two rings, one zero area": function(centroid) {
163163
assert.deepEqual(centroid({type: "Polygon", coordinates: [[[100, 0], [101, 0], [101, 1], [100, 1], [100, 0]], [[100.1, 0], [100.2, 0], [100.3, 0], [100.1, 0]]]}), [982.5, 247.5]);
164+
},
165+
"anticlockwise exterior and interior": function(centroid) {
166+
assert.inDelta(centroid({
167+
type: "Polygon",
168+
coordinates: [
169+
[[-2, -2], [2, -2], [2, 2], [-2, 2], [-2, -2]],
170+
[[ 0, -1], [1, -1], [1, 1], [ 0, 1], [ 0, -1]]
171+
]
172+
}), [479.642857, 250], 1e-6);
173+
},
174+
"clockwise exterior and interior": function(centroid) {
175+
assert.inDelta(centroid({
176+
type: "Polygon",
177+
coordinates: [
178+
[[-2, -2], [2, -2], [2, 2], [-2, 2], [-2, -2]].reverse(),
179+
[[ 0, -1], [1, -1], [1, 1], [ 0, 1], [ 0, -1]].reverse()
180+
]
181+
}), [479.642857, 250], 1e-6);
182+
},
183+
"anticlockwise exterior, clockwise interior": function(centroid) {
184+
assert.inDelta(centroid({
185+
type: "Polygon",
186+
coordinates: [
187+
[[-2, -2], [2, -2], [2, 2], [-2, 2], [-2, -2]],
188+
[[ 0, -1], [1, -1], [1, 1], [ 0, 1], [ 0, -1]].reverse()
189+
]
190+
}), [479.642857, 250], 1e-6);
191+
},
192+
"clockwise exterior, anticlockwise interior": function(centroid) {
193+
assert.inDelta(centroid({
194+
type: "Polygon",
195+
coordinates: [
196+
[[-2, -2], [2, -2], [2, 2], [-2, 2], [-2, -2]].reverse(),
197+
[[ 0, -1], [1, -1], [1, 1], [ 0, 1], [ 0, -1]]
198+
]
199+
}), [479.642857, 250], 1e-6);
164200
}
165201
},
166202
"MultiPolygon": {

0 commit comments

Comments
 (0)