当前位置:文档之家› 贝塞尔曲线公式

贝塞尔曲线公式

#include

#include

#include



//三个控制点

POINT P0={50,50},P1={500,600},P2={800,200};



int ax = P0.x-2*P1.x+P2.x;

int ay = P0.y-2*P1.y+P2.y;

int bx = 2*P1.x-2*P0.x;

int by = 2*P1.y-2*P0.y;



double A = 4*(ax*ax+ay*ay);

double B = 4*(ax*bx+ay*by);

double C = bx*bx+by*by;



//曲线总长度

double total_length = 0.0;



//曲线分割的份数

const int STEP = 70;



//用于保存绘制点数据的数组

POINT pixels[STEP];



//-------------------------------------------------------------------------------------

//速度函数

/*

s(t_) = Sqrt[A*t*t+B*t+C]

*/

double s(double t)

{

return sqrt(A*t*t+B*t+C);

}



//-------------------------------------------------------------------------------------

//长度函数

/*



L(t) = Integrate[s[t], t]



L(t_) = ((2*Sqrt[A]*(2*A*t*Sqrt[C + t*(B + A*t)] + B*(-Sqrt[C] + Sqrt[C + t*(B + A*t)])) +

(B^2 - 4*A*C) (Log[B + 2*Sqrt[A]*Sqrt[C]] - Log[B + 2*A*t + 2 Sqrt[A]*Sqrt[C + t*(B + A*t)]]))

/(8* A^(3/2)));

*/

double L(double t)

{

double temp1 = sqrt(C+t*(B+A*t));

double temp2 = (2*A*t*temp1+B*(temp1-sqrt(C)));

double temp3 = log(B+2*sqrt(A)*sqrt(C));

double temp4 = log(B+2*A*t+2*sqrt(A)*temp1);

double temp5 = 2*sqrt(A)*temp2;

double temp6 = (B*B-4*A*C)*(temp3-temp4);



return (temp5+temp6)/(8*pow(A,1.5));

}



//-------------------------------------------------------------------------------------

//长度函数反函数,使用牛顿切线法求解

/*

X(n+1) = Xn - F(Xn)/F'(Xn)

*/

double InvertL(double t, double l)

{

double t1=t, t2;



do

{

t2 = t1 - (L(t1)-l)/s(t1);

if(abs(t1-t2)<0.000001) break;

t1=t2;

}while(true);

return t2;

}



//-------------------------------------------------------------------------------------

LRESULT CALLBACK _WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

switch (message)

{

case WM_TIMER:

{

static nIndex = 0;

if(nIndex>=0 && nIndex<=STEP)

{

double t = (double)nIndex/STEP;

//如果按照线形增长,此时对应的曲线长度

double l = t*total_length;

//根据L函数的反函数,求得l对应的t值

t = InvertL(t, l);



//根据贝塞尔曲线函数,求得取得此时的x,y坐标

double x = (1-t)*(1-t)*P0.x +2*(1-t)*t*P1.x + t*t*P2.x;

double y = (1-t)*(1-t)*P0.y +2*(1-t)*t*P1.y + t*t*P2.y;



//取整

pixels[nIndex].x = (int)(x+0.5);

pixels[nIndex].y = (int)(y+0.5);



nIndex++;

InvalidateRect(hWnd, 0, 0);

}

else

{

KillTimer(hWnd, 101);

}

}

break;

case WM_PAINT:

{

PAINTSTRUCT ps;

HDC hdc = BeginPaint(hWnd, &ps);

::MoveToEx(hdc, P0.x, P0.y, 0);

LineTo(hdc, P1.x, P1.y);

LineTo(hdc,

P2.x, P2.y);



for(int i=0; i
{

const POINT &pt = pixels[i];

if(pt.x==0 && pt.y==0) break;



::MoveToEx(hdc, pt.x-2, pt.y, 0);

::LineTo(hdc, pt.x+2, pt.y);

::MoveToEx(hdc, pt.x, pt.y-2, 0);

::LineTo(hdc, pt.x, pt.y+2);

}

EndPaint(hWnd, &ps);

}

break;

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}



//-------------------------------------------------------------------------------------

int APIENTRY WinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPTSTR lpCmdLine,

int nCmdShow)

{

//注册窗口类

WNDCLASSEX wcex;

ZeroMemory(&wcex, sizeof(WNDCLASSEX));



wcex.cbSize = sizeof(WNDCLASSEX);

wcex.style = CS_HREDRAW | CS_VREDRAW;

wcex.lpfnWndProc = (WNDPROC)_WndProc;

wcex.hInstance = hInstance;

wcex.hCursor = LoadCursor(NULL, IDC_ARROW);

wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);

wcex.lpszClassName = "BezierClass";

RegisterClassEx(&wcex);



//创建窗口

HWND hWnd = CreateWindow("BezierClass", "BezierDemo", WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);



//计算总长度

total_length = L(1);



//清空绘制点数据

ZeroMemory(&pixels, sizeof(pixels));



//设定定时刷新计时器

SetTimer(hWnd, 101, 10, 0);



//消息循环

MSG msg;

while(GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}



return (int) msg.wParam;

}


相关主题
文本预览
相关文档 最新文档