Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 37

BÀI THỰC HÀNH ĐỒ HỌA MÁY TÍNH

CÁC THUẬT TOÁN ĐỒ HỌA CƠ BẢN


Vẽ đường thẳng, đường tròn

Họ và Tên: Lê Anh Ngữ MSSV: 102220200

Nhóm học phần: 22N13

MỤC LỤC

1. Vẽ đường thẳng theo thuật toán Bresenham.......................................................1


1.1 Chương trình drawlinebres01.cpp..................................................................................1
1.2 Chương trình drawlinebres02.cpp..................................................................................2
2. Vẽ đường thẳng theo thuật toán DDA.................................................................4
3. Vẽ đường thẳng theo thuật toán Midpoint..........................................................5
3.1 Chương trình drawlineMidpoint01.cpp..........................................................................5
3.2 Chương trình drawlineMidpoint02.py............................................................................7
4. Vẽ đường tròn theo thuật toán Michener............................................................7
4.1 Chương trình drawcircleMichener01.py.........................................................................7
4.2 Chương trình drawcirleMichener02.py (python)............................................................9
5. Vẽ đường tròn theo thuật toán Midpoint...........................................................10
5.1 Chương trình drawcircleMidpoint.py...........................................................................10
6. Thuật toán vẽ đường ellipse................................................................................11
7. Thuật toán xén hình.............................................................................................12
8. Thuật toán xén hình Cohen-Sutherland............................................................16
9. BÀI TẬP................................................................................................................18

1. Vẽ đường thẳng theo thuật toán Bresenham

1.1 Chương trình drawlinebres01.cpp


#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

void init(void)
{
glClearColor(1.0,1.0,1.0,0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0,400.0,0.0,400.0);
}

void setPixel(GLint x,GLint y)


{
glBegin(GL_POINTS);
glVertex2i(x,y);
glEnd();
}

void linebres()

KhoaCNTT – Trường ĐHBK 1


{
int x0 = 50, y0=50, xn = 300, yn = 150, x, y;
int dx, dy, //deltas
pk, //decision parameter
k; //looping variable

glClear(GL_COLOR_BUFFER_BIT);
glColor3f( 1 ,0, 0);
setPixel(x0, y0); //plot first point

// difference between starting and ending points


dx = xn - x0;
dy = yn - y0;
pk = 2 * dy - dx;
x = x0; y = y0;

for ( k = 0; k < dx-1; ++k ) {


if ( pk < 0 ) {
pk = pk + 2 * dy; //calculate next pk
//next pixel: (x+1, y )
} else {
//next pixel: (x+1, y+1)
pk = pk + 2*dy - 2*dx; //calculate next pk
++y;
}
++x;
setPixel( x, y );
}

glFlush();
}

int main(int argc,char **argv){


glutInit(&argc,argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0,0);
glutInitWindowSize(500,500);
glutCreateWindow("Bresenham Line");
init();
glutDisplayFunc( linebres );
glutMainLoop();
return 0;
}

Kết quả chương trình:

KhoaCNTT – Trường ĐHBK 2


1.2 Chương trình drawlinebres02.cpp
#include <gl/glut.h>
#include <stdio.h>

int x1, y1, x2, y2;

void myInit() {
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 1.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0, 500, 0, 500);
}

void draw_pixel(int x, int y) {


glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}

void drawlinebres(int x1, int x2, int y1, int y2) {

KhoaCNTT – Trường ĐHBK 3


int dx, dy, i, e;
int incx, incy, inc1, inc2;
int x,y;

dx = x2-x1;
dy = y2-y1;

if (dx < 0) dx = -dx;


if (dy < 0) dy = -dy;
incx = 1;
if (x2 < x1) incx = -1;
incy = 1;
if (y2 < y1) incy = -1;
x = x1; y = y1;
if (dx > dy) {
draw_pixel(x, y);
e = 2 * dy-dx;
inc1 = 2*(dy-dx);
inc2 = 2*dy;
for (i=0; i<dx; i++) {
if (e >= 0) {
y += incy;
e += inc1;
}
else
e += inc2;
x += incx;
draw_pixel(x, y);
}

} else {
draw_pixel(x, y);
e = 2*dx-dy;
inc1 = 2*(dx-dy);
inc2 = 2*dx;
for (i=0; i<dy; i++) {
if (e >= 0) {
x += incx;
e += inc1;
}
else
e += inc2;
y += incy;
draw_pixel(x, y);
}
}
}

void myDisplay() {
drawlinebres(x1, x2, y1, y2);
glFlush();
}

int main(int argc, char **argv) {

printf( "Enter (x1, y1, x2, y2)\n");


scanf("%d %d %d %d", &x1, &y1, &x2, &y2);

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowSize(500, 500);
glutInitWindowPosition(0, 0);
glutCreateWindow("Bresenham's Line Drawing");
myInit();
glutDisplayFunc(myDisplay);
glutMainLoop();
}

Kết quả chương trình:

KhoaCNTT – Trường ĐHBK 4


