天天看點

計算機圖形學實驗(一) Bresenham畫直線和中點畫圓法畫圓

圖形學的第一個實驗,

因為老師課上的講解原因,是以這裡将一個邊長為1的正方形塊作為一個像素,放大後可以看出來。

先上代碼,畫線的:

void drawLine(node * mnode)
{
	glClearColor(0.0f, 0.0f, 0.0f,0.0f);//繪圖顔色為黑色   
	glClear(GL_COLOR_BUFFER_BIT); 
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINES);
	//glViewport(0, 0, 400, 400);
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(i, 0);
		glVertex2i(i, 400);
	}
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(0, i);
		glVertex2i(400,i);
	}
	glEnd();
	//glClear(GL_COLOR_BUFFER_BIT);   //清空顔色緩沖池
	glColor3f(1.0, 0.0, 0.0);
	//glBegin(GL_POINTS);   
	//glViewport(0, 0, 400, 400);
	int x, y, dx, dy, e;
	int x1 = mnode[0].x, y1 = mnode[0].y, x2 = mnode[1].x, y2 =mnode[1].y;  
	dx = x2 - x1;
	dy = y2 - y1;
	e = -dx;
	x = x1;
	y = y1;
	for (int i = 0; i <= dx; i++)
	{
		//glVertex2i(x, y);
		glRectf(x,y, x+1, y+1);  //繪制矩形

		x++;
		e = e + 2 * dy;
		if (e >= 0)
		{
			y++;
			e = e - 2 * dx;
		}
	}
	//glEnd();     
	glFlush();
}
           
計算機圖形學實驗(一) Bresenham畫直線和中點畫圓法畫圓

放大後的圖像

計算機圖形學實驗(一) Bresenham畫直線和中點畫圓法畫圓

然後是畫圓的代碼:

void drawCircle()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//繪圖顔色為黑色   
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);
	//glBegin(GL_POINTS);
	glBegin(GL_LINES);
	glViewport(0, 0, 400, 400);
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(i, 0);
		glVertex2i(i, 400);
	}
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(0, i);
		glVertex2i(400, i);
	}
	glEnd();
	//glViewport(0, 0, 400, 400);
	glColor3f(1.0, 0.0, 0.0);
	int x, y;
	float d;
	int r = 100;
	x = 0, y = r;
	d = 1.25 - r;
	//glVertex2i(x+r,y+r);
	//glVertex2i(y+r, x+r);
	//glVertex2i(-x+r, y+r);
	//glVertex2i(y+r, -x+r);
	//glVertex2i(x+r, -y+r);
	//glVertex2i(-y+r, x+r);
	//glVertex2i(-x+r, -y+r);
	//glVertex2i(-y+r, -x+r);
	glRectf(x+r, y+r, x +r+1, y+r+1);  //繪制矩形
	glRectf(y+r, x+r, y+r+ 1, x+r+1);  //繪制矩形	
	glRectf(-x+r, y+r, -x+r+1, y +r+ 1);  //繪制矩形	
	glRectf(y+r, -x+r, y+r+ 1, -x+r+ 1);  //繪制矩形	
	glRectf(x+r, -y+r, x+r+ 1, -y+r+ 1);  //繪制矩形	
	glRectf(-y+r, x+r, -y+r + 1, x+r+ 1);  //繪制矩形	
	glRectf(-x+r, -y+r, -x+r + 1, -y+r + 1);  //繪制矩形	
	glRectf(-y+r, -x+r, -y+r + 1, -x+r + 1);  //繪制矩形
	while (x <= y)
	{
		if (d <= 0)
		{
			d += 2 * x + 3;
		}
		else
		{
			d += 2 * (x - y) + 5; 
			y--;
		}
		x++;
		//cout<< x <<" "<<y<< endl;
		/*glVertex2i(x + r, y + r);
		glVertex2i(y + r, x + r);
		glVertex2i(-x + r, y + r);
		glVertex2i(y + r, -x + r);
		glVertex2i(x + r, -y + r);
		glVertex2i(-y + r, x + r);
		glVertex2i(-x + r, -y + r);
		glVertex2i(-y + r, -x + r);*/
		glRectf(x + r, y + r, x + r + 1, y + r + 1);  //繪制矩形
		glRectf(y + r, x + r, y + r + 1, x + r + 1);  //繪制矩形	
		glRectf(-x + r, y + r, -x + r + 1, y + r + 1);  //繪制矩形	
		glRectf(y + r, -x + r, y + r + 1, -x + r + 1);  //繪制矩形	
		glRectf(x + r, -y + r, x + r + 1, -y + r + 1);  //繪制矩形	
		glRectf(-y + r, x + r, -y + r + 1, x + r + 1);  //繪制矩形	
		glRectf(-x + r, -y + r, -x + r + 1, -y + r + 1);  //繪制矩形	
		glRectf(-y + r, -x + r, -y + r + 1, -x + r + 1);  //繪制矩形
	}
	//glEnd();
	glFlush();
}
           
計算機圖形學實驗(一) Bresenham畫直線和中點畫圓法畫圓

放大後的代碼:

