Question

Here we have an interesting real-world algorithm requirement involving colors.

  1. N Pretty Colors: In order to draw a beautiful chart (i.e: pie chart) we need to pick a random set of N colors that are "different enough" and look good together. This could be accomplished by fixing brightness and saturation and stepping through hue in steps of 360/N.
  2. Stable Color Assignment: given Pie_1 with sectors labelled ('A','B','C') and Pie_2 with sectors labelled ('B','C','D'), it would be nice if the color of sectors B and C are the same on both Pie_1 and Pie_2. This will help prevent confusion if sectors are removed or added to the chart over time. The label is the only stable thing.
  3. Allows Hard-coded colors: The algorithm should allow hardcoded label->color relationships as an input but will compute colors (according to rules 1 and 2) for the rest of the labels.

I think this algorithm, even if it looks quite ad-hoc, will be useful in more than one situation.

Any ideas?

Update: Eric is right that is impossible to guarantee the stability of colors for each label as new labels appear and disappear. But I'm happy if it is "stable enough", i.e. color changes are minimized.

I was thinking of something like:

  1. Every label gets a random hue value using hash(label)%360
  2. In order to guarantee that the generated hues are different enough, we divide the hue circle in a fixed amount of steps (i.e: 2*N) and try to 'round' the previous hue values to the new differentiated ones.
  3. In the case of different labels going to the same rounded hue value, we break the tie somehow and move the point somewhere else.

But this leaves aside the issue of hard-coded colors.

Was it helpful?

Solution

You can pick a set of random colors that look good together using a color wheel algorithm. Here's a related SO question with implementation guides, or google for many others.

You can use something like a hash of your labels as a starting point on the color wheel to ensure stability. This also satisfies 3. if you have an override mechanism to state that a specific label hash value should correspond to a specific starting point on the color wheel.

EDIT:

The color wheel lets you pick one master starting point (e.g. (hash(A) % 360) and ensure that two other colors (B, C) are "nice" when used together with A. B and C are determined by A. If you can later have a pie chart (B, Y, Z), B would be set as (hash(B) % 360) and would be different than it was in the (A, B, C) case.

If you can arbitrarily mix labels on pie charts, NO algorithm can ensure they will always look good together. Here's a simple proof:

Let A, B, C be selected so that they look good together.

Now let A appear with an arbitrary color Z

You can certainly pick some color for Z such that A and Z will clash.

You can only guarantee that a certain set of colors will look good together, and that picking the same set will reproduce the same colors.

You can use the hash of e.g. the first label as the starting point on the wheel (hash(A)) or you can combine the hashes (hash(A) + 31*hash(B) + 31*31*hash(C)). Multiplying by 31 (a prime number) is something from the Java world that helps ensure a better mathematical distribution when combining multiple hashes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top