KhoaCNTT – Trường ĐHBK 5
2. Vẽ đường thẳng theo thuật toán DDA
Tham khảo thêm.
2.1 Chương trình drawlineDDA.cpp
#include<gl/glut.h>
#include<math.h>

void LineDDA(int x1, int y1, int x2, int y2)


{
// Find Δm = max(|Δx|, |Δy|)
int dm = 0;
if (abs(x2-x1) >= abs(y2-y1)) //abs is a function for absolute value
dm = abs(x2-x1); //x is the length direction
else
dm = abs(y2-y1); //y is the length direction

//Find ∆𝒙⁄∆𝒎, and (∆𝒚)⁄∆𝒎, the length direction will be equal to 1


float dx = (float)(x2 - x1) / dm;
float dy = (float)(y2 - y1) / dm;

// Round the current coordinates


float x = x1 + 0.5;
float y = y1 + 0.5;

// Draw points in a loop, the x direction is increased to ∆𝒙⁄∆𝒎 and the y


direction is increased to (∆𝒚)⁄∆𝒎
glColor3f(0.0f, 0.0f, 1.0f);//blue
glPointSize(5);
for (int i = 0; i < dm; i++)
{
glBegin(GL_POINTS);
glVertex2i((int)x, (int)y);
glEnd();
x += dx;
y += dy;
}
}

void myDisplay()
{
glClearColor(1.0, 1.0, 1.0, 1.0);//Clear color, white
glClear(GL_COLOR_BUFFER_BIT);//Eliminate the buffer, use the above clear color to
eliminate

glColor3f(1.0f, 0.0f, 0.0f);//Set the color, red


glLineWidth(5);
glBegin(GL_LINES);
glVertex3f(200.0f, 200.0f, 0.0f);
glVertex3f(400.0f, 400.0f, 0.0f);
glEnd();

//LineDDA(0, 0, 200, 200);


//LineDDA(200, 200, 0, 0);
LineDDA(0, 200, 100, 100);

glFlush();//Forced refresh
}

void reshape(int w, int h)


{
glViewport(0, 0, (GLsizei)w, (GLsizei)h); //Define the viewport size
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//Make the coordinates of the lower
left corner be (0, 0) and the coordinates of the upper right corner be (w, h)

KhoaCNTT – Trường ĐHBK 6


}

void main(int argc, char* argv[])


{
glutInit(&argc, argv);//Initialize GLUT
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//Display mode
glutInitWindowPosition(100, 100);//Window position, the coordinates of the upper
left corner of the window on the screen
glutInitWindowSize(400, 400);//Window size
glutCreateWindow("LineDDA");//Create a window, the parameter is the title of the
window
glutDisplayFunc(myDisplay);//Tell GLUT which function is responsible for drawing,
that is, register a drawing function myDisplay
glutReshapeFunc(reshape); //When the window changes, what function is used to redraw
glutMainLoop();//Handle the never-ending loop monitoring
}

Kết quả chương trình:

3. Vẽ đường thẳng theo thuật toán Midpoint


3.1 Chương trình drawlineMidpoint01.cpp
#include <gl/glut.h>
#include <math.h>

KhoaCNTT – Trường ĐHBK 7


void drawlineMidpoint(int x0, int y0, int x1, int y1)
{
glColor3f(0.0f, 0.0f, 1.0f);//Set the color, blue
glPointSize(3);//Rasterized point with a diameter of 3

int a, b, d, x, y, temp, tag = 0;


if (abs(x1-x0) <abs(y1-y0)) //If the absolute value of the slope is greater than 1,
swap the coordinates x and y
{
temp = x0, x0 = y0, y0 = temp;
temp = x1, x1 = y1, y1 = temp;
tag = 1;
}

if (x0> x1)//guarantee x0<x1


{
temp = x0, x0 = x1, x1 = temp;
temp = y0, y0 = y1, y1 = temp;
}

a = y0-y1; //The discriminant a


b = x1-x0; //discriminant b
d = a + b / 2; //The initial value of the discriminant

if (y0 <y1)//The slope is positive


{
x = x0; y = y0;
glBegin(GL_POINTS);//Draw the starting point
glVertex2i(x, y);
glEnd();
while (x < x1)
{
if (d <0) // Discriminant <0, take point P2, the increment is a+b
{
x++; y++; d = d + a + b;
}
else// Discriminant >=0, take point P1, increment is a
{
x++;
d += a;
}
if (tag)//The slope is greater than 1
{
glBegin(GL_POINTS);
glVertex2i(y, x);
glEnd();
}
else
{
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
} /* while */
}

else//The slope is negative (y0>=y1)


{
x = x1;
y = y1;

glBegin(GL_POINTS);//Draw the starting point


glVertex2i(x, y);
glEnd();
while (x > x0)
{
if (d <0)// Discriminant <0, the increment is -a+b
{
x--;
y++;

KhoaCNTT – Trường ĐHBK 8


d = d - a + b;
}
else// Discriminant >=0, the increment is -a
{
x--; d -= a;
}
if (tag)//The slope is greater than 1
{
glBegin(GL_POINTS);
glVertex2i(y, x);
glEnd();
}
else
{
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
} /* while */
}
}
void myDisplay()
{
glClearColor(1.0, 1.0, 1.0, 1.0);//Clear color, white
glClear(GL_COLOR_BUFFER_BIT);//Eliminate the buffer, use the above clear color to
eliminate

drawlineMidpoint(200, 200, 400, 0);


glFlush();//Forced refresh
}

void Reshape(int w, int h)


{
glViewport(0, 0, (GLsizei)w, (GLsizei)h); //Define the viewport size
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, (GLdouble)w, 0.0, (GLdouble)h);//Make the coordinates of the lower
left corner be (0, 0) and the coordinates of the upper right corner be (w, h)
}

void main(int argc, char* argv[])


{
glutInit(&argc, argv);//Initialize GLUT
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//Display mode
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);//Window size
glutCreateWindow("Midpoint drawing method");
glutDisplayFunc(myDisplay);
glutReshapeFunc(Reshape);
glutMainLoop();//Handle the never-ending loop monitoring
}

