java:表示颜色标度上的浮点值范围

时间:2013-08-10 22:00:58

标签: java colors scale

我正在尝试创建一个将浮点值转换为颜色的函数。我创建了一个简单的线性比例:

float value;
float maxValue;

float scaleStep = maxValue / 5;

if (value < scaleStep) {
    color = blue
}

if (value > scaleStep && value <= scaleStep * 2) {
    color = green
}

if (value > scaleStep * 2 && value <= scaleStep * 3) {
    color = yellow
}

if (value > scaleStep * 3 && value <= scaleStep * 4) {
    color = orange
}

if (value > scaleStep * 4 && value <= scaleStep * 5) {
    color = red
}

但是由于我试图表示的集合中的大多数(但不是全部)值与一个特定值非常接近,因此使用线性刻度的图形表示不是很有用(几乎所有内容都转换为一个颜色)。

如何创建非线性比例以使值之间的差异更明显?

5 个答案:

答案 0 :(得分:2)

Interpolation就是你想要的。插值在数据集中的已知样本之间生成样本。

在这里,您已知的样本是您的颜色;蓝色,绿色,黄色,橙色和红色。这些已知颜色之间的颜色是您正在寻找的颜色。

Here's a link一个很好的插值函数可视化器。

这里有一些插值函数,方便您使用。与他们一起玩,找到最适合你的那个!

public float linearInterpolation(float start, float end, float normalizedValue) {
    return start + (end - start) * normalizedValue;
}

public float sinInterpolation(float start, float end, float normalizedValue){
    return (start+(end-start)* (1 - Math.cos(normalizedValue * Math.PI)) / 2;
}

//usage
linearInterpolation(red, green, .5f);//halfway between red and green.
//same with other demonstrations.

编辑:

这里,start和end指的是一个开始和结束的样本。 normalizedValue是[0,1]之间的某个值(这意味着它可以恰好等于0或1,或0到1之间的任何值。这就是术语normalized通常意味着什么。)

因此,对您而言,startend将是两种颜色,normalizedValue将表示您与起始颜色或结束颜色的接近程度。

以linearInterpolation为例。

red = 1;
green = 2;
float midway = 1 + (2 - 1) * .5;
//midway = 1.5, which is halfway between red and green.
float allRed = 1 + (2 - 1) * 0;
//allRed = 1, which is the value of red (or start)
float allGreen = 1 + (2 - 1) * 1;
//allGreen = 2, which is the value of green (or end)

因此,对于线性插值,normalizedValue越接近1,返回值越接近endnormalizedValue越接近0,返回的值越接近start

其他插值函数不一定如此。您可以将线性插值视为连接值的简单线段。想要在这些细分市场之间获得价值吗?使用标准化值.5,viola!

其他功能可能会有更陡峭的斜率,甚至在startend之间振荡!

尝试并停止思考颜色,并开始更抽象地思考。颜色相隔一定距离。插值可帮助您定义它们之间的距离中的值。

答案 1 :(得分:1)

由于浮点值在一个集合中,您知道有多少,并且可以计算颜色间隔。然后,您可以迭代它们,分配颜色并按颜色间隔递增。

编辑:这种方法的缺点是当值的数量发生变化时,相同的浮点值不会映射到相同的颜色。

答案 2 :(得分:0)

我建议采用对数标度。如果使用基数为10的日志,则范围将为-39到+39。

答案 3 :(得分:0)

根据您的发行版,双重或三重日志可能会更好。我做了一个非常快速的测试,对于样本{ 1.00, 1.20, 1.10, 1.05, 1.15, 9.70, 1.20, 2.00, 1.01, 1.03, 1.16, 1.02, 9.00, 1.20, 1.10, 1.50, 1.05, 1.15, 2.00, 3.00 },函数

int f(float x) {
    return (int)(Math.log(Math.log(x)*100+1)*2.5) ;
}

产生以下分布:

f(x)  color   count
 0    blue      4
 1    green     4
 2    yellow    6
 3    orange    3
 4    red       3

5分钟的工作还不错。但是,如果您发布合理的数字样本(比如100),分布图,或者更好的是分布直方图,我们可以帮助您更好。诀窍是找到数据的分布函数。从该函数可以很容易地得到第二个函数,使得分布均匀(“平坦”)。

答案 4 :(得分:0)

在你的情况下的第二种选择(由于你只想使用几种颜色而相对简单),是使用不同“宽度”的scaleStep

if( value < greenMin ) color= blue ;
else if( value < yellowMin ) color= green ;
else if( value < orangeMin ) color= yellow ;
else if( value < redMin ) color = orange ;
else color= red ;

我冒昧地将代码缩了一下。如果不清楚,请告诉我。当然,您需要确定greenMin,yellowMin,orangeMin和redMin的值。为此,抓住一个大的,有代表性的数据样本,对其进行排序,并将其划分为5个相同大小的组。第二组的第一个值是greenMin,第三个的第一个值是yellowMin,依此类推。您可以使用办公室电子表格程序来执行此操作,因为这是一次性活动。