diff --git a/README.md b/README.md index 2e6c5ab..a1ead46 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ The returned geometry objects are typically passed to [d3.geoPath](https://githu # contours.contour(values, threshold) [<>](https://github.com/d3/d3-contour/blob/master/src/contours.js "Source") -Computes a single contour, returning a [GeoJSON](http://geojson.org/geojson-spec.html) [MultiPolygon](http://geojson.org/geojson-spec.html#multipolygon) [geometry object](http://geojson.org/geojson-spec.html#geometry-objects) representing the area where the input values are greater than or equal to the given [*threshold* value](#contours_thresholds); the threshold value for each geometry object is exposed as geometry.value. +Computes a single contour, returning a [GeoJSON](http://geojson.org/geojson-spec.html) [MultiPolygon](http://geojson.org/geojson-spec.html#multipolygon) [geometry object](http://geojson.org/geojson-spec.html#geometry-objects) representing the area where the input values are greater than or equal to the given [*threshold* value](#contours_thresholds); the threshold value for each geometry object is exposed as geometry.value, and its area exposed as geometry.area. The input *values* must be an array of length n×m where [n, m] is the contour generator’s [size](#contours_size); furthermore, each values[i + jn] must represent the value at the position ⟨i, j⟩. See [*contours*](#_contours) for an example. diff --git a/src/contours.js b/src/contours.js index 1bed5b1..8a98d50 100644 --- a/src/contours.js +++ b/src/contours.js @@ -52,12 +52,15 @@ export default function() { // Based on https://github.com/mbostock/shapefile/blob/v0.6.2/shp/polygon.js function contour(values, value) { var polygons = [], - holes = []; + holes = [], + a = 0; isorings(values, value, function(ring) { smooth(ring, values, value); - if (area(ring) > 0) polygons.push([ring]); + var ar = area(ring); + if (ar > 0) polygons.push([ring]); else holes.push(ring); + a += ar / 2; }); holes.forEach(function(hole) { @@ -72,6 +75,7 @@ export default function() { return { type: "MultiPolygon", value: value, + area: a, coordinates: polygons }; } diff --git a/test/contours-test.js b/test/contours-test.js index 7d997fb..1bd75c2 100644 --- a/test/contours-test.js +++ b/test/contours-test.js @@ -18,6 +18,7 @@ tape("contours(values) returns the expected result for an empty polygon", functi { "type": "MultiPolygon", "value": 0.5, + "area": 0, "coordinates": [] } ]); @@ -41,6 +42,7 @@ tape("contours(values) returns the expected result for a simple polygon", functi { "type": "MultiPolygon", "value": 0.5, + "area": 14.5, "coordinates": [ [ [[6, 7.5], [6, 6.5], [6, 5.5], [6, 4.5], [6, 3.5], [5.5, 3], [4.5, 3], @@ -69,6 +71,7 @@ tape("contours(values).contour(value) returns the expected result for a simple p ], 0.5), { "type": "MultiPolygon", "value": 0.5, + "area": 14.5, "coordinates": [ [ [[6, 7.5], [6, 6.5], [6, 5.5], [6, 4.5], [6, 3.5], [5.5, 3], [4.5, 3], @@ -97,6 +100,7 @@ tape("contours.smooth(false)(values) returns the expected result for a simple po { "type": "MultiPolygon", "value": 0.5, + "area": 14.5, "coordinates": [ [ [[6, 7.5], [6, 6.5], [6, 5.5], [6, 4.5], [6, 3.5], [5.5, 3], [4.5, 3], @@ -126,6 +130,7 @@ tape("contours(values) returns the expected result for a polygon with a hole", f { "type": "MultiPolygon", "value": 0.5, + "area": 12, "coordinates": [ [ [[6, 7.5], [6, 6.5], [6, 5.5], [6, 4.5], [6, 3.5], [5.5, 3], [4.5, 3], @@ -157,6 +162,7 @@ tape("contours(values) returns the expected result for a multipolygon", function { "type": "MultiPolygon", "value": 0.5, + "area": 14, "coordinates": [ [ [[5, 7.5], [5, 6.5], [5, 5.5], [5, 4.5], [5, 3.5], [4.5, 3], [3.5, 3], @@ -190,6 +196,7 @@ tape("contours(values) returns the expected result for a multipolygon with holes { "type": "MultiPolygon", "value": 0.5, + "area": 16, "coordinates": [ [ [[4, 5.5], [4, 4.5], [4, 3.5], [3.5, 3], [2.5, 3], [1.5, 3], [1, 3.5],