Kết quả chương trình:

KhoaCNTT – Trường ĐHBK 9


3.2 Chương trình drawlineMidpoint02.py
# pip install matplotlib
# Midpoint line generation Algorithm
import matplotlib.pyplot as plt
plt.title("Midpoint Line Algorithm")
plt.xlabel("X Axis")
plt.ylabel("Y Axis")

def midpoint(x1, y1, x2, y2):


dx = x2 - x1
dy = y2 - y1

# Initialize the decision parameter


d = dy - (dx/2)
x = x1
y = y1

print(f"x = {x}, y = {y}")


# Initialize the plotting points
xcoordinates = [x]
ycoordinates = [y]

while (x<x2):
x = x + 1
# East is Chosen
if (d<0):
d = d + dy

# North East is Chosen

KhoaCNTT – Trường ĐHBK 10


else:
d = d + (dy - dx)
y = y + 1

xcoordinates.append(x)
ycoordinates.append(y)
print(f"x = {x}, y = {y}")
plt.plot(xcoordinates, ycoordinates)
plt.show()

if __name__=="__main__":
x1 = int(input("Enter the starting point of x: "))
y1 = int(input("Enter the starting point of y: "))
x2 = int(input("Enter the end point of x: "))
y2 = int(input("Enter the end point of y: "))

midpoint(x1, y1, x2, y2)

4. Vẽ đường tròn theo thuật toán Michener


4.1 Chương trình drawcircleMichener01.py

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 200.0, 0.0, 200.0);

void setPixel(GLint x, GLint y)


{
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}
void drawcirclebres()
{
int xc=100, yc=100, r=10;
int x=0, y=r;
int p = 3-2*r;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1, 0, 0);

while(x<=y){
// 1st octant
setPixel(xc+x, yc+y);
setPixel(xc+y, yc+x); //find other points by symmetry

// 2nd octant
setPixel(xc-x, yc+y);
setPixel(xc-y, yc+x);

KhoaCNTT – Trường ĐHBK 11


// 3rd octant
setPixel(xc-y, yc-x);
setPixel(xc-x, yc-y);

//4th octant
setPixel(xc+y, yc-x);
setPixel(xc+x, yc-y);

if (p<0) {
x = x + 1;
p = p + 4*x + 6;
}
else {
x = x + 1;
y = y - 1;
p = p + 4*x - 4*y + 10;
}
}//while

glFlush();

int main(int argc, char **argv){


glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0, 0);
glutInitWindowSize(500, 500);
glutCreateWindow("Bresenham Circle");
init();
glutDisplayFunc(drawcirclebres);

glutMainLoop();
return 0;
}//main

 Kết quả chạy chương trình:

4.2 Chương trình drawcirleMichener02.py (python)


# Bresenham Circle Algorithm in Python
import matplotlib.pyplot as plt
def bresenham_circle(x0, y0, radius):
x = radius
y = 0
err = 0
points = []
while x >= y:
points.append((x0 + x, y0 + y))

KhoaCNTT – Trường ĐHBK 12


points.append((x0 + y, y0 + x))
points.append((x0 - y, y0 + x))
points.append((x0 - x, y0 + y))
points.append((x0 - x, y0 - y))
points.append((x0 - y, y0 - x))
points.append((x0 + y, y0 - x))
points.append((x0 + x, y0 - y))

y += 1
err += 1 + 2*y
if 2*(err-x) + 1 > 0:
x -= 1
err += 1 - 2*x

return points

points = bresenham_circle(50, 50, 30)

# plot the points


plt.scatter([x for x, y in points], [y for x, y in points])

# draw the circle


circle = plt.Circle((50, 50), 30, fill=False)
plt.gcf().gca().add_artist(circle)

plt.show()

5. Vẽ đường tròn theo thuật toán Midpoint


5.1 Chương trình drawcircleMidpoint.py
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 200.0, 0.0, 200.0);
}

void setPixel(GLint x, GLint y)


{
glBegin(GL_POINTS);
glVertex2i(x, y);
glEnd();
}

