22Nh15 - DHMT - Lab15 - 102220026 - 102220041

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

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

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


Sinh viên 1: Lê Hải Khoa MSSV: 102220026
Sinh viên 2: Lê Nguyễn Ngọc Thanh MSSV: 102220041
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()
{
int x0 = 50, y0=50, xn = 300, yn = 150, x, y;

KhoaCNTT – Trường ĐHBK 1


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Ả:

1.2 Chương trình drawlinebres02.cpp


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

KhoaCNTT – Trường ĐHBK 2


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) {


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) {

KhoaCNTT – Trường ĐHBK 3


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();
}

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

KhoaCNTT – Trường ĐHBK 4


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)
}

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
}

KhoaCNTT – Trường ĐHBK 5


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>

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
{

KhoaCNTT – Trường ĐHBK 6


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++;
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);

KhoaCNTT – Trường ĐHBK 7


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
}

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):

KhoaCNTT – Trường ĐHBK 8


d = d + dy

# North East is Chosen


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

KhoaCNTT – Trường ĐHBK 9


#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);

// 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){

KhoaCNTT – Trường ĐHBK 10


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))
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()

KhoaCNTT – Trường ĐHBK 11


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){

KhoaCNTT – Trường ĐHBK 12


// 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);

//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

KhoaCNTT – Trường ĐHBK 13


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);
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;

KhoaCNTT – Trường ĐHBK 14


}
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);
glutInitWindowSize(500, 500);
glutCreateWindow("Bresenham Circle");
init();
glutDisplayFunc(ellipse);
glutMainLoop();
return 0;
}//main

KhoaCNTT – Trường ĐHBK 15


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;

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);

KhoaCNTT – Trường ĐHBK 16


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;
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));

KhoaCNTT – Trường ĐHBK 17


}
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;
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();

KhoaCNTT – Trường ĐHBK 18


}

}
//-----------------------------------------
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();
glutMouseFunc(MouseEventHandler);
glutDisplayFunc(Mydisplay);
glutSpecialFunc(KeyboardEventHandler);
glutMainLoop();
}

KhoaCNTT – Trường ĐHBK 19


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

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);

KhoaCNTT – Trường ĐHBK 20


}
}

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
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;
}

KhoaCNTT – Trường ĐHBK 21


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.

#include <stdio.h>
#include <math.h>

// Bư?c tính đi?m trung gian cho đư?ng th?ng Bresenham


void bresenhamLine(int x1, int y1, int x2, int y2) {
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
int incx = (x2 > x1) ? 1 : -1;
int incy = (y2 > y1) ? 1 : -1;

int x = x1, y = y1;


int p = 2 * dy - dx;

printf("Step\t(x, y)\t\t\tP\n");
printf("------------------------------\n");

for (int i = 0; i <= dx; i++) {


printf("%d\t(%d, %d)\t\t%d\n", i, x, y, p);
if (p >= 0) {

KhoaCNTT – Trường ĐHBK 22


y += incy;
p -= 2 * dx;
}
x += incx;
p += 2 * dy;
}
}

// Bư?c tính đi?m trung gian cho đư?ng tr?n Bresenham


void bresenhamCircle(int x0, int y0, int radius) {
int x = radius, y = 0;
int err = 0;

printf("Step\t(x, y)\t\t\tError\n");
printf("------------------------------\n");

while (x >= y) {
printf("(%d, %d)\t\t%d\n", x + x0, y + y0, err);
if (err <= 0) {
y += 1;
err += 2 * y + 1;
}
if (err > 0) {
x -= 1;
err -= 2 * x + 1;
}
}
}

// Bư?c tính đi?m trung gian cho đư?ng ellipse Bresenham


void bresenhamEllipse(int xc, int yc, int a, int b) {
int x = 0, y = b;
int a2 = a * a;
int b2 = b * b;
int d = 2 * b2 - a2;
KhoaCNTT – Trường ĐHBK 23
printf("Step\t(x, y)\t\t\tD\n");
printf("------------------------------\n");

while (y >= 0) {
printf("(%d, %d)\t\t%d\n", x + xc, y + yc, d);
if (d > 0) {
y--;
d -= 2 * a2;
}
x++;
d += 2 * b2;
}
}

int main() {
printf("Bresenham Line Algorithm:\n");
bresenhamLine(1, 1, 8, 5);
printf("\nBresenham Circle Algorithm:\n");
bresenhamCircle(0, 0, 5);
printf("\nBresenham Ellipse Algorithm:\n");
bresenhamEllipse(0, 0, 8, 4);

return 0;
}

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.
1. Đường thẳng Bresenham:

#include <stdio.h>
#include <math.h>

// Bước tính điểm trung gian cho đường thẳng Bresenham


void bresenhamLine(int x1, int y1, int x2, int y2) {
int dx = abs(x2 - x1);
int dy = abs(y2 - y1);
KhoaCNTT – Trường ĐHBK 24
int incx = (x2 > x1) ? 1 : -1;
int incy = (y2 > y1) ? 1 : -1;

int x = x1, y = y1;


int p = 2 * dy - dx;

printf("Step\t(x, y)\t\t\tP\n");
printf("------------------------------\n");

for (int i = 0; i <= dx; i++) {


printf("%d\t(%d, %d)\t\t%d\n", i, x, y, p);
x += incx;
p += 2 * dy;
if (p >= 0) {
y += incy;
p -= 2 * dx;
}
}
}

int main() {
printf("Bresenham Line Algorithm:\n");
bresenhamLine(1, 1, 8, 5);

return 0;
}

2. Đường tròn Bresenham:

#include <stdio.h>

// Bước tính điểm trung gian cho đường tròn Bresenham


void bresenhamCircle(int x0, int y0, int radius) {
int x = radius, y = 0;
int err = 0;

KhoaCNTT – Trường ĐHBK 25


printf("Step\t(x, y)\t\t\tError\n");
printf("------------------------------\n");

while (x >= y) {
printf("(%d, %d)\t\t%d\n", x + x0, y + y0, err);
y += 1;
err += 1 + 2 * y;
if (err <= 0) {
x -= 1;
err += 1 - 2 * x;
}
}
}

int main() {
printf("Bresenham Circle Algorithm:\n");
bresenhamCircle(0, 0, 5);

return 0;
}

3. Đường ellipse Bresenham:

#include <stdio.h>

// Bước tính điểm trung gian cho đường ellipse Bresenham


void bresenhamEllipse(int xc, int yc, int a, int b) {
int x = 0, y = b;
int a2 = a * a;
int b2 = b * b;
int d = 2 * b2 - a2;

printf("Step\t(x, y)\t\t\tD\n");
printf("------------------------------\n");

while (y >= 0) {
KhoaCNTT – Trường ĐHBK 26
printf("(%d, %d)\t\t%d\n", x + xc, y + yc, d);
if (d > 0) {
y--;
d -= 2 * a2;
}
x++;
d += 2 * b2;
}
}

int main() {
printf("Bresenham Ellipse Algorithm:\n");
bresenhamEllipse(0, 0, 8, 4);

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 27

You might also like