d3 / d3-shape

Graphical primitives for visualization, such as lines and areas.
https://d3js.org/d3-shape
ISC License
2.47k stars 305 forks source link

pie() / arc() rendering bug for specific combination of radii #119

Closed danburzo closed 5 years ago

danburzo commented 6 years ago

While toying with the parameters for pie and arc, I have found a glitch for this configuration:

{
  "innerRadius": 23,
  "outerRadius": 128,
  "cornerRadius": 14,
  "padAngle": 0.06,
  "values": [6, 6]
}

Which outputs this shape:

screen shot 2018-03-07 at 17 59 40

Not sure if it warrants further investigation, but I wanted to let you know.

Seems to be a kind of floating point error, since it happens only on specific combinations of values and radii.

Other combinations can cause different glitches:

{
  "innerRadius": 20,
  "outerRadius": 115,
  "cornerRadius": 13,
  "padAngle": 0.06,
  "values": [ 6, 6 ]
}

Outputs the shape below:

screen shot 2018-03-07 at 18 30 19
mbostock commented 6 years ago

Confirmed. https://beta.observablehq.com/d/efdc14bd2b7292c4

Most likely related to this test:

https://github.com/d3/d3-shape/blob/master/src/arc.js#L152

mbostock commented 6 years ago

Just noticed you already linked to an Observable notebook to reproduce this issue. Well played, sir.

danburzo commented 6 years ago

I wouldn't dare show up without an Observable notebook to reproduce this issue! :)

Would you say that it's benign that the pie() generator produces π as the angle for most identical value pairs, but "almost π" for [6, 6]? (I still have to read more carefully through the code to have any useful points to make).

mbostock commented 6 years ago

It’s not exactly π because the padAngle is non-zero.

danburzo commented 6 years ago

Looking through the code for the pie() generator, it seems that in the case of N identical values, the padAngle gets eliminated and the angle span for each slice is (2 * π / N), which for N = 2 gives us π — in most cases, except that for [6, 6] and particular padAngle values it results in not-quite-π.

(Not sure if it's relevant but it seems counter-intuitive for the padAngle to evaporate in these specific cases? Edit: I realized later that padAngle is included within each slice's angle span)