Bezier Curves and Bezier Surfaces generation with C/C++ in Code::Blocks
destination source:https://www.programming-techniques.com/?p=99
Brief Theory of Bezier Curve
In order to draw curvy surface we implement Bezier curve algorithm. In drawing Bezier we first define n+1 control point pk = (xk, yk, zk) with k varying from 0 to n. And the coordinate points are blended to produce following position vectors that define the path of an approximation Bezier polynomial function between p0 and pn.
The Bezier blending functions BEZk,n(u) are the Bernstein polynomials: BEZk,n(u)=C(n,k)uk(1-u)n-k
Where the C(n, k) are binomial coefficients.
Equivalently, we can define Bezier blending functions with the recursion calculation.
BEZk,n (u) = (1-u) BEZk,n-1(u)+u BEZk-1,n-1(u), n>k?1
With BEZk,k = uk , and BEZ0,k = (1-u)k.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | #include <windows.h> #include <math.h> #define ROUND(a) ((int) (a + 0.5)) /* set window handle */ static HWND sHwnd; int a; void SetWindowHandle(HWND hwnd){ sHwnd=hwnd; } void setPixel(int x,int y,COLORREF color){ if(sHwnd==NULL){ MessageBox(NULL,"sHwnd was not initialized !","Error",MB_OK|MB_ICONERROR); exit(0); } HDC hdc=GetDC(sHwnd); SetPixel(hdc,x,y,color); ReleaseDC(sHwnd,hdc); return; // NEVERREACH // } float Coeff (int k, int n) { int j; float coeff= 1.0; for (j=n; j>k; j--) coeff *= j; for (j=n-k; j>k; j--) coeff /= j; return(coeff); } float BValue (int k, int n, float u, float coeff) { int j; float bvl = coeff; for (j=1; j<=k; j++) bvl *=u; for (j=1; j<=n-k; j++) bvl *= (1-u); return (bvl); } void BezierCurve (int Points, int col,...) { va_list Cord; int xpt[10], ypt[10], i=0, j, CP; float x,y,u,b,c; va_start (Cord,col); while (((xpt[i]=(va_arg (Cord,int))) >= -1) && ((ypt[i]=(va_arg (Cord,int))) >= -1) && ( i<=20)) i++; va_end (Cord); CP = (i-1); for (i=0; i<=Points; i++) { u = (float)i/Points; x = 0; y = 0; for (j=0; j<=CP; j++) { c = Coeff(j,CP); b = BValue (j,CP,u,c); x += xpt[j]*b; y += ypt[j]*b; } setPixel(ceil(0.5+x),y,col); } } /* Window Procedure WndProc */ LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){ switch(message){ case WM_PAINT: SetWindowHandle(hwnd); for(a=0;a<=50;a+=1) { BezierCurve(2000,RGB(a+100,a,50+a),50,200+a,100+a+a,300+a,150,200+a,200,200+a,-1000); BezierCurve(2000,RGB(a+100,a,50+a),200,200+a,300+a+a,300+a,400,200+a,500,200+a,-1000); BezierCurve(2000,RGB(a+100,a,50+a),500,200+a,550+a+a,300+a,600,200+a,650,200+a,-1000); } break; case WM_CLOSE: // FAIL THROUGH to call DefWindowProc break; case WM_DESTROY: PostQuitMessage(0); return 0; default: break; // FAIL to call DefWindowProc // } return DefWindowProc(hwnd,message,wParam,lParam); } int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iCmdShow){ static TCHAR szAppName[] = TEXT("Curves"); WNDCLASS wndclass; wndclass.style = CS_HREDRAW|CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; // Register the window // if(!RegisterClass(&wndclass)){ MessageBox(NULL,"Registering the class failled","Error",MB_OK|MB_ICONERROR); exit(0); } // Createw indow // HWND hwnd=CreateWindow(szAppName,"Bezier Curve - Programming Techniques", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); if(!hwnd){ MessageBox(NULL,"Window Creation Failed!","Error",MB_OK); exit(0); } // ShowWindow and UpdateWindow // ShowWindow(hwnd,iCmdShow); UpdateWindow(hwnd); // Message Loop // MSG msg; while(GetMessage(&msg,NULL,0,0)){ TranslateMessage(&msg); DispatchMessage(&msg); } /* return no error to the operating system */ return 0; } |
Note: to run this code in your machine with Code::blocks IDE, add a link
library libgdi32.a (it is usually inside MinGWlib ) in linker setting.
Output
Related Article
destination source:https://www.programming-techniques.com/?p=99