65.9K
CodeProject 正在变化。 阅读更多。
Home

绘图图形库

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (66投票s)

2001年11月7日

LGPL3

6分钟阅读

viewsIcon

1451742

downloadIcon

51508

用于MFC项目中绘制数据(线条、地图等)的库

Snapshot

描述

PGL 是一个封装了绘图功能的库,适用于 MFC 项目,支持 VC6 和 VC7。它旨在无需任何外部软件即可轻松绘制项目中生成的数据。实际上,通过 CViewCDialog 派生类,您可以在 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 用于您项目的安装步骤

  1. 安装 GDI+(Microsoft SDK 的一部分)。
  2. 下载 Gdiplus.dll 并确保它在系统路径中。
  3. 重新编译源代码,将在 lib 目录中生成 .lib 文件,在 bin 目录中生成 .dll 文件。
  4. 将包含 PGL 二进制文件的目录添加到您的系统路径中(默认情况下是 C:\Program Files\PGL\bin)。
  5. include 目录和 lib 目录添加到 Visual C++ 的 include/lib 目录中。
  6. 确保头文件可用。

就是这样!

开始您的项目

  1. 在您的 StdAfx.h 文件中添加以下内容
    #include "PGL.h"
  2. 由于 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)。

Snapshot

以下是我用于生成数据的代码:一个简单的正弦曲线。请注意,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;
}
  1. 首先,创建一个图表对象
    CPGLGraph* pGraph = new CPGLGraph;
    请注意,由于所有 PGL 对象都继承自 CObject,您可以使用 ASSERT_VALID 来检查它们。
  2. 创建一个 2D 线条

    CPGLLine2D* pLine = new CPGLLine2D;
  3. 将数据附加到线条上。PGL 将在此之后处理内存。也就是说,它将在对象销毁时删除数据指针。这意味着 pX,pY 必须在堆上分配!

    pLine->SetDatas( nPoints /* number of points */, 
                       pX /* x(i) */, pY /* y(i) */);
  4. (可选)更改线条的某些属性:pLine->SetLineWidth(2);

  5. 将线条添加到图表中(请注意,一个对象只能添加到一个图表中)
    pGraph->AddObject(pLine);
  6. PGL 自动缩放绘图

    pGraph->ZoomAll();
  7. 创建一个对话框并显示绘图

    CPGLGraphBitDlg graphdlg(this, pGraph);
    graphdlg.DoModal();

您应该会看到与上面图像相同的结果。请注意,这张图像(PNG)是由 PGL 生成的。

示例 2:添加具有细节层次控制的线条

您可能需要绘制包含数千个点的线条。这可能会变得非常耗费资源,特别是当您将其导出为 EPS 时,文件可能会变得非常大。为了解决这个问题,您可以使用 PGL 中内置的带 LOD 的线条。

Snapshot

在此示例中,我们近似了上一条线。从上一个示例开始

  1. 更改代码行
    CPGLLine2D* pLine = new CPGLLine2D;

    to

    CPGLLine2DLOD* pLine = new CPGLLine2DLOD;
  2. 更改细节层次的容差
    pLine->SetTol(0.05);
  3. 按所需的压缩比缩小点的数量(此处为 10% 阈值为 2%)
    pLine->ShrinkNorm(0.1,0.02);

在上图所示的图像中,您可以看到原始线和近似线。使用这种技术可以大大减少点的数量!

示例 3:自定义坐标轴、标签等

如上一张图像所示,对象的所有参数都可以通过代码进行更改。在此示例中,我们将

  • 更改标题文本,
  • 关闭水平网格,
  • 显示右侧标签,
  • 更改顶部坐标轴刻度的数量,
  • 切换到 x 轴的时间标签,
  • 以及更多...

Snapshot

我们从第二个示例开始,在调用 ZoomAll() 之前添加以下代码行。

  1. 获取坐标轴对象的指针(英文中有一个巨大的错误,但在法语中是正确的:(axe -> axis))
    CPGLAxe2D* pAxis = pGraph-&gtGetAxe();
  2. 更改标题文本和颜色
    pAxis->SetTitle(str);
    pAxis->GetTitle()->SetString(str);
    pAxis->GetTitle()->SetColor(0 /* red */,0.5f /* green */,
                                0 /* blue*/ /* alpha optional */);
  3. 关闭垂直网格(垂直 -> 0,水平 -> 1)
    pAxis->SetShowGrid(1,FALSE);
  4. 显示并更改右侧标签
    pAxis->GetRightLabel()-&gtShow(TRUE);
    pAxis->GetRightLabel()-&gtSetString("This is the right label");
  5. 显示右侧编号
    pAxis->GetRightNumber()->Show();
  6. 更改顶部坐标轴刻度的数量
    pAxis->SetTopSecondTicksNb(5);
  7. 切换到 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 中有多种方式实现。事实上,您可以将绘图添加到绘图中,依此类推。

Snapshot

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:在运行时更改对象属性

您可以通过右键单击视图或对话框来探索对象层次结构。不幸的是,序列化尚未实现。所以之前的努力都白费了...

Snapshot

参考

文档是使用 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。算法类集合。此项目包含线近似算法。
  • IGfxPGL 使用的图形库。多层图形接口,可导出为多种图形格式,如 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 日:初始发布。
© . All rights reserved.