圆光栅化算法
简单方程产生圆弧
圆的函数方程与极坐标方程在此不再赘述
算法原理为离散计算,表示出圆;
但这种算法计算比较复杂,需要改进。
若采用极坐标画法则有
利用圆的八方对称性画圆
采用递推的方法:
void Bresenham_drawcircle(GLint R) { //默认原点是0,0 bresenham算法画圆
GLint x = 0;
GLint y = R;
GLint d = 3 - 2 * R;
glBegin(GL_POINTS);
glPointSize(pointsize);
while (x < ((int)(R*1.0 / (sqrt(2)))))
{
glVertex2i(x, y); //八分画圆
glVertex2i(-x, -y);
glVertex2i(-x, y);
glVertex2i(x, -y);
glVertex2i(y, -x);
glVertex2i(-y, -x);
glVertex2i(-y, x);
glVertex2i(y, x);
x = x + 1;
if (d >= 0) {
y = y - 1;
d = d + 4 * (x - y) + 10;
}
else {
d = d + 4 * x + 6;
}
}
glEnd();//结束
glFlush();
}
完整代码如下所示:
#include <GL/glut.h>
#include<iostream>
#include<math.h>
using namespace std;
GLfloat pointsize = 1.0f;
void init(void)
{
glClearColor(0.0, 0.0, 0.0, 0.0);//设置背景颜色为黑色
glShadeModel(GL_SMOOTH);//设置为光滑明暗模式
gluOrtho2D(-300.0, 300.0, -300.0, 300.0);///*设定映射区域,参数为(minX,maxX,minY,maxY),(minX,minY为原点);(maxX, maxY)为右上角的点* /
}
double D2R(double deg) {
return deg / 180.0 * 3.14159265;
}
void Bresenham_drawOneLine(GLint xs, GLint ys, GLint xe, GLint ye) {
GLint x = xs;
GLint y = ys;
int flag;//用以表示是否发生了交换
GLint dx = abs(xe - xs);
GLint dy = abs(ye - ys);
GLint sx = ((xe > xs)?1:-1);
GLint sy = ((ye > ys)?1:-1);
if (dy > dx)
{
swap(dx, dy);
flag = 1;
}
else
{
flag = 0;
}
cout << flag;
GLfloat Nerror =2*dy - dx;//开始在光栅点处,d=0,下一个点处d=k
for (int i = 1; i < dx; i++)
{
glBegin(GL_LINES);
//glColor3f(1.0f, 0.0f, 0.0f);
//cout << x << y << endl;
glVertex2i(x, y);
if (Nerror>=0)
{
if (flag)
{
x = x + sx;
}
else
{
y = y + sy;
}
Nerror = Nerror - 2*dx;
}
if (flag)
{
y = y + sy;
}
else
{
x = x + sx;
}
Nerror = Nerror + 2*dy;
}
glEnd();//结束
glFlush();
/*OpenGL指令不是立即执行的。它们首先被送到指令缓冲区,然后才被送到硬件执行。
glFlush都是强制将命令缓冲区的内容提交给硬件执行。*/
}
void Bresenham_drawcircle(GLint R) { //默认原点是0,0 bresenham算法画圆
GLint x = 0;
GLint y = R;
GLint d = 3 - 2 * R;
glBegin(GL_POINTS);
glPointSize(pointsize);
while (x < ((int)(R*1.0 / (sqrt(2)))))
{
glVertex2i(x, y); //八分画圆
glVertex2i(-x, -y);
glVertex2i(-x, y);
glVertex2i(x, -y);
glVertex2i(y, -x);
glVertex2i(-y, -x);
glVertex2i(-y, x);
glVertex2i(y, x);
x = x + 1;
if (d >= 0) {
y = y - 1;
d = d + 4 * (x - y) + 10;
}
else {
d = d + 4 * x + 6;
}
}
glEnd();//结束
glFlush();
}
void Bresenham_circle()
{
glClear(GL_COLOR_BUFFER_BIT); //清除所有的像素
glEnable(GL_LINE_STIPPLE); //点画线模式
glColor3f(1.0, 1.0, 1.0); //使用白色绘制该线段
for (int i = -300; i <= 300; i = i + 10)
{
Bresenham_drawOneLine(i, 300, i, -300);
}
for (int j = 300; j >= -300; j = j - 10)
{
Bresenham_drawOneLine(-300, j, 300, j);
}
glColor3f(1.0, 0.0, 1.0);
Bresenham_drawcircle(50);
glColor3f(0.0, 1.0, 1.0);
Bresenham_drawcircle(75);
glColor3f(1.0, 1.0, 0.0);
Bresenham_drawcircle(100);
glColor3f(1.0, 0.5, 0.5);
Bresenham_drawcircle(125);
glColor3f(0.0, 0.5, 1.0);
Bresenham_drawcircle(150);
glColor3f(1.0, 1.0, 1.0);
Bresenham_drawcircle(175);
glFlush();
}
int main(int argc, char ** argv)
{
/*初始化*/
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//单缓冲、RGB模式
glutInitWindowSize(800, 800);
glutInitWindowPosition(200, 200);
glutCreateWindow("Bresenham直线光栅化算法");//窗口标题
init();
/*绘制与显示*/
//glutReshapeFunc(myReshape);//窗口大小发生改变时采取的行为
glutDisplayFunc(Bresenham_circle);//将图传递给显示窗口,参数是描述的一个程序,即调用这个函数再送到显示窗口
glutMainLoop();//循环
return(0);//去掉这个函数,程序窗口一打开就马上关闭了
}