Robert Monfera
twitter bl.ocks linkedin github stackoverflow email

Text fitting with constructive plane geometry

Partition charts usually show a hierarchical part-to-whole relationship on a planar surface with no overlap among parts of a hierarchy layer. Pie and sunburst charts, while controversial, have properties like clearly conveying the intent: subdivision of a whole. They work best if there are relatively few major parts. Due to the planar nature, it's a good option to put text labels as close to the sector geometry as possible, for example, overlaying the geometry itself. This technical example goes beyond reasonable effort to fit text as the last 4 directly labeled slices have very small font:

The subdivisions of a sunburst chart are ring sectors (annular sectors):

Source: wikipedia

The pie slices are circular sectors, which are just a special case of ring sectors, the inner radius being zero. A pie chart with a single slice, or a sunburst with a single sector in each layer are also just special cases.

The chart iterates over the sectors and constructs the sectors, highlighting the current one in white (because that part is not covered by any of the circline constraints):

Ring sectors are a planar shape bounded by two circular arcs and two line segments. But we can approximate a ring sector as a planar geometry construction: an AND or NOR set operation involving 4 circlines, where a line is an infinite-radius circle, and a half-plane is an infinite-radius disk.

The reason for modeling sectors via circlines and constructive plane geometry, instead of as circle arcs and line segments is to be economical with code size spent on what ought to be a very small aspect of a chart. Instead of circle/circle, line/line, circle/line intersections, we just solve the circle/circle intersections:

It yields freedom for font size maximization (readability, accessibility), text orientation and geometry orientation:

The solution has other configurable constraints, such as:

  • Maximum number of text rows
  • Minimum and maximum fill label font size
  • Angular threshold for switching to a linked label instead of fill label
  • Threshold for stepping away from the preference for horizontal text, when radial text orientation yields a larger font
  • The solution addresses other things invisible to the user. For example, a large slice count would lead to burnout if the slices have a constant width gap among them, eg. 1px:

    Instead, the gap between two slices is modeled as a pentagon: the gap tapers down below a specific distance from the center, reaching zero width in the center:

    Besides the tapered shape, there's a constraint on the area distortion (and by consequence, burnout) introduced by the gap: it can't be more than a certain percentage of the area, or the arc of the full slice. So a thin slice will have a thin border, so the border can't eat up most or all space.

    It's usually best to avoid showing more than a handful of slices. It's still nice to support scalability for the use cases where lots of slices are OK.

    In addition to ring sectors, the rectangular boxes of treemaps, mosaic/Marimekko and Cartesian charts such as bars can be modeled via circlines. Here is a mosaic plot and a treemap with the same technique:

    Similar to pie/sunburst, the distortion introduced by the borders and the group headings are capped as a proportion, so the relative distortion is small even in case of small partitions, avoiding lost parts.

    elastic-charts example

    First pull request for partition charts