void drawcirclemidpoint(){

int xc=100, yc=100, r=10;


int x=0, y=r;
int p = 1 - r; // = 3/2 - r

glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1 , 0, 0);
while(x<=y){
// 1st octant
setPixel(xc+x, yc+y);
setPixel(xc+y, yc+x); //find other points by symmetry

// 2nd octant
setPixel(xc-x, yc+y);
setPixel(xc-y, yc+x);

// 3rd octant
setPixel(xc-y, yc-x);
setPixel(xc-x, yc-y);

KhoaCNTT – Trường ĐHBK 13


//4th octant
setPixel(xc+y, yc-x);
setPixel(xc+x, yc-y);

if (p<0) {
x = x + 1;
p = p + 2*x + 3; //p = p + 2*x + 1;
}
else {
x = x + 1;
y = y - 1;
p = p + 2*x - 2*y + 5; //p = p + 2*x - 2*y + 1;
}
}//while

glFlush();
}

int main(int argc, char **argv){


glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0, 0);
glutInitWindowSize(500, 500);
glutCreateWindow("Bresenham Circle");
init();
glutDisplayFunc(drawcirclemidpoint);
glutMainLoop();
return 0;
}//main

6. Thuật toán vẽ đường ellipse

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

void init(void)
{
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 200.0, 0.0, 200.0);
}

void setPixel(GLint x, GLint y)


{
glBegin(GL_POINTS);

KhoaCNTT – Trường ĐHBK 14


glVertex2i(x, y);
glEnd();
}

void ellipse()
{
int a = 80, b = 40, xc = 100, yc = 100;
int aSq, bSq, twoASq, twoBSq, d, dx, dy, x, y;

glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1 , 0, 0);

aSq = a*a;
bSq = b*b;
twoASq = 2*aSq;
twoBSq = 2*bSq;
d = bSq - b*aSq + aSq/4;
dx = 0;
dy = twoASq*b;
x = 0;
y = b;

setPixel(xc + x, yc + y);
setPixel(xc - x, yc + y);
setPixel(xc + x, yc - y);
setPixel(xc - x, yc - y);

while (dx < dy)


{ x++;
dx += twoBSq;
if (d >= 0)
{ y--;
dy -= twoASq;
}
if (d < 0)
d += bSq + dx;
else
d += bSq + dx - dy;

setPixel(xc + x, yc + y);
setPixel(xc - x, yc + y);
setPixel(xc + x, yc - y);
setPixel(xc - x, yc - y);
}

d = (int)(bSq*(x+0.5)*(x+0.5) + aSq*(y-1)*(y-1) - aSq*bSq);


while (y > 0)
{ y--;
dy -= twoASq;
if (d <= 0)
{ x++;
dx += twoBSq;
}
if (d > 0)
d += aSq - dy;
else
d += aSq -dy +dx;

setPixel(xc + x, yc + y);
setPixel(xc - x, yc + y);
setPixel(xc + x, yc - y);
setPixel(xc - x, yc - y);

}
glFlush();
}

int main(int argc, char **argv){


glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
glutInitWindowPosition(0, 0);

KhoaCNTT – Trường ĐHBK 15


glutInitWindowSize(500, 500);
glutCreateWindow("Bresenham Circle");
init();
glutDisplayFunc(ellipse);
glutMainLoop();
return 0;
}//main

Kết quả chương trình:

7. Thuật toán xén hình


#include <glut.h>
#include <math.h>

#define INC 10
#define M_PI 3.14159265358979323846

typedef struct {
int x,y;
} Point;

KhoaCNTT – Trường ĐHBK 16


Point A,B, wmax, wmin;;
float goc;
char chuot;

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

