とりあえず、コッホ曲線を描いてみました、GDIで。

GDIによるコッホ曲線

ソースコードを載せておきます。C++です。

#include <windows.h>
#include <windowsx.h>
 
#include <math.h>
#ifdef _MSC_VER
#define hypot _hypot
#endif
 
void DrawKochCurveGDI(HDC hdc,
   double startX, double startY,
   double endX, double endY, int level)
{
    double dx = endX - startX;
    double dy = endY - startY;
    double trisectionLengthX = dx / 3.;
    double trisectionLengthY = dy / 3.;
    double triangleHeight = hypot(
        trisectionLengthX, trisectionLengthY) * 0.5 * sqrt(3.);
    double angle = atan2(dy, dx);
    double vertexX = startX + dx * 0.5 - triangleHeight * -sin(angle); //下向きがyの正の向きであることに注意
    double vertexY = startY + dy * 0.5 - triangleHeight * cos(angle);
    double mid1x = startX + trisectionLengthX;
    double mid1y = startY + trisectionLengthY;
    double mid2x = mid1x + trisectionLengthX;
    double mid2y = mid1y + trisectionLengthY;
    if (level == 0)
    {
        MoveToEx(hdc, static_cast<int>(startX), static_cast<int>(startY), 0);
        LineTo(hdc, static_cast<int>(mid1x), static_cast<int>(mid1y));
        LineTo(hdc, static_cast<int>(vertexX), static_cast<int>(vertexY));
        LineTo(hdc, static_cast<int>(mid2x), static_cast<int>(mid2y));
        LineTo(hdc, static_cast<int>(endX), static_cast<int>(endY));
    }
    else
    {
        level--;
        DrawKochCurveGDI(hdc, startX, startY, mid1x, mid1y, level);
        DrawKochCurveGDI(hdc, mid1x, mid1y, vertexX, vertexY, level);
        DrawKochCurveGDI(hdc, vertexX, vertexY, mid2x, mid2y, level);
        DrawKochCurveGDI(hdc, mid2x, mid2y, endX, endY, level);
    }
}
 
namespace
{
    HPEN const hpen = CreatePen(PS_SOLID, 2, RGB(0, 0, 0));
}
 
void OnPaint(HWND hwnd)
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    HGDIOBJ hpenOld = SelectObject(hdc, hpen);
    DrawKochCurveGDI(hdc, 10, 100, 300, 100, 3);
    SelectObject(hdc, hpenOld);
    EndPaint(hwnd, &ps);
}
 
void OnDestroy(HWND)
{
    DeleteObject(hpen);
    PostQuitMessage(0);
}
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
    switch (msg)
    {
        HANDLE_MSG(hwnd, WM_PAINT, OnPaint);
        HANDLE_MSG(hwnd, WM_DESTROY, OnDestroy);
    }
    return DefWindowProc(hwnd, msg, wp, lp);
}
 
int WINAPI WinMain(HINSTANCE hinst, HINSTANCE, PTSTR, int cmdShow)
{
    MSG msg;
    WNDCLASS wc;
 
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hinst;
    wc.hIcon = static_cast<HICON>(LoadImage(
        0, IDI_APPLICATION, IMAGE_ICON, 0, 0, LR_SHARED));
    wc.hCursor = static_cast<HCURSOR>(LoadImage(
        0, IDC_ARROW, IMAGE_CURSOR, 0, 0, LR_SHARED));
    wc.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
    wc.lpszMenuName = 0;
    wc.lpszClassName = TEXT("GDI Test");
    ATOM wncClassAtom = RegisterClass(&wc);
    if (!wncClassAtom)
        return 1;
 
    HWND hwnd = CreateWindow(
        reinterpret_cast<LPCTSTR>(static_cast<UINT_PTR>(wncClassAtom)),
        TEXT("GDI Test"), WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        0, 0,hinst, 0);
    if (!hwnd)
        return 1;
    ShowWindow(hwnd, cmdShow);
    UpdateWindow(hwnd);
 
    for (;;)
    {
        int ret = GetMessage(&msg, 0, 0, 0);
        if (ret == -1)
            return -1;
        else if (ret == 0)
            break;
 
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return static_cast<int>(msg.wParam);
}

HPENの扱いが雑なのは許してください。


スポンサード リンク

この記事のカテゴリ