绘图图形库






4.95/5 (66投票s)
用于MFC项目中绘制数据(线条、地图等)的库
描述
PGL
是一个封装了绘图功能的库,适用于 MFC 项目,支持 VC6 和 VC7。它旨在无需任何外部软件即可轻松绘制项目中生成的数据。实际上,通过 CView
和 CDialog
派生类,您可以在 5 分钟内让您的应用程序显示图表。
PGL
的目标不是提供一个用户友好的环境,而是能够从源代码生成任何绘图。
PGL
最初使用 OpenGL
进行光栅图形渲染,但现在它使用 GDI+
(因此您需要安装 Microsoft SDK 才能编译 PGL
)。
许可
CodeProject 上的源代码根据 LGPL 许可。但是,后续版本将不再免费(哎呀,抱歉)。您可以在 PGL 官方主页 查看最新开发动态。无论如何,请享受精美的图表绘制。
特点
- 线带,完全可定制
- 颜色 (RGBA)
- 线型
- 点类型(圆圈、方框、三角形等)
- 线宽
- 填充
- 线阴影
- 多条线带
- 等等。
- 具有细节层次 (LOD) 功能的线带(基于 Douglas-Peukler 线简化算法)
- 矢量地图
- 高度图
- 文本
- 可变刻度
- 多种字体
- 方向可调
- 无限子图
- 自动坐标轴
- 时间标签
- 导出为 EPS, SVG, JPEG, TIFF, PNG
- 用于快速集成到现有项目的
CView
派生类 CDialog
派生类等。
UML
UML 图可在此 PDF 文件 中找到。虽然不完整,但应该有助于您理解该库。
安装
以下是将 PGL
用于您项目的安装步骤
- 安装
GDI+
(Microsoft SDK 的一部分)。 - 下载 Gdiplus.dll 并确保它在系统路径中。
- 重新编译源代码,将在 lib 目录中生成 .lib 文件,在 bin 目录中生成 .dll 文件。
- 将包含
PGL
二进制文件的目录添加到您的系统路径中(默认情况下是 C:\Program Files\PGL\bin)。 - 将 include 目录和 lib 目录添加到 Visual C++ 的 include/lib 目录中。
- 确保头文件可用。
就是这样!
开始您的项目
- 在您的 StdAfx.h 文件中添加以下内容
#include "PGL.h"
-
由于
PGL
使用GDI+
,您必须初始化它- 在您的
CWinApp
派生类中添加以下变量ULONG_PTR m_ulGdiplusToken;
- 在
CWinApp::OnInitInstance
函数中添加以下内容以初始化GDI+
// initialize <code>GDI+ (gdi+ is in Gdiplus namespace) Gdiplus::GdiplusStartupInput gdiplusStartupInput; Gdiplus::GdiplusStartup(&m_ulGdiplusToken, &gdiplusStartupInput, NULL);
- 在
CWinApp::OnExitInstance
函数中添加以下内容以清理GDI+
。// shutdown GDI+ Gdiplus::GdiplusShutdown(m_ulGdiplusToken);
- 在您的
您的项目现在应该可以正常工作了。
示例
所有这些示例都可以在源代码中找到。请参阅 TestPGL
的示例菜单。
示例 1:绘制简单线条
这是一个第一个解释性示例。我们假设线条的点 (x,y) 已经生成并存储在大小为 nPoints
的两个数组 pX,pY
中(请注意,您也可以将数据作为 std::vector<double>
传递给 PGL
)。
以下是我用于生成数据的代码:一个简单的正弦曲线。请注意,y
的范围在 [-1.1, 1.1]
之间,但 PGL
会自动处理坐标轴标签,使其具有良好的单位。
// generate data
int nPoints = 50;
double* pX=new double[nPoints];
double* pY=new double[nPoints];
for (UINT i=0;i< nPoints;i++)
{
pX[i]=i;
pY[i]=sin(i/(double)nPoints*2*3.14)*1.1;
}
- 首先,创建一个图表对象
CPGLGraph* pGraph = new CPGLGraph;
请注意,由于所有PGL
对象都继承自CObject
,您可以使用ASSERT_VALID
来检查它们。 -
创建一个 2D 线条
CPGLLine2D* pLine = new CPGLLine2D;
-
将数据附加到线条上。
PGL
将在此之后处理内存。也就是说,它将在对象销毁时删除数据指针。这意味着pX,pY
必须在堆上分配!pLine->SetDatas( nPoints /* number of points */, pX /* x(i) */, pY /* y(i) */);
-
(可选)更改线条的某些属性:
pLine->SetLineWidth(2)
; - 将线条添加到图表中(请注意,一个对象只能添加到一个图表中)
pGraph->AddObject(pLine);
-
让
PGL
自动缩放绘图pGraph->ZoomAll();
-
创建一个对话框并显示绘图
CPGLGraphBitDlg graphdlg(this, pGraph); graphdlg.DoModal();
您应该会看到与上面图像相同的结果。请注意,这张图像(PNG)是由 PGL
生成的。
示例 2:添加具有细节层次控制的线条
您可能需要绘制包含数千个点的线条。这可能会变得非常耗费资源,特别是当您将其导出为 EPS 时,文件可能会变得非常大。为了解决这个问题,您可以使用 PGL
中内置的带 LOD 的线条。
在此示例中,我们近似了上一条线。从上一个示例开始
- 更改代码行
CPGLLine2D* pLine = new CPGLLine2D;
to
CPGLLine2DLOD* pLine = new CPGLLine2DLOD;
- 更改细节层次的容差
pLine->SetTol(0.05);
- 按所需的压缩比缩小点的数量(此处为 10% 阈值为 2%)
pLine->ShrinkNorm(0.1,0.02);
在上图所示的图像中,您可以看到原始线和近似线。使用这种技术可以大大减少点的数量!
示例 3:自定义坐标轴、标签等
如上一张图像所示,对象的所有参数都可以通过代码进行更改。在此示例中,我们将
- 更改标题文本,
- 关闭水平网格,
- 显示右侧标签,
- 更改顶部坐标轴刻度的数量,
- 切换到 x 轴的时间标签,
- 以及更多...
我们从第二个示例开始,在调用 ZoomAll()
之前添加以下代码行。
- 获取坐标轴对象的指针(英文中有一个巨大的错误,但在法语中是正确的:(axe -> axis))
CPGLAxe2D* pAxis = pGraph->GetAxe();
- 更改标题文本和颜色
pAxis->SetTitle(str);
或pAxis->GetTitle()->SetString(str);
pAxis->GetTitle()->SetColor(0 /* red */,0.5f /* green */, 0 /* blue*/ /* alpha optional */);
- 关闭垂直网格(垂直 -> 0,水平 -> 1)
pAxis->SetShowGrid(1,FALSE);
- 显示并更改右侧标签
pAxis->GetRightLabel()->Show(TRUE); pAxis->GetRightLabel()->SetString("This is the right label");
- 显示右侧编号
pAxis->GetRightNumber()->Show();
- 更改顶部坐标轴刻度的数量
pAxis->SetTopSecondTicksNb(5);
- 切换到 x 轴的时间标签
// enable time labelling pAxis->SetTimeLabel(TRUE); // set origin, time step and format (see COleDateTime.Format for details) pAxis->SetTimeLabelFormat(COleDateTime::GetCurrentTime() /* Time at zero. */, COleDateTimeSpan(0,0,30,0) /* Time per unit */, "%H:%M:%S" /* String format */);
我还禁用了线条绘制,并将 LOD 线条的容差设置为 0.025。当然,您可以做得更多。这只是一个示例。
示例 4:子图!
如何在图形上放置多个绘图:这在 PGL
中有多种方式实现。事实上,您可以将绘图添加到绘图中,依此类推。
类 CPGLGraph
继承自一个通用的绘图类:CPGLRegion
。您可以
- 使用函数
Divide(m,n)
将区域分割成 m 行 n 列的数组(注意此方法会擦除区域中的所有对象)。之后,您可以通过GetChilds(i)
访问子区域(子区域按行创建)。您可以使用GetNChilds()
获取子区域的数量。// allocated somewhere CPGLRegion* pRegion; // dividing pRegion->Divide(m,n); // accessing region at row 2 and column 1 (zero based index) CPGLRegion* pChildRegion = pRegion->GetChild(2*n+1);
- 直接创建并添加一个区域,使用
AddRegion
。要使用此方法,您必须调用SetNormBBox(...)
来设置边界框(以父区域的归一化坐标表示)。CPGLRegion* pChildRegion = pRegion->AddRegion(); pChildRegion->SetNormBBox(0.1 /* llx */ , 0.2 /* lly */ , 0.7 /* urx */ , 0.8 /* ury */);
当然,您可以分割子区域,依此类推。
示例 5:在运行时更改对象属性
您可以通过右键单击视图或对话框来探索对象层次结构。不幸的是,序列化尚未实现。所以之前的努力都白费了...
参考
文档是使用 Doxygen 和 Doxygen Studio 生成的。请参阅 Plot Graphic Library.dow 文件。否则,它会与 Microsoft Installer 一起提供。
下载
您可以在 PGL 官方主页 下载 Microsoft Installer。
编译源代码
提供了 PGL
的源代码。打开工作区
- 对于 VC6 用户,请打开 "Plot Graphic Library.dsw"
- 对于 VC7 用户,请打开 "Plot Graphic LibraryNET.dsw"
它包含 6 个项目
AlgoTools
。算法类集合。此项目包含线近似算法。IGfx
。PGL
使用的图形库。多层图形接口,可导出为多种图形格式,如 EPS 或 SVG。IGfxTest
。IGfx 的测试项目。OGLTools
。用于在 Windows 中处理 OpenGL 的有用库。不再使用,但仍然有用。PGL
。图形库。Testpgl
。一个演示应用程序。
编译源代码。.lib 文件将位于 lib 目录中,DLL 文件将位于 bin 目录中。
历史
- 2002 年 11 月 6 日:添加了 VC7 构建,修复了一些问题并更新了
DPHull
。 - 2002 年 7 月 15 日:修复了资源缺失问题,将
CP_THREAD_ACP
更改为CP_ASP
,修复了导出错误和文本条错误。 - 2002 年 6 月 5 日:更新了下载。
- 2002 年 3 月 29 日:重大更新!
- 2001 年 11 月 8 日:初始发布。