You have to know the possible range of the double
values. (At least, this would make things easier to understand). In any case, you can transform your double
value to be in the range [0,1]. And it's in many cases beneficial to do such a kind of normalization anyhow.
So you can create a method
private static double normalize(double min, double max, double value) {
return (value - min) / (max - min);
}
This method will convert any "value" between min and max to a value in [0,1]. In order to map this normalized value to a color, you can use
private static Color colorFor(double value) {
value = Math.max(0, Math.min(1, value));
int red = (int)(value * 255);
return new Color(red,0,0);
}
This method will convert a value between 0.0 and 1.0 into a color: 0.0 will be black, and 1.0 will be red.
So assuming you have a double "value" between "min" and "max", you can map it to a color like this:
g2d.setColor(colorFor(normalize(min, max, value)));
g2d.fill(shape);
EDIT: Reply to the comment: I think there are basically two options:
- You could constantly keep track of the current min/max values that you have encountered so far.
- Alternatively, you could map the interval of [-Infinity,+Infinity] to the interval [0,1] using a sigmoidal function
The first option has the disadvantage that values that have previously been associated with a certain color may suddenly have a different color. For example assume that you mapped the interval [0,1] to the color range [black, red]. Now you obtain a new maximum value like 100000. Then you have to adjust your range, the values 0 and 1 will no longer have a visual difference: They will both be mapped to 'black'.
The second option has the disadvantage that small differences in the initial values will not have a noticable effect on the color, depending on the range in which these differences occur. For example, you will not be able to see a difference between 10000 and 10001 there.
So you have to be clear about what color mapping and behavior you want.
However, here is an example that uses a sigmoidal function to map the interval of [-Infinity,+Infinity] to the interval [0,1], and this interval to a color:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
class ColorRange
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new ColorRangePanel());
f.setSize(1000, 200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class ColorRangePanel extends JPanel
{
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
double values[] = {
-1e3, -1e2, -1e1, -1, -0.5, 0.0, 0.5, 1, 1e1, 1e2, 1e3
};
for (int i=0; i<values.length; i++)
{
double value = values[i];
int w = getWidth() / values.length;
int x = i * w;
g.setColor(Color.BLACK);
g.drawString(String.valueOf(value), x, 20);
g.setColor(colorFor(value));
g.fillRect(x, 50, w, 100);
}
}
private static Color colorFor(double value)
{
double v0 = value / Math.sqrt(1 + value * value); // -1...1
double v1 = (1 + v0) * 0.5; // 0...1
return colorForRange(v1);
}
private static Color colorForRange(double value)
{
value = Math.max(0, Math.min(1, value));
int red = (int)(value * 255);
return new Color(red,0,0);
}
}