vtkLookupTable将标量映射到指定的颜色,颜色有两种方式设置:
- 一种是默认的,通过色调Hues,亮度Value、对比度Saturation设置
- 另一种是手动设置,SetTableValue(index,r,g,b,a);
常见函数:
-
SetTableRange(minValue, maxValue):设置颜色查找表的数值范围。所有待映射的数据值应在这个范围内。
-
GetTableRange():获取当前设置的数值范围。
-
SetNumberOfColors(numberOfColors):设置颜色查找表中颜色条目的数量。默认情况下,创建一个
vtkLookupTable
会生成256个颜色条目。 -
SetHueRange(minHue, maxHue):设置颜色条目的色调范围。Hue值介于0.0到1.0之间,对应于色彩轮上的角度。例如,(0.667, 0.0)表示从蓝色到红色的过渡。
-
SetSaturationRange(minSaturation, maxSaturation):设置颜色条目的饱和度范围。Saturation值介于0.0(灰色)到1.0(完全饱和)之间。
-
SetValueRange(minValue, maxValue):设置颜色条目的亮度(Value)范围。Value值介于0.0(黑色)到1.0(白色)之间。
-
Build():根据当前设置的参数(如色调、饱和度、亮度范围等)生成颜色查找表。在修改了颜色查找表的参数后,通常需要调用此方法更新颜色条目。
-
GetColor(index, rgbaArray):获取指定索引处的颜色条目的RGBA值。rgbaArray应是一个长度为4的浮点数数组,用于接收红、绿、蓝、透明度(Alpha)通道的值。
-
GetColor(value, rgbaArray):根据给定数值value从颜色查找表中获取对应的RGBA颜色值。
- SetRampToLinear(): 设置颜色查找表的颜色分布方式为线性。数据值与颜色之间呈线性比例关系,颜色变化连续且均匀。相邻数据值之间的颜色差异是恒定的。
- SetRampToSCurve(): 置颜色查找表的颜色分布方式为S形曲线(sigmoidal curve)。这是一种非线性映射,颜色变化起初缓慢,然后在中间区域加速变化,最后再次放缓。这样的映射方式增强了数据两端颜色的区分度,同时在中间区域保持较高的颜色分辨率。
- SetRampToSQRT(): 设置颜色查找表的颜色分布方式为平方根函数。这是一种非线性映射,数据值与颜色之间的关系不再是简单的线性比例,而是数据值的平方根与颜色值成正比。这导致数据值较小的变化在颜色上体现为较大的变化,而随着数据值增大,相同增量的数据值对应的颜色变化逐渐减小。
- GetRamp():获取当前的Ramp类型,默认是SetRampToSCurve()
举例:显示地形的伪代码
// 创建颜色查找表
vtkSmartPointer<vtkLookupTable> colorLUT = vtkSmartPointer<vtkLookupTable>::New();
colorLUT->SetHueRange(0.667, 0); // 从蓝色到红色
colorLUT->SetSaturationRange(1.0, 1.0);
colorLUT->SetValueRange(1.0, 1.0);
colorLUT->SetTableRange(demReader->GetOutput()->GetScalarRange()); // 自动获取DEM的高度范围
colorLUT->Build();
// 设置地形Actor的Mapper使用颜色查找表
vtkSmartPointer<vtkPolyDataMapper> mapper = ...; // 获取地形Actor的Mapper
mapper->SetScalarRange(colorLUT->GetTableRange()); // 使映射器使用相同的范围
mapper->SetLookupTable(colorLUT);
mapper->SetScalarModeToUsePointData(); // 使用点数据(高度值)进行颜色映射
mapper->SetColorModeToMapScalars(); // 启用颜色映射
举例:创建一个特定颜色不同强度的查找表
vtkSmartPointer<vtkLookupTable> CreateLookupTable(ColorType type, double lower, double upper)
{
double mask[3] = { 0 };
double dColor = 0;
switch (type)
{
case Red:
mask[0] = 1;
mask[1] = 0;
mask[2] = 0;
dColor = 0;
break;
case Green:
mask[0] = 0;
mask[1] = 1;
mask[2] = 0;
dColor = 0.333;
break;
case Blue:
mask[0] = 0;
mask[1] = 0;
mask[2] = 1;
dColor = 0.667;
break;
case Yellow:
mask[0] = 1;
mask[1] = 1;
mask[2] = 0;
dColor = 0.167;
break;
default:
mask[0] = 1;
mask[1] = 1;
mask[2] = 1;
break;
}
#if 1
vtkNew<vtkLookupTable> lookupTable;
lookupTable->SetNumberOfColors(256);
lookupTable->SetRange(lower, upper);
lookupTable->SetHueRange(dColor, dColor);
lookupTable->SetSaturationRange(0.0, 1.0);
lookupTable->SetValueRange(0.0, 1.0);
lookupTable->SetRampToSCurve();
lookupTable->Build();
#else
for (int i = 0; i < 256; ++i)
{
lookupTable->SetTableValue(i, ((double)i / 255.0)*mask[0], ((double)i / 255.0) * mask[1], ((double)i / 255.0) * mask[2], 1);
}
#endif
return lookupTable;
}
举例:用四个顶点,拓扑两个三角形,四个顶点设置四个颜色(多种方式实现)
int main(int, char*[])
{
//创建四个点
vtkNew<vtkPoints> points;
points->InsertNextPoint(0.0, 0.0, 0.0);
points->InsertNextPoint(1.0, 0.0, 0.0);
points->InsertNextPoint(0.0, 1.0, 0.0);
points->InsertNextPoint(1.0, 1.0, 0.0);
//创建两个三角形:第一个参数是三角形三个点的索引,第二个参数是当前三角型的顶点对应points中哪个点
vtkNew<vtkTriangle> triangle1;
triangle1->GetPointIds()->SetId(0, 0);
triangle1->GetPointIds()->SetId(1, 1);
triangle1->GetPointIds()->SetId(2, 2);
vtkNew<vtkTriangle> triangle2;
triangle2->GetPointIds()->SetId(0, 1);
triangle2->GetPointIds()->SetId(1, 2);
triangle2->GetPointIds()->SetId(2, 3);
//创建拓扑结构:插入两个三角形
vtkNew<vtkCellArray> triangles;
triangles->InsertNextCell(triangle1);
triangles->InsertNextCell(triangle2);
//创建vtkPolyData,并设置顶点数据和拓扑数据
vtkNew<vtkPolyData> polyData;
polyData->SetPoints(points);
polyData->SetPolys(triangles);
// 定义四个温度值
std::vector<double> temperatures = { 10.0, 20.0, 30.0, 40.0 };
// 给四个顶点设置颜色方式1:
// 该方式不常用,此处仅仅是为了联系和理解标量和查找表的映射关系
//vtkNew<vtkUnsignedCharArray> colorArr;
//colorArr->SetNumberOfComponents(3);
创建颜色查找表(默认为RGB,256个颜色条目)
//vtkSmartPointer<vtkLookupTable> colorLUT = vtkSmartPointer<vtkLookupTable>::New();
//colorLUT->SetNumberOfColors(256);//256个颜色条目
//colorLUT->SetTableRange( temperatures[0], temperatures[temperatures.size()-1]); // 设置颜色查找表的范围与温度范围一致
//colorLUT->SetHueRange(0.667, 0); // 色调从蓝色到红色
//colorLUT->SetSaturationRange(1.0, 1.0);//对比度一直最大保持不变
//colorLUT->SetValueRange(1.0, 1.0);//亮度一直最大保持不变
//colorLUT->SetRampToSCurve();//默认值也是他,另外两个是SetRampToLinear()和SetRampToSQRT()
//colorLUT->Build();
定义一个颜色与温度映射函数
//auto GetColor = [&temperatures, &colorLUT](double value, double colorRGB[3])
//{
// // 对每个温度值进行颜色映射
// for (double temperature : temperatures)
// {
// // double rgba[4]; // 存储映射后的RGBA颜色值
// if (temperature == value)
// {
// colorLUT->GetColor(temperature, colorRGB);//有个缺陷没法获取单个点的alpha
// std::cout << "Temperature: " << temperature << ", Color: (" << colorRGB[0] << ", "<< colorRGB[1] << ", " << colorRGB[2] << ")\n";
// colorRGB[0] *= 255;//内部归一化了,所以进行还原
// colorRGB[1] *= 255;
// colorRGB[2] *= 255;
// break;
// }
// }
// return colorRGB;
//};
//for (size_t i = 0; i < temperatures.size(); i++)
//{
// double rgb[3] = { 255, 0, 0 };
// colorArr->InsertNextTuple(GetColor(temperatures[i],rgb));
//}
//polyData->GetPointData()->SetScalars(colorArr);
// 给四个顶点设置颜色方式2:
//给polyData设置标量值,然后在mapper中设置vtkLookupTable
vtkNew<vtkIntArray> tempArr;
for (size_t i = 0; i < temperatures.size(); i++)
{
tempArr->InsertNextValue(temperatures[i]);
}
polyData->GetPointData()->SetScalars(tempArr);
// 给每个温度设置指定的颜色
vtkSmartPointer<vtkLookupTable> colorLUT = vtkSmartPointer<vtkLookupTable>::New();
colorLUT->SetTableRange(temperatures[0], temperatures[temperatures.size()-1]);//temperatures要求是从小到大排序
colorLUT->SetNumberOfTableValues(4);//四个顶点设置四个颜色,不需要默认256,渲染三角形时会做插值
#if 0
colorLUT->SetHueRange(0, 0.667); // 从蓝色到红色
colorLUT->SetSaturationRange(1.0, 1.0);
colorLUT->SetValueRange(1.0, 1.0);
#else
colorLUT->Build();
//也可以手动给每个温度设置颜色值,此方法的好处时可以设置alpha
double rgba1[4] = { 0, 0, 1, 1 };
double rgba2[4] = { 0, 1, 0, 0.8 };
double rgba3[4] = { 0, 1, 0, 0.5 };
double rgba4[4] = { 1, 0, 0, 0.1 };
//此处必须要SetNumberOfTableValues(4)
//SetTableValue查找表的索引,查找表内部可理解为index-colorValue[4]
//该方法也可以设置梯度而非线性,例如手动修改256索引的颜色值,例如:
//for (int i = 0; i < 256; i++)
//{
// if (i < 100)
// colorLUT->SetTableValue(i, rgba1);
// if (i < 200)
// colorLUT->SetTableValue(i, rgba2);
// else
// colorLUT->SetTableValue(i, rgba3);
//}
colorLUT->SetTableValue(0, rgba1);
colorLUT->SetTableValue(1, rgba2);
colorLUT->SetTableValue(2, rgba3);
colorLUT->SetTableValue(3, rgba4);//第一个参数必须小于GetNumberOfTableValues,默认是256个
#endif
//显示流程
vtkNew<vtkPolyDataMapper> mapper;
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
mapper->SetInputData(polyData);
//方式2剩余部分
mapper->SetScalarRange(temperatures[0], temperatures[temperatures.size() - 1]);
mapper->SetLookupTable(colorLUT);
vtkNew<vtkRenderWindow> window;
vtkNew<vtkRenderer> render;
window->AddRenderer(render);
render->AddActor(actor);
vtkNew<vtkRenderWindowInteractor> inter;
inter->SetRenderWindow(window);
inter->Initialize();
inter->Start();
return EXIT_SUCCESS;
}