您的位置:首页 > 健康 > 养生 > 网页个人信息页面_动态网站开发实训心得800字_危机公关处理方案_武汉网站推广

网页个人信息页面_动态网站开发实训心得800字_危机公关处理方案_武汉网站推广

2025/4/22 0:40:35 来源:https://blog.csdn.net/m0_50910915/article/details/147124338  浏览:    关键词:网页个人信息页面_动态网站开发实训心得800字_危机公关处理方案_武汉网站推广
网页个人信息页面_动态网站开发实训心得800字_危机公关处理方案_武汉网站推广

如何在C++项目中优雅地绘制图表

  • matplotlib
    • prepare
    • matplotlibcpp.h
    • python3
    • vs configure
    • test
  • Gnuplot
    • prepare
    • gnuplot
    • gnuplot-iostream.h
    • boost
    • vs configure
    • test
  • MathGL

在C++项目中,在进行一些数据分析时往往不够直观,若能借助图表进行分析可以达到事半功倍的效果,通常可以将数据写出到文本,再在excel或python上进行图表绘制和分析,那为什么不直接在像python一样,借助三方库进行图表绘制呢?以下将介绍简单易行的方法,尝试在C++中优雅地绘制图表(测试环境:Windows+VS2019)。


matplotlib

实际上是调用Python中的matplotlib提供的C++ API,无需编译,直接包含头文件然后在C++中配置相应python环境就可以,对于熟悉python的伙伴来说几乎没有学习成本(其本身语法也很简单)。

prepare

  1. 可访问github的网络
  2. git(非必须)
  3. python3(< 3.11)
  4. vs环境

matplotlibcpp.h

有git的直接clone到本地:

 git clone https://github.com/lava/matplotlib-cpp.git

没有git可以下载代码或者直接在线复制 matplotlibcpp.h

matplotlibcpp.h 作如下修改:

新版的matplotlibcpp.h中支持了C++17语法,将其改回C++11,且有重定义,需要注释。

将353行至356行代码用以下代码覆盖:

static_assert(sizeof(long long) == 8, "long type must occupy 8 bytes");
//template <> struct select_npy_type<long long> { const static NPY_TYPES type = NPY_INT64; };
static_assert(sizeof(unsigned long long) == 8, "long type must occupy 8 bytes");
//template <> struct select_npy_type<unsigned long long> { const static NPY_TYPES type = NPY_UINT64; };

python3

matplotlibcpp.h 语法与python3.11以上版本不兼容,报错如下:

1>matpoltlibTest.cpp
1>D:\Program Files\MatplotlibCpp\matplotlibcpp.h(174): error C4996: 'Py_SetProgramName': deprecated in 3.11
1>d:\programdata\anaconda3\include\pylifecycle.h(37): note: 参见“Py_SetProgramName”的声明
1>D:\Program Files\MatplotlibCpp\matplotlibcpp.h(182): error C4996: 'PySys_SetArgv': deprecated in 3.11
1>d:\programdata\anaconda3\include\sysmodule.h(13): note: 参见“PySys_SetArgv”的声明

使用3.11以下的python版本即可,这里我创建一个新的虚拟环境:

(base)>conda create -n Env310 python=3.10.16
(base)>conda activate Env310
(Env310)>conda install matplotlib numpy

将 复制到 D:\Program Files\MatplotlibCpp 下(非必须)。


vs configure

创建一个vs项目,切换为Release x64平台,在属性管理器的【Release | 64】下中新增一个属性表:

在这里插入图片描述
双击该属性表,开始配置:

【通用属性】-【VC++目录】-【包含目录】添加:

D:\Program Files\MatplotlibCpp
D:\ProgramData\anaconda3\envs\Env310\include
D:\ProgramData\anaconda3\envs\Env310\Lib\site-packages\numpy\_core\include

在这里插入图片描述
注意:不同版本的numpy包含目录所在路径可能不同,可通过以下代码确定:

import numpy
print(numpy.get_include())

【通用属性】-【VC++目录】-【库目录】添加:

D:\ProgramData\anaconda3\envs\Env310\libs

在这里插入图片描述
【通用属性】-【链接器】-【常规】-【附加库目录】添加:

D:\ProgramData\anaconda3\envs\Env310

在这里插入图片描述

【通用属性】-【链接器】-【输入】-【附加依赖项】添加:

python3.lib

在这里插入图片描述

保存属性表,在解决方案管理器中右击,更改属性:
【配置属性】-【调试】-【工作目录】更改为:

D:\ProgramData\anaconda3\envs\Env310

在这里插入图片描述

test

添加C++测试代码,如:

#include <cmath>
#include "matplotlibcpp.h"namespace plt = matplotlibcpp;#define M_PI 3.141592653589793238432643int main()
{// Prepare data.int n = 5000; // number of data pointsstd::vector<double> x(n), y(n);for (int i = 0; i < n; ++i){double t = 2 * M_PI * i / n;x.at(i) = 16 * sin(t) * sin(t) * sin(t);y.at(i) = 13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t);}// plot() takes an arbitrary number of (x,y,format)-triples.// x must be iterable (that is, anything providing begin(x) and end(x)),// y must either be callable (providing operator() const) or iterable.plt::plot(x, y, "r-", x, [](double d){return 12.5 + abs(sin(d));}, "k-");// show plotsplt::show();
}