void KhoiTao(){
glClearColor(0,0,0,0);
glLineWidth(2);

wmin.x=0;wmin.y=0;
wmax.x=200;wmax.y=120;
A.x=300;
A.y=200;
B.x=50;
B.y=-100;

goc=0;
chuot=0;
}
int Ma(Point M){
int m=0;
if(M.x<wmin.x) m |=1;
if(M.x>wmax.x) m |=2;
if(M.y<wmin.y) m |=4;
if(M.y>wmax.y) m |=8;
return m;
}
void HoanVi(Point *A,Point *B){
Point T;
T=*A; *A=*B; *B=T;
}
Point Xoay(Point A,int g)
{
float goc_rad =g * M_PI/180;
Point T;
T.x=A.x*cos(goc_rad)-A.y*sin(goc_rad);
T.y=A.x*sin(goc_rad)+A.y*cos(goc_rad);
return T;
}
void VeDuongThang(Point A,Point B){
glBegin(GL_LINES);
glVertex2i(A.x,A.y);
glVertex2i(B.x,B.y);
glEnd();
}
void VeHCN(Point wmin,Point wmax,int g)
{
Point A,B,C,D;
A=wmin;
C=wmax;
B.x=wmax.x; B.y=wmin.y;
D.x=wmin.x; D.y=wmax.y;

A=Xoay(A,g);
B=Xoay(B,g);
C=Xoay(C,g);
D=Xoay(D,g);

glBegin(GL_LINE_LOOP);
glVertex2i(A.x,A.y);
glVertex2i(B.x,B.y);
glVertex2i(C.x,C.y);
glVertex2i(D.x,D.y);
glEnd();

void ClipCohen(Point A,Point B,Point wmin,Point wmax,int g){


int thoat=0 , ve=1;

KhoaCNTT – Trường ĐHBK 17


double m;

while(thoat==0){
if((Ma(A)|Ma(B))==0) thoat=1; // A va B nam trong vung cn
ma(A)=ma(B)=0000
else if((Ma(A) & Ma(B))!=0) // AB nam hoan toan ben ngoai
vung cn
{
thoat =1; ve=0;
}else{
if(Ma(A)==0) HoanVi(&A,&B); //A nam trong vung cn
if(A.x==B.x) // A va B cung nam doc
{
if(A.y>wmax.y) A.y=wmax.y; //
else A.y=wmin.y;
}
else
{
m=(double)(B.y-A.y)/(B.x-A.x);
if(A.x<wmin.x)
{
A.y=A.y+(wmin.x-A.x)*m;
A.x=wmin.x;
}else if(A.x>wmax.x)
{
A.y=A.y+(wmax.x-A.x)*m;
A.x=wmax.x;
}else if(A.y<wmin.y)
{
A.x=A.x+(wmin.y-A.y)/m;
A.y=wmin.y;
}else if(A.y>wmax.y)
{
A.x=A.x+(wmax.y-A.y)/m;
A.y=wmax.y;
}
}

}
}
if(ve) VeDuongThang(Xoay(A,g),Xoay(B,g));
}
void XenHinhNhiPhan(Point A,Point B,Point wmin,Point wmax,int g){
Point P,Q,M;

if((Ma(A)|Ma(B))==0) VeDuongThang(Xoay(A,g),Xoay(B,g));
if((Ma(A)&Ma(B))!=0) return ;
if((Ma(A)!=0) &&(Ma(B)==0)) HoanVi(&A,&B);
if((Ma(A)==0) &&(Ma(B)!=0))
{
P=A;Q=B;
while((abs(P.x-Q.x)+abs(P.y-Q.y))>2)
{
M.x=(P.x+Q.x)/2;
M.y=(P.y+Q.y)/2;
if(Ma(M)==0) P=M;
else Q=M;
}
VeDuongThang(Xoay(A,g),Xoay(P,g));
}
if((Ma(A)!=0)&&(Ma(B)!=0)&&((Ma(A) & Ma(B))==0))
{
P=A;Q=B;
M.x=(P.x+Q.x)/2;
M.y=(P.y+Q.y)/2;

while(( Ma(M)!=0) && ((abs(P.x-Q.x)+abs(P.y-Q.y))>2))


{
if((Ma(P)& Ma(M)) !=0) P=M;
else Q=M;
M.x=(P.x+Q.x)/2;

KhoaCNTT – Trường ĐHBK 18


M.y=(P.y+Q.y)/2;
}
if(Ma(M)==0)
{
XenHinhNhiPhan(P,M,wmin,wmax,g);
XenHinhNhiPhan(M,Q,wmin,wmax,g);
}
}
}

void Mydisplay(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glColor3f(0.0, 1.0, 0.0);


VeHCN(wmin,wmax,goc);

glColor3f(0.0, 0.0, 1.0);


VeDuongThang(A,B);

glColor3f(1.0, 0.0, 0.0);


ClipCohen(Xoay(A,-goc),Xoay(B,-goc),wmin,wmax,goc);
//XenHinhNhiPhan(Xoay(A,-goc),Xoay(B,-goc),wmin,wmax,goc);

glFlush();
}

void KeyboardEventHandler(int key,int x,int y)


{
switch(key)
{
case GLUT_KEY_UP:
goc += INC;
if(goc >360) goc=0;
glutPostRedisplay();
break;
case GLUT_KEY_DOWN:
goc -= INC;
if(goc <0) goc=360;
glutPostRedisplay();
break;
}
}

void MouseEventHandler(int button, int state, int x, int y)


{

if(button == GLUT_LEFT_BUTTON && state == GLUT_UP)


if(chuot==0)
{
A.x=x-300;
A.y=300-y;
chuot=1;
}
else
{
B.x=x-300;
B.y=300-y;
chuot=0;
glutPostRedisplay();
}

}
//-----------------------------------------
int main(int argc,char* arg[]){

glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);


glutInitWindowSize (600, 600);
glutInitWindowPosition (10, 10);
glutCreateWindow("Thuat Toan Xen Hinh");
gluOrtho2D(-300, 300, -300, 300);
KhoiTao();

KhoaCNTT – Trường ĐHBK 19


glutMouseFunc(MouseEventHandler);
glutDisplayFunc(Mydisplay);
glutSpecialFunc(KeyboardEventHandler);
glutMainLoop();
}

Kết quả chương trình:

8. Thuật toán xén hình Cohen-Sutherland

#include <GL/glut.h>
#include <cstdio>

#define LEFT 1
#define RIGHT 2
#define BOTTOM 4
#define TOP 8

