python的图表库很丰富,C++依赖于python的 matplotlib的库却有很多功能不足,显得很鸡肋,其他的一些库没有过多的研究,
这里主要说说不依赖于python的纯C++ 的图表库 Matplot++
Matplot++官网
使用Matplot++同时需要下载安装gnuplot,并将gnuplot的bin加入到环境变量
Matplot++编译需要依赖一堆第三方库,可以参考官网,但是github上也提供了编译好的静态库,
Matplot++静态库下载链接
gnuplot官网
这里主要使用官网提供的静态库。
将include、lib加入到对应的位置,并配置好路径和库连接,这部分不多说了。
以下直接上代码
下方案例主要针对2D坐标系,共享坐标系实现一个SVG图形的生成。
头文件
cpp
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <chrono>
#include <cassert>
#include "matplot/matplot.h"
using namespace matplot;
class GSTestMaplotlib
{
public:
explicit GSTestMaplotlib();
~GSTestMaplotlib();
public:
void InitAxez();
void TestFunc();
std::vector<double> CaculatePower(std::vector<double>& u, std::vector<double>& i);
void AddIVData(axes_handle&,std::vector<double>& u, std::vector<double>& i);
void ADDPVData(axes_handle&,std::vector<double>& u, std::vector<double>& i);
void GetIVPointsData(const char* path,std::vector<double>& x,std::vector<double>& y);
void GetStringOfSub(std::string src, std::string splitStr, std::vector<std::string>& strVec, int isRFind);
private:
axes_handle parent_axes;
figure_handle parent_figure;
};
cpp文件
cpp
#include "GSTestMaplotlib.h"
#include <QtCore/QCoreApplication>
GSTestMaplotlib::GSTestMaplotlib()
{
InitAxez();
}
GSTestMaplotlib::~GSTestMaplotlib()
{
}
void GSTestMaplotlib::InitAxez()
{
parent_figure = figure(true); //设置为quiet_mode模式,即只处理数据,不会调用gnuplot的UI显示窗口
//parent_figure= figure_no_backend(true);
this->parent_axes = axes();
this->parent_axes->grid(true);
this->parent_axes->grid_alpha(0.5);
this->parent_axes->grid_color({ 125,125,125,0 });
this->parent_axes->xlabel("Voltage(V)");
this->parent_axes->ylabel("Currect(A)");
this->parent_axes->y2label("Currect(P)");
this->parent_axes->hold(on);
parent_figure->add_axes(this->parent_axes,true, true);
//parent_figure->current_axes(this->parent_axes);
parent_figure->reactive_mode(false);
std::string path = QString(QCoreApplication::applicationDirPath() + "/area_4.svg").toStdString();
parent_figure->backend()->output(path);
}
#include <QThread>
void GSTestMaplotlib::TestFunc()
{
std::vector<double> u;
std::vector<double> i;
GetIVPointsData("0000000001-T1M1.csv", u, i);
std::vector<double> p = CaculatePower(u, i);
for (int ii= 0; ii <5; ii++)
{
AddIVData(parent_axes, u, i);
ADDPVData(parent_axes, u, p);
QThread::msleep(20);
}
std::string path = QString(QCoreApplication::applicationDirPath() + "/area_4.svg").toStdString();
bool ret = parent_figure->save(path);
parent_figure->draw();
}
void GSTestMaplotlib::AddIVData(axes_handle& parent_axes,std::vector<double>& u, std::vector<double>& i)
{
auto start = std::chrono::steady_clock::now();
auto parent = parent_axes->plot(u, i);
parent->touch();
auto end = std::chrono::steady_clock::now();
auto time_diff = end - start;
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(time_diff);
std::cout << "Operation cost IV : " << duration.count() << "ms" << std::endl;
}
void GSTestMaplotlib::ADDPVData(axes_handle& parent_axes,std::vector<double>& u, std::vector<double>& p)
{
auto start = std::chrono::steady_clock::now();
auto parent = parent_axes->plot(u, p);
parent->use_y2(true); //使用右侧Y轴
y2label("Currect(P)"); //必需设置
parent->touch();
auto end = std::chrono::steady_clock::now();
auto time_diff = end - start;
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(time_diff);
std::cout << "Operation cost PV : " << duration.count() << "ms" << std::endl;
}
std::vector<double> GSTestMaplotlib::CaculatePower(std::vector<double>& u, std::vector<double>& i)
{
std::vector<double> powerVec;
auto itorV = u.begin();
auto itorI = i.begin();
for (; itorV != u.end(); itorV++, itorI++)
{
double power = (*itorV)*(*itorI);
powerVec.emplace_back(power);
}
return powerVec;
}
void GSTestMaplotlib::GetIVPointsData(const char* path, std::vector<double>& x, std::vector<double>& y)
{
std::ifstream fileIn;
fileIn.open(path);
assert(fileIn.is_open());
std::string line;
std::vector<std::string> axisData;
while (getline(fileIn, line))
{
GetStringOfSub(line,",", axisData,1);
x.emplace_back(atof(axisData[0].c_str()));
y.emplace_back(atof(axisData[1].c_str()));
axisData.clear();
}
fileIn.close();
}
void GSTestMaplotlib::GetStringOfSub(std::string src, std::string splitStr, std::vector<std::string>& strVec, int isRFind)
{
if (isRFind == 0) //反向查找
{
int pos = src.rfind(splitStr);
if (pos != -1)
{
std::string dstStr = src.substr(pos, src.length() - 1);
strVec.emplace_back(dstStr);
std::string srcStr = src.substr(0, pos);
GetStringOfSub(srcStr, splitStr, strVec, isRFind);
}
else
{
strVec.emplace_back(src);
}
}
else
{
int pos = src.find(splitStr);
if (pos != -1)
{
std::string dstStr = src.substr(0, pos);
strVec.emplace_back(dstStr);
std::string srcStr = src.substr(pos + 1, src.length());
GetStringOfSub(srcStr, splitStr, strVec, isRFind);
}
else
{
strVec.emplace_back(src);
}
}
}