25-三次Beizer曲线算法

参考:https://www.bilibili.com/video/BV1ud4y1C7iA

1.Bernstrin基函数算法

    void DrawCurve1(HDC hdc)    // 基函数绘制曲线
    {
        MoveToEx(hdc, ROUND(P[0].x), ROUND(P[0].y), NULL);
        double tStep = 0.01;
        for (double t = 0; t <= 1; t += tStep)
        {
            double B03 = (1 - t) * (1 - t) * (1 - t);
            double B13 = 3 * t * (1 - t) * (1 - t);
            double B23 = 3 * t * t * (1 - t) ;
            double B33 = t * t * t;
            Point2 pt = B03 * P[0] + B13 * P[1] + B23 * P[2] + B33 * P[3];
            LineTo(hdc,ROUND(pt.x),ROUND(pt.y));
        }
    }

2.de Casteljau 递推算法

    void DrawCurve(HDC hdc)    // de Casteljau 递推算法
    {
        MoveToEx(hdc, ROUND(P[0].x), ROUND(P[0].y), NULL);
        double tStep = 0.01;
        for (double t = 0; t <= 1; t += tStep)
        {
            Point2 p0, p1, p2, p3, p4, p5;
            p0 = (1 - t) * P[0] + t * P[1];
            p1 = (1 - t) * P[1] + t * P[2];
            p2 = (1 - t) * P[2] + t * P[3];
            p3 = (1 - t) * p0 + t * p1;
            p4 = (1 - t) * p1 + t * p2;
            p5 = (1 - t) * p3 + t * p4;
            LineTo(hdc, ROUND(p5.x), ROUND(p5.y));
        }
    }

完成代码

// 25-三次Beizer曲线算法
// 参考 https://www.bilibili.com/video/BV1ud4y1C7iA

#define UNICODE
#include <Windows.h>
#include <Windowsx.h>
#include <math.h>
#define WINDOW_TEXT L"25-三次Beizer曲线算法"
#define ROUND(d) int(floor(d)+0.5)  // 四舍五入
#define PI        3.1415926

struct Point2  // 二维点
{
    double x;
    double y;
    double w;  // 齐次坐标
    Point2() :x(0), y(0), w(0) {}
    Point2(double x, double y) :x(x), y(y), w(0) {}

    friend Point2 operator + (Point2 pt0, Point2 pt1 )
    {
        return  Point2(pt0.x + pt1.x, pt0.y + pt1.y);
    }

    friend Point2 operator * (Point2 pt, double n)
    {
        return  Point2(pt.x * n, pt.y * n);
    }

    friend Point2 operator * ( double n, Point2 pt)
    {
        return  Point2(pt.x * n, pt.y * n);
    }
};

class CubicBezierCurve
{
public:
    Point2 P[4];              // 控制点数组
public:
    CubicBezierCurve(){}
    ~CubicBezierCurve(){}
    void ReadPoint(Point2 * p) // 读入控制点
    {
        for (int nPoint = 0; nPoint < 4; nPoint++)
        {
            P[nPoint] = p[nPoint];
        }
    }
    void DrawCurve1(HDC hdc)    // 基函数绘制曲线
    {
        MoveToEx(hdc, ROUND(P[0].x), ROUND(P[0].y), NULL);
        double tStep = 0.01;
        for (double t = 0; t <= 1; t += tStep)
        {
            double B03 = (1 - t) * (1 - t) * (1 - t);
            double B13 = 3 * t * (1 - t) * (1 - t);
            double B23 = 3 * t * t * (1 - t) ;
            double B33 = t * t * t;
            Point2 pt = B03 * P[0] + B13 * P[1] + B23 * P[2] + B33 * P[3];
            LineTo(hdc,ROUND(pt.x),ROUND(pt.y));
        }
    }
    void DrawCurve(HDC hdc)    // de Casteljau 递推算法
    {
        MoveToEx(hdc, ROUND(P[0].x), ROUND(P[0].y), NULL);
        double tStep = 0.01;
        for (double t = 0; t <= 1; t += tStep)
        {
            Point2 p0, p1, p2, p3, p4, p5;
            p0 = (1 - t) * P[0] + t * P[1];
            p1 = (1 - t) * P[1] + t * P[2];
            p2 = (1 - t) * P[2] + t * P[3];
            p3 = (1 - t) * p0 + t * p1;
            p4 = (1 - t) * p1 + t * p2;
            p5 = (1 - t) * p3 + t * p4;
            LineTo(hdc, ROUND(p5.x), ROUND(p5.y));
        }
    }

