中点画圆法
一、在进行圆的扫描转换时,首先应注意,只要能生成8分圆,那么圆的其他部分可以通过一系列的简单反射变换得到。那么已知圆心在原点的圆上的一点的(x,y),那么根据对称性可以得到七个8分圆的对应的点(y,x),(y,-x),(x,-y),(-x,-y),(-y,-x),(-y,x),(-x,y).因此只需要构造八分圆。
如果此时点的位置为(X1,Y1),那么下一个点位置只可能是(X1+1,Y1)或者(X1+1,Y1-1).
对于构造函数 F(x,y)=x^2+y^2-R^2,讨论F(X,Y)的值与零的大小关系,如果F(X,Y)>0,那么使用(X1+1,Y1-1),F(X,Y)<0,那么使用(X1+1,Y1+1)。
如果构造判别式d=F(M)=F(X1+1,Y1-0.5)=(X1+1)^2+(Y1-0.5)^2-R^2;
d<0,应取(X1+1,Y1)为下一个点,下一个像素的为d=d+2*x+3;
d>=0应取(X1+1,Y1-1)为下一个点,下一个像素的d=d+(2*x+3)+(-2*y+2);
实现代码
#include<GL\glut.h>
#include<iostream>
#include<cmath>
using namespace std;
void setpoint(int x0, int y0, int x, int y)//同时绘制八个点(对称)
{
glColor3f(1.0f, 1.0f, 0.0);
glVertex2f((x0 + x), (y0 + y));
glVertex2f((x0 + y), (y0 + x));
glVertex2f((x0 + y), (y0 - x));
glVertex2f((x0 + x), (y0 - y));
glVertex2f((x0 - x), (y0 - y));
glVertex2f((x0 - y), (y0 - x));
glVertex2f((x0 - y), (y0 + x));
glVertex2f((x0 - x), (y0 + y));
}
void midpointcircle(int x0, int y0, int r)//中点画圆法
{
int x = 0;
int y = r;
int d = 1 - r; // 为了简化算法,摆脱浮点数,所以对d进行取整计算所以从1.25-r变到了1-r
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_POLYGON);
setpoint(x0, y0, x, y);
while (x < y)
{
if (d < 0)
{
d += 2 * x + 3;
}
else
{
d += 2 * (x - y) + 5;
y--;
}
x++;
setpoint(x0, y0, x, y);
}
glEnd();
glFlush();
}
void ChangeSize(GLsizei w, GLsizei h)
{
if (h == 0) h = 1;
// 设置视区尺寸
glViewport(0, 0, w, h);
// 重置坐标系统
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// 建立修剪空间的范围
if (w <= h)
glOrtho(0.0f, 250.0f, 0.0f, 250.0f*h / w, 1.0, -1.0);
else
glOrtho(0.0f, 250.0f*w / h, 0.0f, 250.0f, 1.0, -1.0);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
int x0 = 100, y0 = 100, r = 60;
midpointcircle(x0, y0, r);
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(200, 200);
glutInitWindowSize(400, 400);
glutCreateWindow("张扬的OpenGl");
glutDisplayFunc(display);
glutReshapeFunc(ChangeSize);
glClearColor(0.8,0.1 ,0.1, 0.0); //设置窗口背景的颜色
glutMainLoop();
return 0;
}
实现结果