用 C++ 和 libgd 来绘图
[TOC]
旧文转贴, 代码很久以前写的, 大约至今有十年了, 最近看到有人问如何用 C++ 来生成图表.
有一个 graphviz 的开源库可以用, 它用了自己的领域特定语言 DSL: dot 来生成图表, 具体应用可见 http://graphviz.org/
当然也可以不用这么重的开源库, 这里介绍了以前写的一个chart 库, 几百行代码, 采用了比较原始的作法, 调用了 libgd 基础API, 如画点, 画线等原子方法来绘制图表, 可以应用于一些比较简单的场合
实例
先看看生成的图表实例
折线图和鱼骨头图
圆饼图和直方图
示例代码
上面两个图表由以下几十行代码来实现
#include "TinyUtil.h"
#include "TinyChart.h"
#include
#include
#include
#include
int main(int argc, char **argv)
{
printf("-- write image by gd ---");
{
STR_VEC xScales;
xScales.reserve(10);
xScales.push_back("11-09");
xScales.push_back("11-10");
xScales.push_back("11-11");
xScales.push_back("11-12");
xScales.push_back("11-13");
xScales.push_back("11-14");
xScales.push_back("11-15");
xScales.push_back("11-16");
xScales.push_back("11-17");
xScales.push_back("11-18");
xScales.push_back("11-19");
xScales.push_back("11-20");
xScales.push_back("11-21");
xScales.push_back("11-22");
INT_VEC yScales;
yScales.reserve(10);
yScales.push_back(200);
yScales.push_back(130);
yScales.push_back(3456);
yScales.push_back(2345);
yScales.push_back(1320);
yScales.push_back(30);
yScales.push_back(2200);
yScales.push_back(1330);
yScales.push_back(3330);
yScales.push_back(332);
yScales.push_back(788);
yScales.push_back(200);
yScales.push_back(13890);
yScales.push_back(200);
TinyTrendlineDiagram* pt = new TinyTrendlineDiagram(
"latency_trendline.png", 800, 250);
pt->SetTitle("Trend of Latency (the middle network latency is the value of 0 coordinate)");
pt->SetLabels(xScales);
pt->SetValues(yScales);
pt->Draw();
pt->WriteImage();
delete pt;
}
{
STR_VEC xScales;
xScales.push_back("America");
xScales.push_back("China");
xScales.push_back("Japan");
xScales.push_back("England");
xScales.push_back("France");
xScales.push_back("Germany");
xScales.push_back("South Korean");
xScales.push_back("India");
INT_VEC yScales;
yScales.push_back(4800);
yScales.push_back(3008);
yScales.push_back(100);
yScales.push_back(20);
yScales.push_back(2000);
yScales.push_back(178);
yScales.push_back(258);
yScales.push_back(1789);
TinyDistributionDiagram* pd = new TinyDistributionDiagram(
"users_distribution.png", 800, 600);
pd->SetTitle("Daily active users distribution among the countries");
pd->SetLabels(xScales);
pd->SetValues(yScales);
pd->Draw();
pd->WriteImage();
delete pd;
}
return 0;
}
�设计与实现
其实, 也就是封装了libgd 的原子操作, 绘制了基本的图形单元
�1) 首先下载并编译依赖库 libgd
- 下载: Download libgd-2.2.1.tar.gz
- 解压: tar xvfz libgd-2.2.1.tar.gz
- 构建步骤 build steps
cd libgd-2.2.1
mkdir bld
cd bld
cmake -DENABLE_PNG=1 -DENABLE_JPEG=1 -DENABLE_FREETYPE=1 ..
make
make install
- 然后实现上图所示的类, 加上测试, 约有千余行代码, 放在 github 里
https://gist.github.com/walterfan/b7200fd3e5315ec1e16551fca096a67e
附以上类图的源码, 由 http://yuml.me 生成
// Cool Class Diagram
[Sharp]^[Arc]
[Arc]^[Eclipse]
[Arc]^[Circle]
[Sharp]^[Rectangle]
[Sharp]^[Scale]
[Sharp]^[Chart]
[Chart]^[CurveChart]
[Chart]^[ColumnChart]
[Chart]^[PieChart]
[Chart]^[HistogramChart]
[Diagram]-[note:Aggregate chart{bg:wheat}]
[Diagram]^[DistributionDiagram]
[Diagram]^[TrendlineDiagram]
[TrendlineDiagram]<>-0..*>[CurveChart]
[TrendlineDiagram]<>-0..*>[ColumnChart]
[DistributionDiagram]<>-0..*>[PieChart]
[DistributionDiagram]<>-0..*>[HistogramChart]
接口如下, 代码比较老, 欢迎指正
#include
#include
#include
#include