int x1=150,y1=50, x2=50, y2=250, XL=100, XR=300, YB=100, YT=200; //(x1,y1), (x2,y2) are
the end points of the straight line segment, XL is the left boundary, XR is the right
boundary, YB is the lower boundary, and YT is the upper boundary
int x1_init = 150, y1_init = 50, x2_init = 50, y2_init = 250; //Back up the end points
of the straight line segment so as to draw the straight line segment before cutting

KhoaCNTT – Trường ĐHBK 20


int encode(int x,int y)
{
int c = 0;
if (x < XL) c |= LEFT;
if (x > XR) c |= RIGHT;
if (y < YB) c |= BOTTOM;
if (y > YT) c |= TOP;
return c;
}

void CS_LineClip() //Cohen-Sutherland cropping algorithm


{
int x, y;
int code1, code2, code;
code1 = encode(x1, y1);
code2 = encode(x2, y2);

while (code1 != 0 || code2 != 0)


{
if (code1 & code2)
return;
if (code1 != 0)
code = code1;
else
code = code2;

if (LEFT & code)


{
x = XL;
y = y1 + (y2 - y1)*(XL - x1) / (x2 - x1);
}
else if (RIGHT & code)
{
x = XR;
y = y1 + (y2 - y1)*(XR - x1) / (x2 - x1);
}
else if (BOTTOM & code)
{
y = YB;
x = x1 + (x2 - x1)*(YB - y1) / (y2 - y1);
}
else if (TOP & code)
{
y = YT;
x = x1 + (x2 - x1)*(YT - y1) / (y2 - y1);
}
if (code == code1)
{
x1 = x; y1 = y; code1 = encode(x1, y1);
}
else
{
x2 = x; y2 = y; code2 = encode(x2, y2);
}
}

void init() //Initialization function


{
glClearColor(1.0, 1.0, 1.0, 0.0); //Set the background color
glMatrixMode(GL_PROJECTION); // Set projection parameters
gluOrtho2D(0.0, 600.0, 0.0, 400.0); // Set the size of the scene
CS_LineClip(); //Execute a cropping algorithm
}

void mydisplay() //Display function


{
//Draw a square border

KhoaCNTT – Trường ĐHBK 21


glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glPointSize(2);
glBegin(GL_LINE_LOOP);
glVertex2i(XL, YT);
glVertex2i(XL, YB);
glVertex2i(XR, YB);
glVertex2i(XR, YT);
glEnd();
glFlush();

//Draw the line segment before cropping


glBegin(GL_LINES);
glVertex2i(x1_init, y1_init);
glVertex2i(x2_init, y2_init);
glEnd();
glFlush();

//Draw the trimmed line segment


glColor3f(0.0, 0.0, 0.0);
glBegin(GL_LINES);
glVertex2i(x1, y1);
glVertex2i(x2, y2);
glEnd();
glFlush();
}

int main(int argc, char *argv[])


{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
glutInitWindowPosition(100, 100);
glutInitWindowSize(400, 400);
glutCreateWindow("Cohen-Sutherland cropping algorithm");
init();
glutDisplayFunc(&mydisplay);
glutMainLoop();
return 0;
}

Kết quả chương trình:

KhoaCNTT – Trường ĐHBK 22


9. BÀI TẬP
1) Viết chương trình liệt kê dạng bảng thứ tự các bước tính điểm trung gian trong quá
trình vẽ đường thẳng, đường tròn, đường ellipse theo các giải thuật trên.

Vẽ đường thẳng bằng thuật toán Bresenham:

KhoaCNTT – Trường ĐHBK 23


Vẽ đường thẳng với thuật toán MidPoint với điểm đầu (20,30), điểm cuối (50,50):

KhoaCNTT – Trường ĐHBK 24


Vẽ đường tròn với thuật toán Michener:

KhoaCNTT – Trường ĐHBK 25


Vẽ đường tròn bằng thuật toán MidPoint:

KhoaCNTT – Trường ĐHBK 26


Vẽ hình Ellcipse:

KhoaCNTT – Trường ĐHBK 27


2) Viết lại các chương trình trên theo hướng tối ưu về hiệu suất thực thi chương trình.

Viết lại chương trình Bresenham:

#include <GL/glut.h>
#include <stdio.h>

KhoaCNTT – Trường ĐHBK 28


#include <stdlib.h>

// Các biến toàn cục để lưu tọa độ của đường thẳng


int x1, y1, x2, y2;

// Hàm khởi tạo


void init() {
glClearColor(0.0, 0.0, 0.0, 1.0); // Màu nền đen
glClear(GL_COLOR_BUFFER_BIT); // Xóa bộ đệm màu
glMatrixMode(GL_PROJECTION); // Đặt ma trận chiếu
gluOrtho2D(0, 500, 0, 500); // Thiết lập không gian hiển thị 2D
}

// Hàm vẽ một điểm tại tọa độ (x, y)


void setPixel(int x, int y) {
glBegin(GL_POINTS); // Bắt đầu vẽ các điểm
glVertex2i(x, y); // Thiết lập tọa độ điểm
glEnd(); // Kết thúc vẽ các điểm
}

