2011-03-18 14 views

Respuesta

2

Divida la superficie en una cuadrícula de celdas y cuente los puntos dentro de cada celda.

Dado el recuento de puntos, calcular un color para cada celda

6

Aquí hay un método simple que generará un color basado en la posición relativa de un valor entre min y max. Los valores más cercanos a min serán más ecológicos, mientras que los valores más cercanos a max serán más rojos.
Para usar este método, genere su lista de valores y calcule los valores mínimo y máximo. Si está construyendo una grilla, puede manejar el evento RowDataBound o algo similar y llamar al método HeatMap desde allí. Obtenga una referencia a la celda y establezca el color de fondo en el color devuelto por el método HeatMap.

public Color HeatMap(decimal value, decimal min, decimal max) 
{ 
    decimal val = (value - min)/(max-min); 
    return new Color 
    { 
     A = 255, 
     R = Convert.ToByte(255 * val), 
     G = Convert.ToByte(255 * (1-val)), 
     B = 0 
    }; 
} 
+0

Curtis, lo que hace tu dosis de solución? El código que publiqué es esencialmente escaso pero se ejecuta (en WPF). – Sam

+2

Su código no se compila en una aplicación Windows Form. Los campos ARGB están listos solo.Color es un Struct y ARGB solo tienen métodos get. –

2

Esta es una solución para el código de Sam.

public Color HeatMapColor(decimal value, decimal min, decimal max) 
    { 
     decimal val = (value - min)/(max - min); 
     int r = Convert.ToByte(255 * val); 
     int g = Convert.ToByte(255 * (1 - val)); 
     int b = 0; 

     return Color.FromArgb(255,r,g,b);          
    } 
+0

¿Y exactamente cómo es esto diferente de [la respuesta de Sam] (http://stackoverflow.com/a/11570954/947171)? –

+2

En Windows Forms, el código de Sam no se ejecuta. Los campos ARGB están listos solo. –

4

Sobre la base de las respuestas que ya están aquí, este método permite especificar el Colors que desea utilizar como máximo y colores min.

private Color HeatMapColor(double value, double min, double max) 
{ 
    Color firstColour = Color.RoyalBlue; 
    Color secondColour = Color.LightSkyBlue; 

    // Example: Take the RGB 
    //135-206-250 // Light Sky Blue 
    // 65-105-225 // Royal Blue 
    // 70-101-25 // Delta 

    int rOffset = Math.Max(firstColour.R, secondColour.R); 
    int gOffset = Math.Max(firstColour.G, secondColour.G); 
    int bOffset = Math.Max(firstColour.B, secondColour.B); 

    int deltaR = Math.Abs(firstColour.R - secondColour.R); 
    int deltaG = Math.Abs(firstColour.G - secondColour.G); 
    int deltaB = Math.Abs(firstColour.B - secondColour.B); 

    double val = (value - min)/(max - min); 
    int r = rOffset - Convert.ToByte(deltaR * (1 - val)); 
    int g = gOffset - Convert.ToByte(deltaG * (1 - val)); 
    int b = bOffset - Convert.ToByte(deltaB * (1 - val));   

    return Color.FromArgb(255, r, g, b); 
} 

Los resultados de este aspecto para una prueba DataGrid con algunos datos de la muestra.

enter image description here

+0

Si uso los siguientes colores Color firstColour = Color.Blue; Color secondColour = Color.Amarillo; Acabo de obtener tonos de gris – Chris

0

Una solución que va de rojo a amarillo a verde

static Color CreateHeatColor(int value, decimal max) 
    { 
     if (max == 0) max = 1M; 
     decimal pct = value/max; 
     Color color = new Color(); 

     color.A = 255; 

     if (pct < 0.34M) 
     { 
      color.R = (byte) (128 + (127 * Math.Min(3 * pct, 1M))); 
      color.G = 0; 
      color.B = 0; 
     } 
     else if (pct < 0.67M) 
     { 
      color.R = 255; 
      color.G = (byte) (255 * Math.Min(3 * (pct - 0.333333M), 1M)); 
      color.B = 0; 
     } 
     else 
     { 
      color.R = (byte)(255 * Math.Min(3 * (1M - pct), 1M)); 
      color.G = 255; 
      color.B = 0; 
     } 

     return color; 
    } 
0

Esto funcionó bien para mí.

public Color HeatMap(float value, float max) 
    { 
     int r, g, b; 
     float val = value/max; // Assuming that range starts from 0 
     if (val > 1) 
      val = 1; 
     if (val > 0.5f) 
     { 
      val = (val - 0.5f) * 2; 
      r = Convert.ToByte(255 * val); 
      g = Convert.ToByte(255 * (1 - val)); 
      b = 0; 
     } 
     else 
     { 
      val = val * 2; 
      r = 0; 
      g = Convert.ToByte(255 * val); 
      b = Convert.ToByte(255 * (1 - val)); 
     } 
     return Color.FromArgb(255, r, g, b); 
    } 
0

Si desea rojo a verde a través de amarillo, también puede utilizar HSL para obtener su mapa de calor. Los números en esa instancia serían 0 - 60, donde 0 = rojo y 60 = verde (see figure 11 on this link).

de implementar, es necesario utilizar System.Runtime.InteropServices y añadir lo siguiente:

[DllImport("shlwapi.dll")] 
public static extern int ColorHLSToRGB(int H, int L, int S); 

En el método, val es un valor largo y m_iMax es el número más grande de la colección, se puede cambiar en los términos requeridos:

if (val == 0) 
    return ColorTranslator.ToHtml(Color.FromArgb(255, 255, 255)); // white 
else 
{ 
    // 0 = red, 60 = green 
    int col = 60 - (int)(60 * val/m_iMax); 

    return ColorTranslator.ToHtml(ColorTranslator.FromWin32(ColorHLSToRGB(col, 120, 240))); 
} 

el siguiente es el resultado del código anterior en una tabla HTML:

Heatmap

0

La versión C# de "Curtis White" 's respuesta:

public Color HeatMap(decimal value, decimal min, decimal max) 
     { 
      decimal val = (value - min)/(max - min); 
      int A, B, R, G; 
      A = 255; 
      R = Convert.ToByte(255 * val); 
      B = Convert.ToByte(255 * (1 - val)); 
      G = 0; 
      return Color.FromArgb(A, R, G, B); 
     } 
Cuestiones relacionadas