需要帮助来了解颜色映射算法

时间:2019-02-27 15:28:53

标签: c opengl data-visualization

因此,我正在从事一个项目,该项目涉及获取模拟“流体流动和可视化”的应用程序的预先存在的框架代码,并在其上应用不同的可视化技术。

该项目的第一步是对以下三个不同的数据集应用不同的颜色映射技术:流体密度(rho),流体速度大小(|| v ||)和力场大小| |。 | f ||。

所提供的框架代码已经有一个示例,我可以研究该示例,以便确定如何最好地设计和实现不同的颜色图,例如红色到白色或蓝色到黄色,或者您拥有什么。

我要理解的代码段如下:

//rainbow: Implements a color palette, mapping the scalar 'value' to a rainbow color RGB
    void rainbow(float value,float* R,float* G,float* B)
    {                          
       const float dx=0.8; 
       if (value<0) value=0; if (value>1) value=1;
       value = (6-2*dx)*value+dx;
       *R = max(0.0,(3-fabs(value-4)-fabs(value-5))/2);
       *G = max(0.0,(4-fabs(value-2)-fabs(value-4))/2);
       *B = max(0.0,(3-fabs(value-1)-fabs(value-2))/2);
    }

据我所知,第一个参数传递的float value是流体密度。我已经通过研究这两个代码段来确定了这一点。

//set_colormap: Sets three different types of colormaps
void set_colormap(float vy)
{
   float R,G,B; 

   if (scalar_col==COLOR_BLACKWHITE)
       R = G = B = vy;
   else if (scalar_col==COLOR_RAINBOW)
       rainbow(vy,&R,&G,&B); 
   else if (scalar_col==COLOR_BANDS)
       {  
          const int NLEVELS = 7;
          vy *= NLEVELS; vy = (int)(vy); vy/= NLEVELS; 
          rainbow(vy,&R,&G,&B);   
       }

   glColor3f(R,G,B);
}

set_colormap(rho[idx0]);
glVertex2f(px0, py0);
set_colormap(rho[idx1]);
glVertex2f(px1, py1);
set_colormap(rho[idx2]);
glVertex2f(px2, py2);


set_colormap(rho[idx0]);
glVertex2f(px0, py0);
set_colormap(rho[idx2]);
glVertex2f(px2, py2);
set_colormap(rho[idx3]);
glVertex2f(px3, py3);

综上所述,有人可以向我解释第一种方法的工作原理吗?

这是用户调用该方法并将物质通过使用光标注入到窗口中时的输出:

-

否则,它将看起来像这样(灰度):

-

2 个答案:

答案 0 :(得分:1)

我怀疑这是HSV to RGB的变体。

这个想法是,您可以将流体密度(以线性比例)映射到HSV format中颜色的Hue参数。饱和度和值只能保持1的恒定值。通常,色相以红色开始和结束,因此您还希望将色相值移到[红色,蓝色]范围内。根据流体密度,这将为您提供HSV格式的颜色“热图”,然后您必须将其映射到着色器中的RGB。

由于某些值可以保持恒定,并且由于您不关心任何中间结果,因此将流体密度转换为RGB的算法可以简化为上面的代码段。

答案 1 :(得分:1)

我不确定您不了解功能的哪一部分,所以让我逐行解释一下:

void rainbow(float value,float* R,float* G,float* B){

}

这部分可能对您很清楚-该函数接受单个密度/颜色值,并在rgb空间中输出彩虹色。

const float dx=0.8;

接下来,初始化常量dx。我不确定名称“ dx”代表什么,但看起来好像后来用来确定使用了色谱的哪个部分。

if (value<0) value=0; if (value>1) value=1;

这会将输入限制在0到1之间。

   value = (6-2*dx)*value+dx;

这会将输入映射到dx6-dx之间的值。

   *R = max(0.0,(3-fabs(value-4)-fabs(value-5))/2);

这可能是最复杂的部分。如果value小于4,则简化为max(0.0,(2*value-6)/2)max(0.0,value-3)。这意味着如果value小于3,则红色输出将为0,如果介于3和4之间,则红色输出将为value-3

如果value在4到5之间,则此行简化为等于1的max(0.0,(3-(value-4)-(5-value))/2)。因此,如果value在4到5之间,则红色输出为1

最后,如果value大于5,则此行会简化为max(0.0,(12-2*value)/2)或只是6-value

因此,当R在4到5之间时,输出value为1,而当value小于3时为0,否则输出介于两者之间。绿色和蓝色输出的计算结果几乎相同,只是调整了值;绿色在2到4之间的值最亮,蓝色在1到2之间的值最亮。这样,输出形成平滑的彩虹色谱。