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

在 Pocket PC 上绘制三次贝塞尔样条

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.50/5 (6投票s)

2005年3月16日

CPOL

2分钟阅读

viewsIcon

59156

downloadIcon

379

用于在 Pocket PC 上绘制贝塞尔曲线的函数。因为它们在 Pocket PC 的 GDI 中缺失。

BezierCETest application.

引言

当我开始为 Pocket PC 编写 CAD 应用程序时,我很快发现 Pocket PC 上的 GDI 与普通的 Windows GDI 相比有所限制。我需要绘制样条曲线。因此,我尝试在网上找到一个简单易用的算法,但没有找到有用的东西。

我查找了有关贝塞尔曲线的信息,因为 Windows 上的 GDI 使用的是贝塞尔曲线,我想要一个替代函数。在阅读了 Donald HernM. Pauline baker 的书 计算机图形学 之后,我理解了贝塞尔曲线的工作原理。

那么它是如何工作的?

提供的代码使用三次贝塞尔曲线,它接受四个控制点,并使用四个混合函数生成曲线

  • f1(u) = (1 - u)³
  • f2(u) = 3u(1 - u)²
  • f3(u) = 3u²(1 - u)
  • f4(u) = u³

其中 0 <= u <= 1

下面显示了计算曲线上点的函数。fPoint 只是一个 struct,包含两个 float 类型的数据 xy。将混合函数与控制点相乘,然后加到 pDstPoint 上。

void BezierComputePoint(float fU, fPoint* pDstPoint, CPoint* pSrcPoints)
{
    //
    //    Add up all the blending functions multiplied with the control points
    //
    float fBlend;
    float f1subu = 1.0f - fU;

    //
    //    First blending function (1-u)^3
    //
    fBlend = f1subu * f1subu * f1subu;
    pDstPoint->x = fBlend * pSrcPoints[0].x;
    pDstPoint->y = fBlend * pSrcPoints[0].y;

    //
    //    Second blending function 3u(1-u)^2
    //
    fBlend = 3 * fU * f1subu * f1subu;
    pDstPoint->x += fBlend * pSrcPoints[1].x;
    pDstPoint->y += fBlend * pSrcPoints[1].y;

    //
    //    Third blending function 3u^2 * (1-u)
    //
    fBlend = 3 * fU * fU * f1subu;
    pDstPoint->x += fBlend * pSrcPoints[2].x;
    pDstPoint->y += fBlend * pSrcPoints[2].y;

    //
    //    Fourth blending function u^3
    //
    fBlend = fU * fU * fU;
    pDstPoint->x += fBlend * pSrcPoints[3].x;
    pDstPoint->y += fBlend * pSrcPoints[3].y;
}

下一个代码片段显示了 DrawBezier 函数。它接受一个 CDC 指针作为输入,四个控制点以及样条曲线应被分割成的段数。您使用的段数越多,结果越好,但这会花费更多的时间。因此,最好进行实验以获得最佳结果。

遍历所有段,生成曲线上一个点。在先前点和计算出的点之间绘制一条线。最后,绘制一条线到终点。

void DrawBezier(CDC *pDC, CPoint *pPoints, int nSegments)
{
    pDC->MoveTo(pPoints[0]);
    fPoint fPointBezier;
    for(int i = 0; i < nSegments; i++)
    {
        BezierComputePoint(i / (float)nSegments, &fPointBezier, pPoints);
        pDC->LineTo(ROUND(fPointBezier.x), ROUND(fPointBezier.y));
    }
    pDC->LineTo(pPoints[3]);
}

使用代码

在您的项目中包含 Bezier.h 并调用这些函数。请查看示例项目以获取提示。我使用 PPC 2003 进行测试,但它不应该与旧的 PPC SDK 存在问题。

就这样!希望对您有所帮助。欢迎提出评论和建设性的批评。

历史

2005-03-15 - 首次发布。

© . All rights reserved.