ベジェ曲線
パラメトリック曲線
さて、さらに自由な図をプログラムで表現するには曲線を扱う必要があります
Windowsでは、プログラムから自由に曲線を表現できるファンクションを用意しているのです
CGクリエイターやグラフィックシステムプログラマであれば
ある程度ベジェ曲線についてはご存知でしょう
しかし、グラフィカル操作になれないプログラマは馴染みがないかもしれません
WindowsはOSレベルでベジェ曲線をサポートしています
これは、CGで用いられる曲線手法の一つでいくつかの座標から曲線を表現します
//たとえば、4つの点から描画するベジェ曲線は「3次ベジェ曲線」と呼ぶ
このようなパラメータから表現する曲線をパラメトリック曲線と呼ぶこともあります
ベジェ曲線の数式を考えたのはPierre Bezier氏という人物で
他のプラットフォームなどでベジェをサポートする場合、数式を調べるのも面白いかもしれません
高度なグラフィックプログラマを目指すなら、数式も知っておいて損はありません
ベジェ曲線を描くにはPolyBezierTo()を用います
このファンクションは、カレントポジションの影響を受けます
BOOL PolyBezierTo(HDC hdc , CONST POINT *lppt , DWORD cCount);
hdcには、デバイスコンテキストのハンドルを
lpptには、ベジェ曲線の制御点を表すPOINT構造体へのポインタを
cCountは、lpptの制御点の個数を指定します
複数のベジェ曲線を同じに描画することも可能です
その場合はcCountの数値は常に曲線の数×3になります
関数が成功すれば0以外、失敗すれば0の値が返ります
制御点は常に4つで、最初の制御点はカレントポジションになります
#include <windows.h>
LRESULT CALLBACK WndProc(HWND hwnd , UINT msg , WPARAM wp , LPARAM lp) {
HDC hdc;
PAINTSTRUCT ps;
static POINT pt[3];
switch (msg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CREATE:
pt[0].x = 100;
pt[0].y = 400;
pt[1].x = 200;
pt[1].y = 400;
pt[2].x = 300;
pt[2].y = 10;
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd , &ps);
MoveToEx(hdc , 0 , 10 , NULL);
PolyBezierTo(hdc , pt , 3);
MoveToEx(hdc , 0 , 10 , NULL);
PolylineTo(hdc , pt , 3);
EndPaint(hwnd , &ps);
return 0;
}
return DefWindowProc(hwnd , msg , wp , lp);
}
int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE hPrevInstance ,
PSTR lpCmdLine , int nCmdShow ) {
HWND hwnd;
MSG msg;
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL , IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL , IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("KITTY");
if (!RegisterClass(&winc)) return -1;
hwnd = CreateWindow(
TEXT("KITTY") , TEXT("Kitty on your lap") ,
WS_OVERLAPPEDWINDOW | WS_VISIBLE ,
CW_USEDEFAULT , CW_USEDEFAULT ,
CW_USEDEFAULT , CW_USEDEFAULT ,
NULL , NULL , hInstance , NULL
);
if (hwnd == NULL) return -1;
while(GetMessage(&msg , NULL , 0 , 0)) DispatchMessage(&msg);
return msg.wParam;
}

上の放物線がPolyBezierTo()で描いたベジェ曲線です
直線は、PolylineTo()で描画したベジェ曲線の制御点を結ぶ線です
ベジェ曲線と制御点の関係が、なんとなくわかっていただけたと思います
ちなみに、カレントポジションの影響を受けないPolyBezier()もあります
PolyBezierTo()
BOOL PolyBezierTo(HDC hdc , CONST POINT *lppt , DWORD cCount);
一つ以上のベジェ曲線を描画します
開始点はカレントポジションを使用し
最後に描画したベジェ曲線の終了点にカレントポジションを設定します
hdc - デバイスコンテキストのハンドルを指定します
lppt - 制御点を表すPOINT構造体変数へのポインタを指定します
cCount - 制御点の数を指定します
戻り値 - 成功すると0以外、失敗すると0
PolyBezier()
BOOL PolyBezier(HDC hdc , CONST POINT *lppt , DWORD cCount);
一つ以上のベジェ曲線を描画します
hdc - デバイスコンテキストのハンドルを指定します
lppt - 制御点を表すPOINT構造体変数へのポインタを指定します
cCount - 制御点の数を指定します
戻り値 - 成功すると0以外、失敗すると0