    void DrawPolygon(HDC hdc)  // 绘制控制多边形
    {
        HPEN newPen=CreatePen(PS_SOLID,3,RGB(0,0,180));
        HGLOBAL oldPen=SelectObject(hdc,newPen);
        MoveToEx(hdc, ROUND(P[0].x), ROUND(P[0].y), NULL);
        Ellipse(hdc, ROUND(P[0].x)-5, ROUND(P[0].y) - 5, ROUND(P[0].x) + 5, ROUND(P[0].y) + 5);
        for (int i = 0; i < 4; i++)
        {
            LineTo(hdc, ROUND(P[i].x) , ROUND(P[i].y));
            Ellipse(hdc, ROUND(P[i].x) - 5, ROUND(P[i].y) - 5, ROUND(P[i].x) + 5, ROUND(P[i].y) + 5);
        }

        SelectObject(hdc, oldPen);
        DeletePen(newPen);
    }
};

static bool     m_Play = false;
static wchar_t* m_str = L"";

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT rect;
    static double alpha;
    static double beta;

    switch (uMsg)
    {
    case WM_TIMER:
        alpha += 1;
        beta += 1;
        InvalidateRect(hwnd, NULL, FALSE);
        return 0;

    case WM_LBUTTONDOWN:
        m_Play = !m_Play;
        if (m_Play)
        {
            SetTimer(hwnd, 0, 0, NULL);
        }
        else
        {
            KillTimer(hwnd, 0);
        }
        return 0;

    case WM_PAINT:
    {
        hdc = BeginPaint(hwnd, &ps);
        GetClientRect(hwnd, &rect);

        SetMapMode(hdc, MM_ANISOTROPIC);
        SetWindowExtEx(hdc, rect.right, rect.bottom, NULL);
        SetViewportExtEx(hdc, rect.right, -rect.bottom, NULL);
        SetViewportOrgEx(hdc, rect.right / 2, rect.bottom / 2, NULL);

        // 内存DC
        HDC     memDC = CreateCompatibleDC(hdc);                                   // 创建兼容DC 画板
        HBITMAP newBitmap = CreateCompatibleBitmap(hdc, rect.right, rect.bottom);  // 创建画布
        HGDIOBJ oldBitmap = SelectObject(memDC, newBitmap);                        // 将画布选入画板
        FillRect(memDC, &rect, (HBRUSH)(COLOR_WINDOW + 1));
        DrawText(memDC, m_str, wcslen(m_str), &rect, NULL);

        SetMapMode(memDC, MM_ANISOTROPIC);
        SetWindowExtEx(memDC, rect.right, rect.bottom, NULL);
        SetViewportExtEx(memDC, rect.right, -rect.bottom, NULL);
        SetViewportOrgEx(memDC, rect.right / 2, rect.bottom / 2, NULL);

        // 绘制图形
        {
            Point2 P[4] =
            {
                Point2(-300, -300),
                Point2(-200,  100),
                Point2( 300,  250),
                Point2( 400, -200),
            };

            CubicBezierCurve bezier;    // 贝塞尔曲线

            bezier.ReadPoint(P);          // 读取控制点
            bezier.DrawPolygon(memDC);    // 绘制控制线
           // bezier.DrawCurve(memDC);    // de Casteljau 递推算法
            bezier.DrawCurve1(memDC);     // 基函数绘制曲线

        }

        // 内存dc复制到设备
        BitBlt(hdc, ROUND(-rect.right / 2), ROUND(-rect.bottom / 2), rect.right, rect.bottom, memDC, ROUND(-rect.right / 2), ROUND(-rect.bottom / 2), SRCCOPY);

        SelectObject(memDC, oldBitmap);

        DeleteObject(newBitmap);
        DeleteDC(memDC);

        EndPaint(hwnd, &ps);
    }
    return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    // Register the window class.
    const wchar_t CLASS_NAME[] = L"CAG";
    WNDCLASS wc = { };

    wc.style = CS_HREDRAW | CS_VREDRAW; // 重新绘制整个工作区
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    RegisterClass(&wc);

    HWND hwnd = CreateWindowEx(
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class
        WINDOW_TEXT,                    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
    );

    if (hwnd == NULL)
    {
        return 0;
    }
    ShowWindow(hwnd, nCmdShow);
    MSG msg = { };
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值