I'm using a graphing package that can draw lines of color (255,255,255). So basically what I'm doing is (Random.Next(0,255),Random.Next(0,255),Random.Next(0,255)) to generate a color each time a line is added.
This is all well and good, but sometimes, I get colors that look very similar, making it difficult for the user to discern which data corresponds to which line.
Is there a more clever way to generate random and unique col开发者_开发百科ors in the (255,255,255) format?
A better option is to typically generate a random hue, and the convert the hue to an RGB color using an HSL or HSV color (with that hue). By using a random "hue" instead of random color, you'll get much more variation in your colors. You can also randomize the other components (saturation/value, etc), if you need even more variation.
See Wikipedia for details on working in colors using HSV/HSL, including how to convert HSV to RGB.
Check the "color distance"
Assume RGB are XYZ coordinates, do a 3D distance calculation. If a color isn't at least N away from all previously generated colors, try again.
N is a value you decide.
assuming difference in shades is a measure of euclidean distance between coordinates,
you can
1. Remember the previous color generated (a,b,c)
2. make sure that the next one generated (x,y,z) is atleast more than half the max possible distance
i.e sqrt [(a-x)^2 + (b-y)^2 + (c-z)^2] > 1/2 sqrt (3 * 255^2)
3. keep generating random triplets until you get one that satisfies above.. if 1/2 is not good enough, try 2/3 etc.strong text
A very simple solution might be to use more distinct levels by taking ((Random.Next(0, 32) * 8) % 256)
for example. Perhaps a lookup table can be used to skip colors that have been used already.
Concerning uniqueness, have a look here.
For clearer color differences, you might try not to allow all possible values from 0 to 255, but only some steps, e.g. 0-32-64-96-128-160-192-224-255, so you get a bit of contrast.
I wrote a utility function once to do that.
The idea was to linearise the RGB space into a 1D [0, 1] interval. For example doing (R + G*256 + B*256*256)/(256^3*256^2+256).
Then, everytime you need a new colour, you split an interval generated by previous samplings in 2. You pick the first colour as 0.0 in the new space, the second as 1.0, the third as 0.5, then 0.25, then 0.75 and so on. This kinda guarantees that if you generate few colours they have maximum 'separation' (though nor measured in terms of hue). As you generate more and more colours, they tend to get closer to one generated before, but always respecting a max-separation principle.
Once you have your [0, 1] value, you use the inverse function (triplet of functions actually) to go back to RGB.
In the basic implementation you get white and black as the two first colours. If you want something different, once you have generated your 'input' [0, 1] value, you can rotate it, say by a third, inside the same interval.
This works pretty well and it behaves deterministically (no unbounded number of retries).
Is there any reason to randomize colors, rather than outputting them in a fixed sequence? I would suggest that you use an index which gets incremented each color. Use a constant (probably maximum) saturation for your colors, have lightness be frac(indexconst1) and hue be frac(indexconst2). I'm not sure how best to compute const1 and const2; that will depend in some measure on how many points you'll have.
If the goal is to produce relatively uniformly distributed colours rather than just random, a standard technique is to set the Hue for the nth colour to n * 137 degrees. 137 (ish) is the "golden angle" which has some special properties that lead to a relatively well spaced distribution.
If you also want to vary the saturation and level I suspect that you can do something similar by mapping angles to a limited range and instead of using the golden angle use multiples of it to avoid tight association between the three components. E.g, use ((n * 2 * 137) mod 360)/720.0 + 0.5 for saturation and ((n * 4 * 137) mod 360)/720.0 + 0.25 for the level.
精彩评论