d3-contour icon indicating copy to clipboard operation
d3-contour copied to clipboard

Some contour polygon is reverse.

Open stoneshell opened this issue 5 years ago • 5 comments

I'm using d3-contour to draw beautiful chart recently. Most of the time it's fine. But in this case: https://observablehq.com/@choukou/untitled In hundreds of polygons, one is special 截屏2020-11-13 下午12 46 50 It's counterclockwise. That cause the whole screen green. Would you give me some help?

stoneshell avatar Nov 13 '20 06:11 stoneshell

It seems that you are computing the contours on the spherical coordinates, then project the resulting polygons. But this creates issues with the holes. If you changed the order of operations (first project, then compute the contours), it would work. I'm sending you a suggestion.

See also https://observablehq.com/@d3/cloud-contours and https://observablehq.com/@fil/netcdf

Fil avatar Nov 13 '20 11:11 Fil

It seems that you are computing the contours on the spherical coordinates, then project the resulting polygons. But this creates issues with the holes. If you changed the order of operations (first project, then compute the contours), it would work. I'm sending you a suggestion.

See also https://observablehq.com/@d3/cloud-contours and https://observablehq.com/@fil/netcdf

Thanks very much for your speedy and professional advice, I'm reading your code now, may get back to you if any further help needed.

Wish you a nice weekend ahead.

stoneshell avatar Nov 13 '20 13:11 stoneshell

In the data source(contours.json), masked area(land) is set -1e20. When I change -1e20 to -999, the chart becomes perfect. I don't know why this value affect the contour polygons.

stoneshell avatar Nov 16 '20 06:11 stoneshell

Ah, true:

contours = d3.contours()
                  .size([data.width, data.height])
                  .thresholds(thresholds)(varData.values.map(d => Math.max(-1e13, d)))

is correct, but with 1e-14 it's broken:

contours = d3.contours()
                  .size([data.width, data.height])
                  .thresholds(thresholds)(varData.values.map(d => Math.max(-1e14, d)))

Fil avatar Nov 16 '20 13:11 Fil

I suspect that this is related to numerical instability and I think it’s unlikely that we would implement a fully robust algorithm. Maybe we can at least guarantee consistency with d3.polygonArea though.

mbostock avatar Jun 28 '22 14:06 mbostock