Bài giảng Đồ họa máy tính - Chương 3: Xây dựng công cụ vẽ hình ảnh
Cửa sổ và khung nhìn
Phép biến đổi từ cửa sổ sang khung nhìn
Giải thuật cắt xén
Xây dựng lớp Canvas phục vụ cho việc vẽ hình ảnh
Vẽ tương đối và đồ hoạ con rùa
Tạo hình ảnh từ đa giác đều
Vẽ đường tròn và cung tròn
Biểu diễn và vẽ đường cong theo dạng tham số
p1 với cạnh trái else if ( p1 nằm bên phải ) cắt xén p1 với cạnh phải else if ( p1 nằm dưới ) cắt xén p1 với cạnh dưới else if ( p1 nằm trên ) cắt xén p1 với cạnh trên } else // p2 nằm ngoài { if ( p2 nằm bên trái ) cắt xén p2 với cạnh trái else if ( p2 nằm bên phải ) cắt xén p2 với cạnh phải else if ( p2 nằm dưới ) cắt xén p2 với cạnh dưới else if ( p2 nằm trên ) cắt xén p2 với cạnh trên } }while(1); } p1 p2 D C A B XÂY DỰNG LỚP CANVAS Mục đích: Cung cấp những tiện ích để vẽ các đối tượng như đường thẳng, đa giác v.v Cung cấp cách làm đơn giản để tạo cửa sổ ứng dụng, thiết lập cửa sổ khung nhìn, thiết lập ánh xạ biến đổi từ cửa sổ sang khung nhìn, cùng với những tiện ích trong đồ họa con rùa XÂY DỰNG LỚP CANVAS Các lớp hỗ trợ class Point2 { public: Point2() { x = y = 0.0f; } // constructor Point2(float xx, float yy) { x = xx; y = yy; } void set(float xx, float yy) { x = xx; y = yy; } float getX() { return x;} float getY() { return y;} void draw() { glBegin(GL_POINTS); glVertex2f((GLfloat)x, (GLfloat)y); glEnd(); } private: float x, y; }; XÂY DỰNG LỚP CANVAS Các lớp hỗ trợ class IntRect { public: IntRect() { l = 0; r = 100; b = 0; t = 100; } IntRect( int left, int right, int bottom, int top) { l = left; r = right; b = bottom; t = top; } void set( int left, int right, int bottom, int top) { l = left; r = right; b = bottom; t = top; } void draw(); // draw this rectangle using OpenGL private: int l, r, b, t; }; class RealRect { giống như lớp intRect ngoại trừ dùng float thay cho int }; XÂY DỰNG LỚP CANVAS class Canvas{ public: Canvas(int width, int height, char* windowTitle); void setWindow(float l, float r, float b, float t); void setViewport(int l, int r, int b, int t); IntRect getViewport(); RealRect getWindow(); float getWindowAspectRatio(); void clearScreen(); void setBackgroundColor(float r, float g, float b); void setColor(float r, float g, float b); void lineTo(float x, float y); void lineTo(Point2 p); void moveTo(float x, float y); void moveTo(Point2 p); những phương thức khác sẽ được định nghĩa sau private: Point2 CP; //current position in the world IntRect viewport; // the current viewport RealRect window; // the current window những biến thành viên khác sẽ được định nghĩa sau }; XÂY DỰNG LỚP CANVAS Canvas::Canvas(int width, int height, char* windowTitle) { char* argv[1]; char dummyString[8]; argv[0] = dummyString; int argc = 1; glutInit(&argc, argv); //initialize the tool kit glutInitDisplayMode(GLUT_SINGLE |GLUT_RGB ); //set the display mode glutInitWindowSize(width, height); //set window size glutInitWindowPosition(20, 20); // set window position on screen glutCreateWindow(windowTitle); // open the screen window setWindow(0, (float)width, 0, (float)height ); //default window setViewport(0, width, 0, height); //default viewport CP.set(0.0f, 0.0f); //initialize the CP to (0, 0) }; XÂY DỰNG LỚP CANVAS void Canvas::moveTo(float x, float y) { CP.set(x, y); } void Canvas::lineTo(float x, float y) { glBegin(GL_LINE); glVertex2f((GLfloat) CP.getX(), (GLfloat) CP.getY()); glVertex2f((GLfloat) x, (GLfloat) y); glEnd(); CP.set(x, y); glFlush(); } void Canvas::setWindow(float l, float r, float b, float t) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D((GLdouble)l,(GLdouble)r,(GLdouble)b,(GLdouble)t); window.set(l, r, b, t); } XÂY DỰNG LỚP CANVAS Canvas cvs(640, 480, "try out Canvas"); void display() { cvs.clearScreen(); //xóa màn hình cvs.setWindow(-10.0, 10.0, -10.0, 10.0); cvs.setViewport(10, 460, 10, 460); cvs.moveTo(0, -10.0);// vẽ đoạn thẳng cvs.lineTo(0, 10.0); RealRect box(-2.0, 2.0, -1.0, 1.0); //tạo hình chữ nhật box.draw(); ...... } void main() { cvs.setBackgroundColor(1.0, 1.0, 1.0); cvs.setColor(0.0, 0.0, 0.0); glutDisplayFunc(myDisplay); glutMainLoop(); } VẼ TƯƠNG ĐỐI moveTo(first data point); drawMarker(); for(each remaining data point) { lineTo(the next point); drawMarker(); } VẼ TƯƠNG ĐỐI void Canvas::moveRel(float dx, float dy) { CP.set(CP.getX() + dx, CP.getY() + dy); } void Canvas::lineRel(float dx, float dy) { float x =CP.getX() + dx; float y =CP.getY() + dy; lineTo(x, y); CP.set(x, y); } VẼ TƯƠNG ĐỐI void arrow(float f,float h, float t,float w) { cvs.lineRel(-w-t/2, -f); cvs.lineRel(w, 0); cvs.lineRel(0, -h); cvs.lineRel(t, 0); cvs.lineRel(0, h); cvs.lineRel(w, 0); cvs.lineRel(-w-t/2, f); } f h w w t CP ĐỒ HỌA CON RÙA Thêm vào lớp Canvas: Biến CD chứa hướng hiện hành turnTo(float angle) CD = angle; turn(float angle) CD += angle; (CCW) forward(float dist,int isVisible) CD CP cũ CP mới dist void Canvas::forward(float dist, int isVisible) { const float RadPerDeg=0.017453393; float x = CP.getX() + dist*cos(RadPerDeg *CD); float y = CP.getY() + dist*sin(RadPerDeg *CD); if( isVisible) lineTo(x, y); else moveTo(x, y); } ĐỒ HỌA CON RÙA for(some number of iteration){ //draw a line in current forward(length, 1); //turn through angle degreee directionturn(angle); // increment the line length length += increment; } a) b) c) d) Ví dụ: Vẽ polyspirals (a) 60 0 (b) 89.5 0 (c) -144 0 (d) 170 0 TẠO HÌNH ẢNH TỪ ĐA GIÁC ĐỀU Đa giác đều Định nghĩa: đa giác đơn, các cạnh bằng nhau, hai cạnh kề nhau hợp với nhau một góc bằng nhau. n: 3 4 5 6 40 TẠO HÌNH ẢNH TỪ ĐA GIÁC ĐỀU Vẽ đa giác đều Pi = ( R cos(2 i / n ), R sin(2 i / n )) với i = 0, 1, ..., n-1 . P 1 = (Rcos(ia), Rsin(ia)) R a P 0 P 2 x y void ngon(int n, float cx, float cy, float r, float rotA){ if (n < 3) return; double angle = rotA*PI/180; double angleInc = 2*PI/n; cvs.moveTo(r*cos(angle)+cx, r*sin(angle)+cy); for(int k=0;k<n;k++) { angle += angleInc; cvs.lineTo(r*cos(angle)+cx, r*sin(angle)+cy); } } TẠO HÌNH ẢNH TỪ ĐA GIÁC ĐỀU Vẽ đa giác bằng đồ họa con rùa for(i=0;i<6;i++) { cvs.forward(L, 1); cvs.turn(60); } L R 360/n Biến thể của đa giác đều a) b) c) VẼ ĐƯỜNG TRÒN VÀ CUNG TRÒN Vẽ đường tròn void drawCircle(Point2 center, float radius) { const int numVerts = 50; ngon(numVerts,center.getX(),center.getY(),radius,0); } Cách chỉ định một đường tròn Tâm và bán kính Tâm và một điểm nằm trên đường tròn Ba điểm nằm trên đường tròn VẼ ĐƯỜNG TRÒN VÀ CUNG TRÒN Vẽ cung tròn void drawArc(Point2 center, float r, float rotA, float sweep) { const int n=30; //number segments float angle = rotA*PI/180; float angleInc = 2*PI/n; float cx=center.getX(), cy=center.getY(); cvs.moveTo(r*cos(angle)+cx, r*sin(angle)+cy); for(int k=1;k<n;k++) { angle += angleInc; cvs.lineTo(r*cos(angle)+cx, r*sin(angle)+cy); } } c R b a x y DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Dạng ẩn : mô tả đường cong bằng hàm F(x, y). Hàm này cho biết mối quan hệ giữa x và y: điểm (x, y) nằm trên đường cong nếu và chỉ nếu F(x, y) = 0. F(x, y) = (y - Ay)(Bx - Ax) - (x - Ax)(By - Ay) (đthẳng) F(x, y) = x 2 + y 2 – R 2 (đtròn) Hàm trong ngoài F(x, y) = 0, nếu (x, y) nằm trên đường cong F(x, y) > 0, nếu (x, y) nằm ngoài đường cong F(x, y) < 0, nếu (x, y) nằm trong đường cong Nhược điểm của dạng ẩn Đối với hàm đa trị, không thể suy ra y=g(x) từ F(x, y), chẳng hạn từ dạng ẩn của đường tròn, ta có: DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Dạng biểu diễn tham số Ví dụ 1: Đoạn thẳng có hai đầu mút là A và B. Ở thời điểm t = 0, đi qua điểm A; ở thời điểm t = 1 qua điểm B. x(t) = Ax + (Bx - Ax)t y(t) = Ay + (By - Ay)t A (Ax, Ay) B (Bx, By) @ t = 0 @ t = 1 DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Dạng biểu diễn tham số Ví dụ 2: Đường ellipse có các bán kính là W và H x(t) = Wcos(t) y(t) = Hsin(t) với ( 0 t 2 ) t y(t) H -H x y H W (x(t), y(t)) c -c t= t= /2 x(t) t 2 W -W 2 DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Dạng biểu diễn tham số dạng ẩn và dạng tham số có cùng biểu diễn một đường cong hay không? từ dạng tham số tìm dạng ẩn? Ví dụ: đối với hình ellipse x(t) = Wcos(t) cos(t) = x/W y(t) = Hsin(t) sin(t) = y/H cos 2 (t) + sin 2 (t) = 1 DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Vẽ đường cong biểu diễn dưới dạng tham số t = T t = 0 P(t) = (x(t), y(t)) P 1 P 2 P m a) b) //draw the curve (x(t), t(t)) using //the array t[0], ..., t[n-1] of “sample-times” glBegin(GL_LINES); for(int i=0;i<n;i++) glVertex2f(x(t[i]), y(t[i])); glEnd() ; DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Superellipse Dạng ẩn Dạng tham số n = 2m/(2n+1) n < 1 co vào n > 1 phình ra n = 1 hình vuông DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Superhyperbola Dạng biểu diễn tham số n = 2m/(2n+1) n < 1 co vào n > 1 phình ra n = 1 đường thẳng DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Đường cong trong hệ tọa độ cực x y r ( r , ) x(t)=r(t)cos( (t)) y(t)=r(t)sin( (t)) x = f( )cos( ) y = f( )sin( ) Ví dụ cardioid f( ) = K(1 + cos( )) rose f( ) = Kcos(n ) Archimedean spiral f( ) = K DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Đường cong trong hệ tọa độ cực Mặt cắt nón (conic section) Đường xoắn ốc logarit f( ) = Ke a a = cot() a) b) a=1 parabola 0 a1hyperbola DẠNG BIỂU DIỄN THAM SỐ CỦA ĐƯỜNG CONG Đường cong 3D P(t) = (x(t), y(t), z(t)) Đường helix x(t) = cos(t) y(t) = sin(t) z(t) = bt Đường toroidal spiral x(t) = (asin(ct) + b)cos(t), y(t) = (asin(ct) + b)sin(t), z(t) = acos(ct)
File đính kèm:
- bai_giang_do_hoa_may_tinh_chuong_3_xay_dung_cong_cu_ve_hinh.ppt