Colour choosing algorithm (C#)

Associate
Joined
14 Apr 2003
Posts
1,101
Hi,

Im working on a project that requires me to display database records on a map. You can group the records by different fields and I have a different colour for each type. Currently I just choose the colours randomly from the Colors class. However, this chooses identical colours sometimes and it also chooses poor colours (such as white, cream etc) what I want is some sort of maths algorigthm that will generate a range of colours from red to blue (say) then i can take colours at set intervals to give a nice spread.

I know it must be possible but maths isnt my strong point!

any ideas?

Thanks,

Matt
 
Since every colour (within reason, obviously) can be expressed as a mixture of red, green and blue, so you can generate a random colour with (pseudo-code):

Code:
int red = randomNumber(0, 255)
int green = randomNumber(0, 255)
int blue = randomNumber(0, 255)

Obviously you can constrain that, so for colours that lean to the green side of the spectrum:

Code:
int red = randomNumber(0, 150)
int green = randomNumber(50, 255)
int blue = randomNumber(0, 150)

Which will almost always result in more green that either red or blue.

I'm 99.99% sure .NET lets you create colours with RGB values, so you can just do this, surely?
 
Rob's suggestion looks good to me, although it would be much easier, for your purposes, to choose colours from the HSL (hue, saturation, luminosity) colourspace than RGB, as it allows you to control the brightness and hue separately. Unfortunately, the .NET framework has very limited support for HSL colour manipulation (and I don't know the details of what support it does have), so you'll probably have to find a third party library out there to do it for you (or write your own).

Once you have the individual RGB values for the colour you want, you can get a Color object from them as follows:
Code:
int red = ...
int green = ...
int blue = ...

Color someColour = Color.FromArgb(red, green, blue);
 
yes, I have now got a system set up that chooses colours at random, but it still has the same problems as before, choosing white-cream or generally pale colours as well as selecting colours that are almost identical which doesnt help differentiate between the fields.
 
robmiller said:
Since every colour (within reason, obviously) can be expressed as a mixture of red, green and blue, so you can generate a random colour with (pseudo-code):

Code:
int red = randomNumber(0, 255)
int green = randomNumber(0, 255)
int blue = randomNumber(0, 255)

Obviously you can constrain that, so for colours that lean to the green side of the spectrum:

Code:
int red = randomNumber(0, 150)
int green = randomNumber(50, 255)
int blue = randomNumber(0, 150)

Which will almost always result in more green that either red or blue.

I'm 99.99% sure .NET lets you create colours with RGB values, so you can just do this, surely?


That doesn't solve the problem though, because he doesn't want random colours (including white/cream etc) and he doesn't want colours to ever be the same!

The big question is whats the maximum number of colours you will ever need? If there is no limit then its obviously impossible not to get duplicate colours. If it is limited to below 20 you should probably just hand pick the colours you want, solving the problem.

Alternatively there are a load of clever things you can do. You could just do something like starting at red and adding a 'bit more' blue each time, but this is not ideal since if you only use 2 colours you end up with red and something close to red, when you would probably want too very different colours.

One idea I can think of is as follows (I think this is pretty clever if I may say so myself :)):
1. Predefine some initial colours to use (eg: 5 colours like red/green/blue/green/yellow). Add these colours to an arraylist (call is InitialColours).
2.a. When you need more colours go through InitialColours and for each pair of colours generate a new colour by 'mixing' them. eg: Get the red component for the two colours and average it to get the new colour's red component. Do the same for blue and green.
Call this new set of colours SecondColours.

Now whenever you need another load of colours just get the last lot you generated and generate all the mixtures. You can add in extra checks to make sure you never get duplicates.

To start with the colours are very different, and the 'usual' colours you would expect. The second lot of colours will be common mixtures like orange (red+yellow) etc etc. You get gradually more obscure colours as you use more and more.
 
Well, getting it to compare a randomly generated colour to each of the ones you're already using could be a bit tricky, but I suppose you could have some sort of threshold for the RGB values. For example, if all of the RGB values are within, say, 20 of another colour's RGB values, then don't use that colour (and you could include the map colour as well).
 
Hi,

Thanks for the idea, ideally no more than say 10 colours would be needed, but seeing as life is unfair the maximum number of colours needed could be as much as 350+ (highly unlikely someone would produce a query that returned so many results though!). I think ill try that algo you suggested, see what happens!

Matt
 
Inquisitor was spot-on.
A very simple hue-to-RGB conversion involves using trig functions :

red = cos(angle) * 0.5 + 0.5
green = cos(angle+((2/3)*pi)) * 0.5 + 0.5;
blue = cos(angle+((4/3)*pi)) * 0.5 + 0.5;

will give you a spectrum for values of 'angle' from 0 to 2*pi.

so if you wanted four distinct and hue-opposed colours, you'd divide 2*pi by 5 and use the first 4 values
 
matja said:
Inquisitor was spot-on.
A very simple hue-to-RGB conversion involves using trig functions :

red = cos(angle) * 0.5 + 0.5
green = cos(angle+((2/3)*pi)) * 0.5 + 0.5;
blue = cos(angle+((4/3)*pi)) * 0.5 + 0.5;

will give you a spectrum for values of 'angle' from 0 to 2*pi.

so if you wanted four distinct and hue-opposed colours, you'd divide 2*pi by 5 and use the first 4 values

Hi, sorry to bring this up again, but i was busy implementing this algorithm and its returning colours taht are identical? Ive got some code from my program:

Code:
double angle = (2 * Math.PI) / (_Colors.Length + 1);   
            double step = angle;
            for (int i = 0; i < _Colors.Length; i++)
            {
                double red = (Math.Cos(angle) * 0.5 + 0.5);
                double green = Math.Cos(angle + ((2 / 3) * Math.PI)) * 0.5 + 0.5;
                double blue = Math.Cos(angle + ((4 / 3) * Math.PI)) * 0.5 + 0.5;
                Color c = Color.FromArgb((int)(red*255), (int)(green*255), (int)(blue*255));
                _Colors[i] = c;
                angle = angle + step;
            }

now if i try to generate 5 colours it comes up with the following numbers for the angle, red, green and blue:

Code:
Angle: 1.0471975511966
Red: 0.75
Green: 0.75
Blue: 0.25
Angle: 2.0943951023932
Red: 0.25
Green: 0.25
Blue: 0.75
Angle: 3.14159265358979
Red: 0
Green: 0
Blue: 1
Angle: 4.18879020478639
Red: 0.25
Green: 0.25
Blue: 0.75
Angle: 5.23598775598299
Red: 0.75
Green: 0.75
Blue: 0.25

I dont know if im using the formula correctly, from what i understood I took the number of colours i required and diveded 2*pi by that number, then i stuck it in the formula and then added the initial angle by itself and repeated the process? To calculate the colour i just multiplied those numbers by 255. if ive got this completely wrong please tell me!!

thanks,

matt

edit: note the first two colours are fine i get a blue and a mustard colour, but after that they get really similar and then eventually the same.
 
Back
Top Bottom