2011-03-29 27 views
5

Mi aplicación contiene un gráfico de líneas que puede mostrar 20 o más conjuntos de datos a la vez, pero normalmente mostrará menos de 5. Me gustaría que cada conjunto de datos tenga un color único.¿Cómo puedo generar colores contrastantes?

Actualmente estoy haciendo esto:

setHsl(i * 255.0/session->getNumDataSets(), 255, 128); 

Funciona, pero tiene la desventaja de que dos conjuntos de datos consecutivos tendrán colores muy similares. Me gustaría que cada color generado sea lo más contrastante posible contra todos los colores anteriores generados.

¿Cuál es una mejor manera de generar los colores?

Aquí es mi segundo intento:

double pos = 0; 
if (wheel.size() == 0) 
{ 
    wheel.append(0.0); 
    wheel.append(1.0); 
} 
else 
{ 
    double gap = 0; 
    double hi = 0; 
    double lo = 0; 

    for (int i = 0; i < wheel.size() - 1; i++) 
    { 
     double g = wheel[i + 1] - wheel[i]; 
     if (g > gap) 
     { 
      gap = g; 
      lo = wheel[i]; 
      hi = wheel[i + 1]; 
     } 
    } 

    pos = (hi - lo)/2.0 + lo; 

    wheel.append(pos); 
    qSort(wheel); 
} 

QColor c; 
c.setHsl(pos * 255.0, 255, 128); 
return c.toRgb(); 

Mi idea es que el primer color, es la posición 0 en el círculo cromático. Luego, para cada color siguiente, recorro la rueda de colores, buscando el espacio más grande entre los colores, y una vez que lo encuentro, inserto un nuevo color en ese espacio. Parece que funciona mejor, pero aún no es perfecto, ya que una vez que las brechas se vuelven pequeñas, los colores consecutivos vuelven a ser similares.

+0

máximo del contrato se hace generalmente con los colores puros (Luminosidad = 120, Saturación = 240), y de hecho escoger la tonalidad como que ya lo hacen. – Wrikken

+0

Ya no quiere elegir el tono porque los colores adyacentes son bastante similares. – Reinderien

+0

Acabo de ver una publicación de blog en reddit o noticias de hackers que resuelve este problema muy bien, pero ahora no puedo encontrarlo. –

Respuesta

3

Se podría hacer algo como:

int n = session->getNumDataSets(); 
setHsl((((i%3) * n/3)+(i/3)) * 255.0/n, 255, 128); 

tendría que volver a verificar mis matemáticas, pero básicamente se gira a través de terceras partes del espectro.

+0

No funciona del todo, da los mismos 3 colores en pedidos alternos, pero creo que entiendo su intención. –

+0

Pruébalo ahora, uno de esos mods debería haber sido una división. – Reinderien

+0

Se ve bastante bien, gracias. Y mucho más simple que mi intento # 2. –

5

Sé que está solicitando una forma de generar computacionalmente los colores para un gráfico, pero es posible que desee considerar diseñar una paleta personalizada y buscar colores en una tabla preestablecida.

Esto tiene la ventaja de que puede crear una selección de colores que son más fáciles de distinguir para los usuarios daltónicos. Puede usar una herramienta como VisCheck para ver cómo aparecería su gráfico a los usuarios de daltónicos.

Si puede tener más de 20 conjuntos de datos, me imagino que puede ser muy difícil distinguirlos solo por el color, pero los colores se pueden reutilizar en combinación con otro diferenciador, como líneas punteadas.

+0

+1 para considerar la accesibilidad para usuarios daltónicos. –

2

No utilice HSL. Sus fallas son la razón por la cual los colores que "se ven diferentes" numéricamente en el espacio HSL (o simplemente como malo, HSV) terminan pareciendo similares en su ojo. En su lugar, use YUV (también conocido como YCbCr). La idea básica de YUV, si usted no está familiarizado, es hacer una transformación lineal en coordenadas donde el primer eje es la intensidad perceptiva , algo así como:

Y = 0.3*R + 0.6*G + 0.1*B 

(coeficientes generalmente afinado más son utilizado, pero estos son simples que le dan una idea aproximada de los pesos)

El segundo y el tercer eje se eligen simplemente como dos vectores en el plano ortogonal al eje Y, a menudo aproximadamente el "rojo" y " "direcciones azules".

Tenga en cuenta que debido a que los colores están limitados a cubo en coordenadas RGB, una vez que elige un valor Y, esto limita los posibles valores U y V que permanecen dentro del cuadro. En Y = max, U y V deben ser cero. Así que simplemente elija algún valor Y de brillo intermedio donde tenga mucho juego en U y V, y luego elija N vectores espaciados uniformemente en coordenadas polares en el plano UV.

2

Uso la siguiente función en Java para crear colores equidistantes para diferentes conjuntos de datos en gráficos generados por Java. Su corto y dulce:

/** 
* This function splits the red-green-blue colour wheel into n equally spaced divisions 
* and returns the colour from a particular division. 
* 
* @param index The index of the colour to return, the range is 0 - (count-1) 
* @param count The number of divisions to split the HSV colour wheel into 
* @return A java.awt.Color object containing the colour. 
* @author HughesR 
*/ 
public static Color getSpacedOutColour(int index, int count) { 
    final float saturation = 0.95f; // Saturation 
    final float brightness = 0.8f; // Brightness 
    float hue = (float)index/(float)count; 
    return Color.getHSBColor(hue, saturation, brightness); 
} 
+0

Este es el enfoque que uso también. Muy conveniente. Q/A relacionado [aquí] (http://stackoverflow.com/a/3403970/276052) relacionado. – aioobe

Cuestiones relacionadas