您必须知道double 值的可能范围。 (至少,这会使事情更容易理解)。在任何情况下,您都可以将 double 值转换为 [0,1] 范围内。无论如何,在许多情况下进行这种规范化是有益的。
所以你可以创建一个方法
private static double normalize(double min, double max, double value) {
return (value - min) / (max - min);
}
此方法会将最小值和最大值之间的任何“值”转换为 [0,1] 中的值。为了将此归一化值映射到颜色,您可以使用
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);
}
此方法会将 0.0 到 1.0 之间的值转换为颜色:0.0 为黑色,1.0 为红色。
所以假设你在“min”和“max”之间有一个双“值”,你可以将它映射到这样的颜色:
g2d.setColor(colorFor(normalize(min, max, value)));
g2d.fill(shape);
编辑:回复评论:我认为基本上有两种选择:
- 您可以持续跟踪您目前遇到的当前最小值/最大值。
- 或者,您可以使用 sigmoidal 函数将 [-Infinity,+Infinity] 的区间映射到区间 [0,1]
第一个选项的缺点是先前与某种颜色相关联的值可能突然具有不同的颜色。例如,假设您将区间 [0,1] 映射到颜色范围 [black, red]。现在您获得了一个新的最大值,例如 100000。然后您必须调整您的范围,值 0 和 1 将不再有视觉差异:它们都将映射到“黑色”。
第二个选项的缺点是初始值的微小差异不会对颜色产生明显影响,具体取决于这些差异发生的范围。例如,您将无法在此处看到 10000 和 10001 之间的差异。
所以你必须清楚你想要什么颜色映射和行为。
但是,这里有一个例子,它使用sigmoidal函数将[-Infinity,+Infinity]的区间映射到区间[0,1],并将这个区间映射到一个颜色:
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);
}
}