// Hàm vẽ đường thẳng bằng thuật toán Bresenham


void drawLineBresenham(int x1, int y1, int x2, int y2) {
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
int sx = (x1 < x2) ? 1 : -1;
int sy = (y1 < y2) ? 1 : -1;
int err = dx - dy;
int e2;

while (1) {
setPixel(x1, y1); // Vẽ điểm tại tọa độ hiện tại
if (x1 == x2 && y1 == y2) break; // Nếu đến điểm cuối thì dừng
e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
KhoaCNTT – Trường ĐHBK 29
x1 += sx;
}
if (e2 < dx) {
err += dx;
y1 += sy;
}
}
}

// Hàm hiển thị


void display() {
drawLineBresenham(x1, y1, x2, y2);
glFlush(); // Đảm bảo tất cả các lệnh vẽ được thực thi
}

// Hàm chính
int main(int argc, char **argv) {
// Nhập tọa độ của đường thẳng
printf("Enter (x1, y1, x2, y2): ");
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);

// Khởi tạo GLUT


glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowSize(500, 500); // Kích thước cửa sổ
glutInitWindowPosition(100, 100); // Vị trí cửa sổ
glutCreateWindow("Bresenham's Line Drawing"); // Tạo cửa sổ với tiêu đề
init(); // Gọi hàm khởi tạo
glutDisplayFunc(display); // Đặt hàm hiển thị làm hàm callback
glutMainLoop(); // Vào vòng lặp chính của GLUT
return 0;
}

Viết lại chương trình vẽ đường tròn bằng thuật toán Michener:
KhoaCNTT – Trường ĐHBK 30
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

// Khởi tạo các tham số ban đầu


void init(void) {
glClearColor(1.0, 1.0, 1.0, 0.0); // Màu nền trắng
glMatrixMode(GL_PROJECTION); // Đặt ma trận chiếu
gluOrtho2D(0.0, 200.0, 0.0, 200.0); // Thiết lập không gian hiển thị 2D
}

// Hàm vẽ một điểm tại tọa độ (x, y)


void setPixel(GLint x, GLint y) {
glVertex2i(x, y);
}

// Hàm vẽ đường tròn bằng thuật toán midpoint


void drawCircleMidpoint() {
int xc = 100, yc = 100; // Tọa độ tâm đường tròn
int r = 10; // Bán kính đường tròn
int x = 0, y = r;
int p = 1 - r; // Giá trị khởi tạo của p

glClear(GL_COLOR_BUFFER_BIT); // Xóa bộ đệm màu


glColor3f(1, 0, 0); // Đặt màu vẽ là đỏ

glBegin(GL_POINTS); // Bắt đầu vẽ các điểm


while (x <= y) {
// Vẽ 8 điểm đối xứng qua tâm (xc, yc)
setPixel(xc + x, yc + y);
setPixel(xc + y, yc + x);
setPixel(xc - x, yc + y);
setPixel(xc - y, yc + x);
setPixel(xc - x, yc - y);
KhoaCNTT – Trường ĐHBK 31
setPixel(xc - y, yc - x);
setPixel(xc + x, yc - y);
setPixel(xc + y, yc - x);

if (p < 0) {
p += 2 * x + 3; // Giá trị tiếp theo của p khi p < 0
} else {
y--;
p += 2 * x - 2 * y + 5; // Giá trị tiếp theo của p khi p >= 0
}
x++;
}
glEnd(); // Kết thúc vẽ các điểm

glFlush(); // Đảm bảo tất cả các lệnh vẽ được thực thi


}

// Hàm chính
int main(int argc, char **argv) {
glutInit(&argc, argv); // Khởi tạo GLUT
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Chế độ hiển thị đơn với màu
RGB
glutInitWindowPosition(100, 100); // Vị trí cửa sổ
glutInitWindowSize(500, 500); // Kích thước cửa sổ
glutCreateWindow("Midpoint Circle Algorithm"); // Tạo cửa sổ với tiêu đề
init(); // Gọi hàm khởi tạo
glutDisplayFunc(drawCircleMidpoint); // Đặt hàm vẽ đường tròn làm hàm
callback hiển thị
glutMainLoop(); // Vào vòng lặp chính của GLUT
return 0;
}
Vẽ đường tròn bằng thuật toán MidPoint:
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>

KhoaCNTT – Trường ĐHBK 32


// Khởi tạo các tham số ban đầu
void init(void) {
glClearColor(1.0, 1.0, 1.0, 0.0); // Màu nền trắng
glMatrixMode(GL_PROJECTION); // Đặt ma trận chiếu
gluOrtho2D(0.0, 200.0, 0.0, 200.0); // Thiết lập không gian hiển thị 2D
}

// Hàm vẽ một điểm tại tọa độ (x, y)


void setPixel(GLint x, GLint y) {
glVertex2i(x, y);
}

// Hàm vẽ đường tròn bằng thuật toán midpoint