計算機圖形學實驗(一) Bresenham畫直線和中點畫圓法畫圓

實作原理:

過各行各列像素中心構造一組網格線,按直線從起點到終點的順序計算直線與各垂直網格線的交點,然後确定該列像素中與此交點最近的像素。該算法的巧妙之處在于采用增量計算,使得對于每一列,隻要檢查一個誤差項的符号,就可以确定該列的所求的像素。

計算機圖形學實驗(一) Bresenham畫直線和中點畫圓法畫圓

簡單來說就是如果在中點及以下則取y,中點以上則取y+1。

中點畫圓法:

計算機圖形學實驗(一) Bresenham畫直線和中點畫圓法畫圓

完整的代碼:

// ConsoleApplication2.cpp: 定義控制台應用程式的入口點。
//
#include "stdafx.h"
#include<gl/GLUT.H>
#include<cmath>
#include<iostream>
#include "node.h"
using namespace std;
node Line[2] = { node(0.0,0.0),node(0.0,0.0) };
int nodeNumber = 0;
bool finish = false;//已經畫完
void Initial(void)//初始化函數 
{
	glClearColor(1.0f, 1.0f, 1.0f, 1.0f);//白色背景,前3個是RGB,最後是Alpha值,用來控制透明,1.0表示完全不透明
	glMatrixMode(GL_MODELVIEW);//OpenGL按照三維方式來處理圖像,是以需要一個投影變換将三維圖形投影到顯示器的二維空間中
	glLoadIdentity();
	gluOrtho2D(0.0, 400, 0.0, 400.0);//指定使用正投影将一個x坐标在0~200,y坐标0~150範圍内的矩形坐标區域投影到顯示器視窗

}
void drawLine(node * mnode)
{
	glClearColor(0.0f, 0.0f, 0.0f,0.0f);//繪圖顔色為黑色   
	glClear(GL_COLOR_BUFFER_BIT); 
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINES);
	//glViewport(0, 0, 400, 400);
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(i, 0);
		glVertex2i(i, 400);
	}
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(0, i);
		glVertex2i(400,i);
	}
	glEnd();
	//glClear(GL_COLOR_BUFFER_BIT);   //清空顔色緩沖池
	glColor3f(1.0, 0.0, 0.0);
	//glBegin(GL_POINTS);   
	//glViewport(0, 0, 400, 400);
	int x, y, dx, dy, e;
	int x1 = mnode[0].x, y1 = mnode[0].y, x2 = mnode[1].x, y2 =mnode[1].y;  
	dx = x2 - x1;
	dy = y2 - y1;
	e = -dx;
	x = x1;
	y = y1;
	for (int i = 0; i <= dx; i++)
	{
		//glVertex2i(x, y);
		glRectf(x,y, x+1, y+1);  //繪制矩形

		x++;
		e = e + 2 * dy;
		if (e >= 0)
		{
			y++;
			e = e - 2 * dx;
		}
	}
	//glEnd();     
	glFlush();
}
void drawLine1()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//繪圖顔色為黑色   
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);
	glBegin(GL_LINES);
	//glViewport(0, 0, 400, 400);
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(i, 0);
		glVertex2i(i, 400);
	}
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(0, i);
		glVertex2i(400, i);
	}
	glEnd();
	//glClear(GL_COLOR_BUFFER_BIT);   //清空顔色緩沖池
	glColor3f(1.0, 0.0, 0.0);
	//glBegin(GL_POINTS);   
	//glViewport(0, 0, 400, 400);
	int x, y, dx, dy, e;
	int x1 = 0, y1 = 8, x2 = 50, y2 = 100;
	dx = x2 - x1;
	dy = y2 - y1;
	e = -dx;
	x = x1;
	y = y1;
	for (int i = 0; i <= dx; i++)
	{
		//glVertex2i(x, y);
		glRectf(x, y, x + 1, y + 1);  //繪制矩形

		x++;
		e = e + 2 * dy;
		if (e >= 0)
		{
			y++;
			e = e - 2 * dx;
		}
	}
	//glEnd();     
	glFlush();
}
void drawLine()
{
	if (finish)
	{
		drawLine(&Line[0]);
		finish = false;
	}
}
void drawCircle()
{
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);//繪圖顔色為黑色   
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(1.0, 1.0, 1.0);
	//glBegin(GL_POINTS);
	glBegin(GL_LINES);
	glViewport(0, 0, 400, 400);
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(i, 0);
		glVertex2i(i, 400);
	}
	for (int i = 0; i < 400; i++)
	{
		glVertex2i(0, i);
		glVertex2i(400, i);
	}
	glEnd();
	//glViewport(0, 0, 400, 400);
	glColor3f(1.0, 0.0, 0.0);
	int x, y;
	float d;
	int r = 100;
	x = 0, y = r;
	d = 1.25 - r;
	//glVertex2i(x+r,y+r);
	//glVertex2i(y+r, x+r);
	//glVertex2i(-x+r, y+r);
	//glVertex2i(y+r, -x+r);
	//glVertex2i(x+r, -y+r);
	//glVertex2i(-y+r, x+r);
	//glVertex2i(-x+r, -y+r);
	//glVertex2i(-y+r, -x+r);
	glRectf(x+r, y+r, x +r+1, y+r+1);  //繪制矩形
	glRectf(y+r, x+r, y+r+ 1, x+r+1);  //繪制矩形	
	glRectf(-x+r, y+r, -x+r+1, y +r+ 1);  //繪制矩形	
	glRectf(y+r, -x+r, y+r+ 1, -x+r+ 1);  //繪制矩形	
	glRectf(x+r, -y+r, x+r+ 1, -y+r+ 1);  //繪制矩形	
	glRectf(-y+r, x+r, -y+r + 1, x+r+ 1);  //繪制矩形	
	glRectf(-x+r, -y+r, -x+r + 1, -y+r + 1);  //繪制矩形	
	glRectf(-y+r, -x+r, -y+r + 1, -x+r + 1);  //繪制矩形
	while (x <= y)
	{
		if (d <= 0)
		{
			d += 2 * x + 3;
		}
		else
		{
			d += 2 * (x - y) + 5; 
			y--;
		}
		x++;
		//cout<< x <<" "<<y<< endl;
		/*glVertex2i(x + r, y + r);
		glVertex2i(y + r, x + r);
		glVertex2i(-x + r, y + r);
		glVertex2i(y + r, -x + r);
		glVertex2i(x + r, -y + r);
		glVertex2i(-y + r, x + r);
		glVertex2i(-x + r, -y + r);
		glVertex2i(-y + r, -x + r);*/
		glRectf(x + r, y + r, x + r + 1, y + r + 1);  //繪制矩形
		glRectf(y + r, x + r, y + r + 1, x + r + 1);  //繪制矩形	
		glRectf(-x + r, y + r, -x + r + 1, y + r + 1);  //繪制矩形	
		glRectf(y + r, -x + r, y + r + 1, -x + r + 1);  //繪制矩形	
		glRectf(x + r, -y + r, x + r + 1, -y + r + 1);  //繪制矩形	
		glRectf(-y + r, x + r, -y + r + 1, x + r + 1);  //繪制矩形	
		glRectf(-x + r, -y + r, -x + r + 1, -y + r + 1);  //繪制矩形	
		glRectf(-y + r, -x + r, -y + r + 1, -x + r + 1);  //繪制矩形
	}
	//glEnd();
	glFlush();
}
void mouseClick(int btn, int state, int x, int y)
{
	if (btn == GLUT_LEFT_BUTTON && state == GLUT_DOWN)//點選左鍵
	{
		y = 400 - y;
		node temp(x, y);
		if (nodeNumber<2)
		{
          Line[nodeNumber] = temp;
		  nodeNumber++;
		  glColor3f(1.0, 0.0, 0.0);
		 // glViewport(0, 0, 400, 400);
		  glBegin(GL_POINTS);
		  glVertex2d(x, y);
		  glEnd();
		  glFlush();
		}
		
	}
	if (btn == GLUT_RIGHT_BUTTON && state == GLUT_DOWN)//點選右鍵
	{
		//drawLine(&Line[0]);
		finish = true;
		nodeNumber = 0;
	}
}
int main(int argc, char * argv[])//這是使用glut庫函數進行視窗管理
{
	glutInit(&argc, argv);//使用glut庫需要進行初始化
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);//設定視窗顯示模式,顔色模型和緩存,這裡是RGB顔色模型和單緩存
	glutInitWindowPosition(100, 100);//設定視窗的初始位置,螢幕左上角為原點,機關為像素
	glutInitWindowSize(400, 400);//設定視窗的大小
	glutCreateWindow("直線");//建立一個視窗,參數是視窗标題名 
	Initial();
	glutDisplayFunc(&drawLine1);//将myDisplay指定為目前視窗的顯示内容函數*/
	//glutMouseFunc(mouseClick);
	glutCreateWindow("圓");//建立一個視窗,參數是視窗标題名 
	Initial(); 
	glutDisplayFunc(&drawCircle);//将myDisplay指定為目前視窗的顯示内容函數							 
	glutMainLoop();//使視窗架構運作起來,使顯示回調函數開始工作
	return 0;
}
           

還有一個頭檔案:

#pragma once
#pragma once
struct node//點結構 
{
	double x;
	double y;
	node()
	{
		x = 0.0;
		y = 0.0;
	}
	~node() {}
	node(double xx, double yy)
	{
		x = xx;
		y = yy;
	}
	/*node & operator=(const node& a)
   {
		node m;
		m.x = a.x;
		m.y = a.y;
		return m;
	}*/
};

struct side//邊結構
{
	node a;
	node b;
	side(node aa, node bb)
	{
		a.x = aa.x;
		a.y = aa.y;
		b.y = bb.y;
		b.x = bb.x;
	}
	side(int n)
	{
		a.x = 0;
		a.y = 0;
		b.x = 0;
		b.y = 0;
	}
	side()
	{
		a.x = 0;
		a.y = 0;
		b.x = 0;
		b.y = 0;
	}
};
           

繼續閱讀