1. 前言
最近项目中需要根据数据绘制热力图来对数据进行可视化,查了很多资料发现Qcustomplot是实现这个功能最方便的,下面就介绍一下使用QcustomPlot的QCPColorMap类进行绘制图像的过程及遇到的问题(本文章是针对QcustomPlot2.0开发的,与1.0版本差别还是很大的)。
2.QCPColorMap简介
qcpcolormap能够绘制二维彩色图表,简单说就是能够将三维数据在二维平面上标识。在绘制过程中需要用到三组数据:键数据(key),值数据(value)以及“键值对”所对应的数据,其中key一般代表x轴的对应坐标,value对应y轴所对应的坐标,由x和y能够确定一个格点,该格点的值可以理解为Z值,在图表中通过映射成颜色来表示。
3.代码示例
// qcustomplot对象,我是通过qtdesigner创建的
QCustomPlot* customPlot=ui->heatmap;
customPlot->addGraph();
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); // 可拖拽+可滚轮缩放
customPlot->xAxis->setRange(xmin, xmax); // X轴的显示范围
customPlot->xAxis->setAutoTickCount(5); // 设置刻度数量
customPlot->yAxis->setLabel("深度(m)");
customPlot->yAxis->setRange(ymin, ymax); // Y轴的显示范围
customPlot->yAxis->setAutoTickCount(3); // 设置刻度数量
// 设置映射图
QCPColorMap* cpColorMap;
cpColorMap = new QCPColorMap(customPlot->xAxis, customPlot->yAxis);
cpColorMap->data()->setSize(x_size, y_size); // 设置key和value的数量
cpColorMap->data()->setRange(QCPRange(x_min, x_max), QCPRange(ymin, ymax)); // 设置key和value的范围
cpColorMap->setDataRange(QCPRange(100, 101)); // 设置z数据的范围
//为每一个点赋值
for (int x = xmin; x < xmax; x++)
{
for (int y = ymin; y < ymax; y++)
{
cpColorMap->data()->setData(x, y, z);
}
}
customPlot->addPlottable(cpColorMap);
cpColorMap->rescaleDataRange(); // 重新缩放数据维度(颜色),以使所有数据点都位于颜色渐变显示的范围内:
cpColorMap->setInterpolate(true); // 禁用插值,界面显示小方块
// 设置色条的颜色变化
QCPColorGradient gradient;
gradient.setColorInterpolation(QCPColorGradient::ciRGB);
gradient.setColorStopAt(0, Qt::black);
gradient.setColorStopAt(0.001, Qt::blue);
gradient.setColorStopAt(0.33, Qt::green);
gradient.setColorStopAt(0.66, Qt::yellow);
gradient.setColorStopAt(1.0, Qt::red);
cpColorMap->setGradient(gradient);
// 立即刷新
customPlot->replot();
customPlot->show();
上面代码中主要包括三部分:首先需要设置图表x、y坐标轴的属性以及刻度范围;然后设置映射图的数据大小和范围,以及对每个格点进行赋值;最后设置数据映射的规则(色条的颜色分布,它会自动根据对映射图中格点的数值自动进行颜色映射)。
除了通过cpColorMap->data()->setData(x, y, z);的方式对格点赋值外还有另一种赋值方式:
QCPColorMapData *colorMapData = new QCPColorMapData2(x_size, y_size,QCPRange(xmin, xmax), QCPRange(ymin, ymax));
for (int x=xmin; x<xmax; x++)
{
for (int y=ymin; y<ymax; y++)
{
colorMapData->setCell(x, y, z);
}
}
colorMap->setData(colorMapData);
4.空值问题
在对格点进行赋值时,存在一个问题,当z值为空值时在映射颜色的时候它会自动将空值通过插值的方式补差,在我的应用中我并不希望这样,我希望对于空值能够显示特定的颜色但是它没办法实现,查找文档想了好久发现一种方法,可以通过设置格点的透明度,将为空值的格点设置为透明以突出它。
QCPColorMapData *colorMapData = new QCPColorMapData2(x_size, y_size,QCPRange(xmin, xmax), QCPRange(ymin, ymax));
for (int x=xmin; x<xmax; x++)
{
for (int y=ymin; y<ymax; y++)
{
if(std::isnan(z))
{
colorMapData->setAlpha(x, y, 10);
}
else
{
colorMapData->setCell(x, y, z);
}
}
}
colorMap->setData(colorMapData);