运行,可得图片如下,配置完成。

在这里插入图片描述


Gnuplot

类似matplotlib,先安装gnuplot本体,然后通过C++API调用库,不同的是其可通过命令在终端中使用,需要一定学习成本。

prepare

  1. 可访问github的网络
  2. git(非必须)
  3. boost
  4. vs环境

gnuplot

在官网 可找到最新稳定版下载页面,下载编译好的二进制文件。

在这里插入图片描述
解压后长这个样子:
在这里插入图片描述
bin文件夹下双击打开gnupolt.exe,输入测试代码如下:

plot [-6:6] [-3:3] sin(x),cos(x)

可得:
在这里插入图片描述

将整个gunplot文件夹剪切至D:\Program Files\下,并重命名为Gnuplot(个人喜好),然后将D:\Program Files\Gnuplot\bin添加至系统环境变量Path中,通过重启或者其他方式确保环境变量生效(打开任意终端,输入gunplot未报错即可)。

在这里插入图片描述

那么同样可以在c++代码中调用该exe:

#include <stdio.h>void main()
{FILE* pipe = _popen("gnuplot", "w");if (pipe == NULL){exit(-1);}fprintf(pipe, "set terminal wxt size 600, 400\n");fprintf(pipe, "unset border\n");fprintf(pipe, "set dummy u, v\n");fprintf(pipe, "set angles degrees\n");fprintf(pipe, "set parametric\n");fprintf(pipe, "set view 60, 136, 1.22, 1.26\n");fprintf(pipe, "set samples 64, 64\n");fprintf(pipe, "set isosamples 13, 13\n");fprintf(pipe, "set mapping spherical\n");fprintf(pipe, "set style data lines\n");fprintf(pipe, "unset xtics\n");fprintf(pipe, "unset ytics\n");fprintf(pipe, "unset ztics\n");fprintf(pipe, "set title 'Labels colored by GeV plotted in spherical coordinate system'\n");fprintf(pipe, "set urange [ -90.0000 : 90.0000 ] noreverse nowriteback\n");fprintf(pipe, "set vrange [ 0.00000 : 360.000 ] noreverse nowriteback\n");fprintf(pipe, "set xrange [ * : * ] noreverse writeback\n");fprintf(pipe, "set x2range [ * : * ] noreverse writeback\n");fprintf(pipe, "set yrange [ * : * ] noreverse writeback\n");fprintf(pipe, "set y2range [ * : * ] noreverse writeback\n");fprintf(pipe, "set zrange [ * : * ] noreverse writeback\n");fprintf(pipe, "set cblabel 'GeV'\n");fprintf(pipe, "set cbrange [ 0.00000 : 8.00000 ] noreverse nowriteback\n");fprintf(pipe, "set rrange [ * : * ] noreverse writeback\n");fprintf(pipe, "set colorbox user\n");fprintf(pipe, "set colorbox vertical origin screen 0.9, 0.2 size screen 0.02, 0.75 front  noinvert bdefault\n");fprintf(pipe, "NO_ANIMATION = 1\n");fprintf(pipe, "splot cos(u)*cos(v),cos(u)*sin(v),sin(u) notitle with lines lt 5\n");fprintf(pipe, "pause mouse\n");_pclose(pipe);
}

结果如下:
在这里插入图片描述
但是,以这种方式,如果要批量绘制自定义的数据,仍需要先存数据为文本,然后再读取,这不是我想要的直接绘制的效果。但是不慌,再做一些简单配置就可以实现了。


gnuplot-iostream.h

有git的直接clone到本地

 git clone https://github.com/dstahlke/gnuplot-iostream.git

没有git可以下载代码或者直接在线复制 gnuplot-iostream.h

gnuplot-iostream.h 作如下修改

新版的gnuplot-iostream.h中支持了C++17语法,将其改回C++11,跟上面的matplotlibcpp.h是同样类型的改动

168-169行:

static_assert( is_like_stl_container<std::vector<int>>);
static_assert(!is_like_stl_container<int>);

改为:

static_assert(is_like_stl_container<std::vector<int>>, "Should be STL-like container");
static_assert(!is_like_stl_container<int>, "int is not STL-like container");

186行:

static_assert(is_boost_tuple_nulltype<boost::tuples::null_type>);

改为:

static_assert(is_boost_tuple_nulltype<boost::tuples::null_type>, "Should be boost null type");

197-200行:

static_assert( is_boost_tuple<boost::tuple<int>>);
static_assert( is_boost_tuple<boost::tuple<int, int>>);
static_assert(!is_boost_tuple<std::tuple<int>>);
static_assert(!is_boost_tuple<std::tuple<int, int>>);

改为:

static_assert(is_boost_tuple<boost::tuple<int>>, "Should be boost::tuple");
static_assert(is_boost_tuple<boost::tuple<int, int>>, "Should be boost::tuple");
static_assert(!is_boost_tuple<std::tuple<int>>, "std::tuple is not boost::tuple");
static_assert(!is_boost_tuple<std::tuple<int, int>>, "std::tuple is not boost::tuple");

2436-2437行

static_assert( is_eigen_matrix<Eigen::MatrixXf>);
static_assert(!is_eigen_matrix<int>);

改为

static_assert(is_eigen_matrix<Eigen::MatrixXf>, "Should be Eigen::Matrix");
static_assert(!is_eigen_matrix<int>, "int is not an Eigen::Matrix");

2442行

static_assert(dont_treat_as_stl_container<Eigen::MatrixXf>);

改为

static_assert(dont_treat_as_stl_container<Eigen::MatrixXf>, "Eigen::Matrix should not be treated as an STL container");

然后在上述gnuplot的安装目录D:\Program Files\Gnuplot下新建include文件夹,将改动后的gnuplot-iostream.h拷贝过去。

boost

由于gnuplot的C++调用需要boost支持,这里也介绍一下boost的配置,因为有预编译好的库,所以也比较easy。

在boost官网的下载页面找到预编译好的Windows库:

在这里插入图片描述
根据所需环境选择对应版本。

在这里插入图片描述

这里我根据自己的环境选择较早的1.80.0 VS140版(注意和自己的环境对应)。
在这里插入图片描述
双击运行:
在这里插入图片描述
更改安装目录:
在这里插入图片描述

在这里插入图片描述


vs configure

创建一个vs项目,切换为Release x64平台,在属性中将【平台工具集】改为Visual Studio 2015 (v140),在属性管理器的【Release | 64】下中新增一个属性表【Gnupolt_Release_x64.props】

双击该属性表,开始配置

【通用属性】-【VC++目录】-【包含目录】添加:

D:\Program Files\Gnuplot\include
D:\Program Files\boost_1_80_0\boost

【通用属性】-【VC++目录】-【库目录】添加:

D:\Program Files\boost_1_80_0\lib64-msvc-14.0

在这里插入图片描述

应用,保存属性表。


test

添加C++测试代码,如:


#include <cmath>
#include <vector>
#include <gnuplot-iostream.h>#define M_PI 3.141592653589793238432643int main()
{// 初始化 Gnuplot 对象Gnuplot gp;// 设置标题和样式gp << "set title 'Sharper Heart Shape'\n";gp << "set size ratio -1\n"; // 确保 x 和 y 轴比例一致gp << "set nokey\n";         // 不显示图例gp << "set samples 1000\n";  // 增加采样点使曲线更平滑gp << "set xrange [-20:20]\n"; // 设置 x 轴范围gp << "set yrange [-20:20]\n"; // 设置 y 轴范围// 定义参数化方程的数据点std::vector<std::pair<double, double>> points;const int num_points = 1000; // 数据点数量for (int i = 0; i <= num_points; ++i){double t = 2 * M_PI * i / num_points; // 参数 t 从 0 到 2πdouble x = 16 * pow(sin(t), 3);      // 使用新的 x 方程double y = (13 * cos(t) - 5 * cos(2 * t) - 2 * cos(3 * t) - cos(4 * t)); // 使用新的 y 方程points.emplace_back(x, y);}// 绘制爱心形状gp << "plot '-' with lines lc rgb 'red' lw 2 title 'Heart'\n";for (const auto& point : points){gp << point.first << " " << point.second << "\n";}gp << "e\n"; // 结束数据流return 0;
}

运行,可得图片如下,配置完成。
在这里插入图片描述


MathGL

需要特定的环境和复杂的配置,其发布的库也是Linux平台下的,在Windows需要和其他依赖库一起重新编译。

同样在官网找到最新版下载入口,这里有两个版本,我两个版本都下载并配置了,很不幸都在测试阶段报错了,要么缺少头文件要么缺依赖库。虽然可以拿源码自己重新cmake,但其需要依赖其他可视化库(背离了简单易行的初衷),本着世上无难事只要肯放弃的精神,暂停MathGL的测试。

在这里插入图片描述
测试代码:

#include <mgl2/mgl.h>int main()
{mglGraph gr;gr.SetRange('x', -1, 1);gr.SetRange('y', -1, 1);gr.Axis();gr.FPlot("sin(1.7*2*pi*x) + sin(1.9*2*pi*x)", "r-2");gr.WriteFrame("test.png");return 0;
}

mathgl-8.0.3-ucrt64 报错:

1>D:\Program Files\MathGL2\include\mgl2\data_cf.h(26,10): fatal error C1083: 无法打开包括文件: “gsl/gsl_vector.h”: No such file or directory

mathgl-8.0.3.LGPL-ucrt64 报错:

1>D:\Program Files\MathGL2\include\mgl2\data.h(27,10): fatal error C1083: 无法打开包括文件: “armadillo”: No such file or directory

打完收工。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com