Permalink
Browse files

Non-contiguous cartogram example.

Also includes new d3.geom.polygon.centroid method. Props to Zachary Johnson for
the inspiration!
  • Loading branch information...
1 parent 6d8a51b commit 3ecb7534ef3150dc465cf1024ce0114d4da52e12 @mbostock mbostock committed Feb 23, 2011
Showing with 333 additions and 33 deletions.
  1. +63 −2 d3.geo.js
  2. +11 −10 d3.geo.min.js
  3. +19 −0 d3.geom.js
  4. +15 −15 d3.geom.min.js
  5. +1 −1 d3.js
  6. +1 −1 d3.min.js
  7. +54 −1 data/us-states.json
  8. +86 −0 examples/cartogram/cartogram.html
  9. +1 −1 src/core/core.js
  10. +63 −2 src/geo/path.js
  11. +19 −0 src/geom/polygon.js
View
@@ -323,13 +323,70 @@ d3.geo.path = function() {
};
function polygonArea(coordinates) {
- var sum = area(coordinates[0]),
+ var sum = area(coordinates[0]), // exterior ring
i = 0, // coordinates.index
n = coordinates.length;
- while (++i < n) sum -= area(coordinates[i]);
+ while (++i < n) sum -= area(coordinates[i]); // holes
return sum;
}
+ function polygonCentroid(coordinates) {
+ var polygon = d3.geom.polygon(coordinates[0].map(projection)), // exterior ring
+ centroid = polygon.centroid(1),
+ x = centroid[0],
+ y = centroid[1],
+ z = Math.abs(polygon.area()),
+ i = 0, // coordinates index
+ n = coordinates.length;
+ while (++i < n) {
+ polygon = d3.geom.polygon(coordinates[i].map(projection)); // holes
+ centroid = polygon.centroid(1);
+ x -= centroid[0];
+ y -= centroid[1];
+ z -= Math.abs(polygon.area());
+ }
+ return [x, y, 6 * z]; // weighted centroid
+ }
+
+ var centroidTypes = {
+
+ // TODO FeatureCollection
+ // TODO Point
+ // TODO MultiPoint
+ // TODO LineString
+ // TODO MultiLineString
+ // TODO GeometryCollection
+
+ Feature: function(f) {
+ return d3_geo_pathType(centroidTypes, f.geometry);
+ },
+
+ Polygon: function(o) {
+ var centroid = polygonCentroid(o.coordinates);
+ return [centroid[0] / centroid[2], centroid[1] / centroid[2]];
+ },
+
+ MultiPolygon: function(o) {
+ var area = 0,
+ coordinates = o.coordinates,
+ centroid,
+ x = 0,
+ y = 0,
+ z = 0,
+ i = -1, // coordinates index
+ n = coordinates.length;
+ while (++i < n) {
+ centroid = polygonCentroid(coordinates[i]);
+ x += centroid[0];
+ y += centroid[1];
+ z += centroid[2];
+ }
+ return [x / z, y / z];
+ }
+
+ };
+
+
function area(coordinates) {
return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
}
@@ -343,6 +400,10 @@ d3.geo.path = function() {
return d3_geo_pathType(areaTypes, d);
};
+ path.centroid = function(d) {
+ return d3_geo_pathType(centroidTypes, d);
+ };
+
path.pointRadius = function(x) {
if (typeof x == "function") pointRadius = x;
else {
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -188,6 +188,25 @@ d3.geom.polygon = function(coordinates) {
return (b - a) * .5;
};
+ coordinates.centroid = function(k) {
+ var i = -1,
+ n = coordinates.length - 1,
+ x = 0,
+ y = 0,
+ a,
+ b,
+ c;
+ if (!arguments.length) k = 1 / (6 * coordinates.area());
+ while (++i < n) {
+ a = coordinates[i];
+ b = coordinates[i + 1];
+ c = a[0] * b[1] - b[0] * a[1];
+ x += (a[0] + b[0]) * c;
+ y += (a[1] + b[1]) * c;
+ }
+ return [x * k, y * k];
+ };
+
// The Sutherland-Hodgman clipping algorithm.
coordinates.clip = function(subject) {
var input,
Oops, something went wrong.

0 comments on commit 3ecb753

Please sign in to comment.