void drawCircleMidpoint() {
int xc = 100, yc = 100; // Tọa độ tâm đường tròn
int r = 10; // Bán kính đường tròn
int x = 0, y = r;
int p = 1 - r; // Giá trị khởi tạo của p

glClear(GL_COLOR_BUFFER_BIT); // Xóa bộ đệm màu


glColor3f(1, 0, 0); // Đặt màu vẽ là đỏ

glBegin(GL_POINTS); // Bắt đầu vẽ các điểm


while (x <= y) {
setPixel(xc + x, yc + y); // Vẽ 8 điểm đối xứng qua tâm (xc, yc)
setPixel(xc + y, yc + x);
setPixel(xc - x, yc + y);
setPixel(xc - y, yc + x);
setPixel(xc - x, yc - y);
setPixel(xc - y, yc - x);
setPixel(xc + x, yc - y);
setPixel(xc + y, yc - x);

if (p < 0) {
KhoaCNTT – Trường ĐHBK 33
p += 2 * x + 3; // Giá trị tiếp theo của p khi p < 0
} else {
y--;
p += 2 * x - 2 * y + 5; // Giá trị tiếp theo của p khi p >= 0
}
x++;
}
glEnd(); // Kết thúc vẽ các điểm

glFlush(); // Đảm bảo tất cả các lệnh vẽ được thực thi


}

// Hàm chính
int main(int argc, char **argv) {
glutInit(&argc, argv); // Khởi tạo GLUT
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Chế độ hiển thị đơn với màu
RGB
glutInitWindowPosition(0, 0); // Vị trí cửa sổ
glutInitWindowSize(500, 500); // Kích thước cửa sổ
glutCreateWindow("Midpoint Circle"); // Tạo cửa sổ với tiêu đề
init(); // Gọi hàm khởi tạo
glutDisplayFunc(drawCircleMidpoint); // Đặt hàm vẽ đường tròn làm hàm
callback hiển thị
glutMainLoop(); // Vào vòng lặp chính của GLUT
return 0;
}

Viết lại chương trình vẽ hình Ellipse:

#include <GL/glut.h>
#include <stdio.h>

void init(void) {
glClearColor(1.0, 1.0, 1.0, 0.0); // Set background color to white
glMatrixMode(GL_PROJECTION); // Set the projection matrix

KhoaCNTT – Trường ĐHBK 34


gluOrtho2D(0.0, 200.0, 0.0, 200.0); // Define the 2D orthographic viewing region
}

void setPixel(GLint x, GLint y) {


glVertex2i(x, y); // Set the pixel at coordinates (x, y)
}

void ellipse() {
int a = 80, b = 40, xc = 100, yc = 100; // Ellipse parameters: semi-major axis, semi-
minor axis, center
int aSq = a * a, bSq = b * b; // Squares of semi-major and semi-minor axes
int twoASq = 2 * aSq, twoBSq = 2 * bSq; // Double the squares of the axes
int d, dx, dy, x, y;

glClear(GL_COLOR_BUFFER_BIT); // Clear the color buffer


glColor3f(1, 0, 0); // Set the drawing color to red

// Region 1
d = bSq - b * aSq + aSq / 4; // Initial decision parameter
dx = 0;
dy = twoASq * b;
x = 0;
y = b;

glBegin(GL_POINTS);
while (dx < dy) { // First region: slope < 1
setPixel(xc + x, yc + y); // First quadrant
setPixel(xc - x, yc + y); // Second quadrant
setPixel(xc + x, yc - y); // Fourth quadrant
setPixel(xc - x, yc - y); // Third quadrant

x++;
dx += twoBSq;
if (d >= 0) {
y--;
KhoaCNTT – Trường ĐHBK 35
dy -= twoASq;
d += bSq + dx - dy;
} else {
d += bSq + dx;
}
}

// Region 2
d = bSq * (x + 0.5) * (x + 0.5) + aSq * (y - 1) * (y - 1) - aSq * bSq;
while (y > 0) { // Second region: slope >= 1
setPixel(xc + x, yc + y); // First quadrant
setPixel(xc - x, yc + y); // Second quadrant
setPixel(xc + x, yc - y); // Fourth quadrant
setPixel(xc - x, yc - y); // Third quadrant

y--;
dy -= twoASq;
if (d <= 0) {
x++;
dx += twoBSq;
d += aSq - dy + dx;
} else {
d += aSq - dy;
}
}
glEnd();

glFlush(); // Force execution of GL commands in finite time


}

int main(int argc, char **argv) {


glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); // Set display mode
glutInitWindowPosition(0, 0); // Set the initial window position
glutInitWindowSize(500, 500); // Set the initial window size
KhoaCNTT – Trường ĐHBK 36
glutCreateWindow("Ellipse"); // Create the window with a title
init(); // Initialize the rendering context
glutDisplayFunc(ellipse); // Set the display callback for the current
window
glutMainLoop(); // Enter the GLUT event processing loop
return 0;
}
----------------------------------------------------------

@Bộ môn Mạng & Truyền thông


KHOA CÔNG NGHỆ THÔNG TIN, TRƯỜNG ĐẠI HỌC BÁCH KHOA – ĐẠI HỌC ĐÀ NẴNG

KhoaCNTT – Trường ĐHBK 37

You might also like