原文链接:https://pcl.readthedocs.io/projects/tutorials/en/latest/pcl_plotter.html#pcl-plotter
PCLPlotter类
PCLPlotter类提供了非常直接简单的接口用于绘制图表。它内置了所有种类图表的工具库:从多项式函数到直方图,而不用另外的软件(如Matlab)。
下面的代码片段简单是展示了PCLPlotter类的使用:
#include<vector>
#include<iostream>
#include<utility>
#include<pcl/visualization/pcl_plotter.h>
int
main()
{
//定义一个plottter类
pcl::visualization::PCLPlotter * plotter = new pcl::visualization::PCLPlotter();
//定义一个多项式函数
//y=x^2,x^2的下标为1,常数项为0
// 0 0 1
std::vector<double> func1(3, 0);
func1[2] = 1;
//将多项式添加进plottter中
//X 轴的区间范围:[-10, 10] as the range in X axis and "y = x^2" as title
plotter->addPlotData(func1, -10, 10, "y=x^2");
//显示图表,完成
plotter->plot();
return 0;
}
运行结果,显示一个简单的y=x^2的曲线:
基本代码结构
PCLPlotter
... //1. 声明绘图对象 pcl::visualization::PCLPlotter *plotter = new PCLPlotter ("My Plotter"); ... //2. 使用addPlotData() 函数添加绘图所需的函数或者数据 plotter->addPlotData(); ... //3. 如果需要,还可以设置窗口属性 plotter->setWindowSize (900, 600); plotter->setYTitle ("this is my own function"); ... //4. 最后调用绘制函数 plotter->plot ()
绘图自动上色
用户可以王addPlotData()函数里传入自己定义的颜色,如果不进行设置,绘图对象plotter将会根据一种颜色模式自动上色。默认的颜色模式是 vtkColorSeries::SPECTRUM,包含了整个光谱的七种颜色。其他的颜色模式是:
vtkColorSeries::WARM
vtkColorSeries::COOL
vtkColorSeries::BLUES
vtkColorSeries::WILD_FLOWER
vtkColorSeries::CITRUS
用户可以使用setColorScheme()函数来改变颜色模式。为了反映改变颜色模式带来的效果,用户要再调用addPlotData()函数之前调用setColorScheme()函数。
不同类型的绘图输入
点对应关系(双数值输入)
这是提供输入的最基本方式。坐标(x,y)作为输入,可以在addPlotData中使用std::vector<std::pair>
#include<vector>
#include<iostream>
#include<utility>
#include<pcl/visualization/pcl_plotter.h>
int
main()
{
//定义一个plottter类
pcl::visualization::PCLPlotter * plotter = new pcl::visualization::PCLPlotter();
std::vector<std::pair<double, double> > data;
//设置数据
data.push_back({ 1,1 });
data.push_back({ 2,2.5 });
data.push_back({ 4.9,1.6 });
data.push_back({ 5.7,6.7 });
data.push_back({ 6.8,4.3 });
data.push_back({ 5.8,7.3 });
data.push_back({ 2.8,9.3 });
data.push_back({ 0.8,2.3 });
plotter->addPlotData(data, "test");
//显示图表,完成
plotter->plot();
return 0;
}
运行效果:
可以看到,所有的点按照顺序连接在了一起。
双数值的另一种输入方式是通过两个相同长度的数组,输入双数值的X值和Y值。
文件输入(表格)
与上一个相同,只是用户将对应关系的点存储在文本文件中,以空格隔开形成表格的形式。这是使用MS Excel绘图的一种替代方法。下面是一个非常简单,可执行的示例,展现了MS Excel 绘图的功能:
#include<pcl/visualization/pcl_plotter.h>
int
main (int argc, char ** argv)
{
pcl::visualization::PCLPlotter * plotter = new PCLPlotter ();
plotter->addPlotData (argv[1]);//文件名为参数传入
plotter->plot ();
return 0;
}
data.txt文件中数据(数字之间用空格隔开):
1 2
3 4
5 6
7 8
9 10
8.8 7.7
6.6 5.5
4.4 3.3
2.2 1.1
在命令行中调用exe文件,并传入data.txt的文件名:
显示效果:
多项式和有理函数
多项式是由系数向量定义的,而有理函数则是由多项式对(分子和分母对)定义的。
std::vector<double>func1(1, 0);
func1[0] = 1;//func1多项式为分子,x^0 的系数为1
std::vector<double>func2(3, 0);
func2[0] = 6; //func2多项式为分母,x ^ 0 的系数为6
func2[1] = 1;//x^1 的系数为1
func2[2] = 1;//x^2 的系数为1
//此时的图形为:func1/func2 = 1/(x^2 + x^1 + 6)
//X 轴的区间范围:[-10, 10]
plotter->addPlotData(std::make_pair(func1, func2), -10, 10, "1/(x^2 + x^1 + 6)");
//显示图表,完成
plotter->plot();
自定义的显示函数
用户可以指定自定义的函数运行。f用于描述对应关系:Y=f(X),形式为回调函数:
double getSquare(double val) {
return val * val;
}
...
plotter->addPlotData(getSquare, -10, 10, "Square");
//显示图表,完成
plotter->plot();
此时的自定义函数为Y = X * X:
添加其他绘图属性和装饰
添加的绘图属性可以是标题,背景颜色和说明等。在plot()函数调用前,可以在任意时候使用这些函数:
plotter->setTitle ("My plot"); //global title
plotter->setXTitle ("degrees");
plotter->setYTitle ("cos");
plotter->setShowLegend (true); //show legends
...
plotter->plot ();
其他功能
不同于对已定义好的双数值的绘制功能,PCLPlotter还提供了一些重要的绘制功能,其中包括特征直方图绘制功能和类PCLHistogramVisualizer的所有功能。
绘制直方图
PCLPlotter就像Matlab提供的hist()函数一样,提供了一个非常方便的直方图绘制函数。它将原始数据按照其频率分类,并将其绘制成条形图。
PCLHistogramVisualizer 是以前版本中绘制直方图的类,所有功能已经被包含在类PCLPlotter中。
显示绘图
可以使用plot()函数显示所有的绘制。PCLPlotter同样提供spin()函数,用于动画或者时间更新的显示。
...
//data and callback defined here
...
plotter->addPlotData (func1, -10, 10, "y = x^2");
plotter->spinOnce (2000); //display the plot for 2 seconds
plotter->clearPlots ();
plotter->addPlotData (identity,-10, 10,"identity");
plotter->spinOnce (2000);
plotter->clearPlots ();
plotter->addPlotData (abs,-5, 5,"abs");
plotter->spinOnce (2000);
...
测试用例
#include<vector>
#include<iostream>
#include<utility>
#include<cmath>
#include<pcl/visualization/pcl_plotter.h>
using namespace pcl::visualization;
void
generateData(double *ax, double *acos, double *asin, int numPoints)
{
double inc = 7.5 / (numPoints - 1);
for (int i = 0; i < numPoints; ++i)
{
ax[i] = i * inc;
acos[i] = std::cos(i + inc);
asin[i] = sin(i + inc);
}
}
//-----------------------定义Y= f(X)的回调函数-------------------
double
step(double val)
{
if (val > 0)
return (double)(int)val;
else
return (double)((int)val - 1);
}
double
identity(double val)
{
return val;
}
int
main(int argc, char** argv)
{
//定义一个plottter类
pcl::visualization::PCLPlotter * plotter = new pcl::visualization::PCLPlotter();
//设置一些属性
plotter->setShowLegend(true);
//生成对应点
int numPoints = 69;
double ax[100], acos[100], asin[100];
generateData(ax, acos, asin, numPoints);
//添加绘制的数据
plotter->addPlotData(ax, acos, numPoints, "cos");
plotter->addPlotData(ax, asin, numPoints, "sin");
//显示3秒
plotter->spinOnce(3000);
plotter->clearPlots();
//-------------绘制隐式函数和自定义函数-------------------
//设置Y轴区域
plotter->setYRange(-10, 10);
//定义多项式
std::vector<double> func1(1, 0);
func1[0] = 1;//y=1
std::vector<double> func2(3, 0);
func2[2] = 1;//y=x^2
plotter->addPlotData(std::make_pair(func1, func2), -10, 10, "y = 1/x^2", 100, vtkChart::POINTS);
plotter->spinOnce(2000);
plotter->addPlotData(func2, -10, 10, "y = x^2");
plotter->spinOnce(2000);
//callbacks
plotter->addPlotData(identity, -10, 10, "identity");
plotter->spinOnce(2000);
plotter->addPlotData(std::abs, -10, 10, "abs");
plotter->spinOnce(2000);
plotter->addPlotData(step, -10, 10, "step", 100, vtkChart::POINTS);
plotter->spinOnce(2000);
plotter->clearPlots();
//一个简单的动画
std::vector<double> fsq(3, 0);
fsq[2] = -100;//y=x^2;
while (!plotter->wasStopped())
{
if (fsq[2] == 100) fsq[2] = -100;
fsq[2]++;
char str[50];
//sprintf(str, "y=%dx^2", (int)fsq[2]);
plotter->addPlotData(fsq, -10, 10, str);
plotter->spinOnce(100);
plotter->clearPlots();
}
return 0;
}