计算机图形学画圆算法源程序
- 格式:doc
- 大小:14.00 KB
- 文档页数:1
画圆环算法c程序全文共四篇示例,供读者参考第一篇示例:画圆环是计算机图形学中常见的基本图形之一,常用于游戏开发、动画制作等领域。
在计算机中,画圆环的算法有多种,其中最常用的是中点画圆算法。
本文将介绍使用C语言实现中点画圆算法的程序,并进行详细分析和讲解。
1. 算法原理中点画圆算法是一种简单而高效的算法,其基本原理是通过逐渐逼近圆形的方法,利用对称性和中点的位置进行迭代计算。
具体步骤如下:(1)给定圆的半径r和圆心坐标(x0, y0),设置初始点P(0, r)作为起点,并计算判别式d=1-r。
(2)在每次迭代中,分别取直线y=x和y=-x两侧的中点,分别计算两种情况下的判别式值,并根据判别式值的大小决定下一个中点的位置。
(3)重复进行上述步骤,直到计算完整个圆的一周。
2. C程序实现下面是使用C语言实现中点画圆算法的程序代码:```c#include <stdio.h>#include <graphics.h>void plot_circle_points(int x0, int y0, int x, int y) { // 绘制圆的八个对称点putpixel(x0 + x, y0 + y, WHITE);putpixel(x0 - x, y0 + y, WHITE);putpixel(x0 + x, y0 - y, WHITE);putpixel(x0 - x, y0 - y, WHITE);putpixel(x0 + y, y0 + x, WHITE);putpixel(x0 - y, y0 + x, WHITE);putpixel(x0 + y, y0 - x, WHITE);putpixel(x0 - y, y0 - x, WHITE);}void midpoint_circle(int x0, int y0, int r) { int x = 0, y = r;int d = 1 - r;plot_circle_points(x0, y0, x, y); while (x < y) {if (d < 0) {d = d + 2 * x + 3;x++;} else {d = d + 2 * (x - y) + 5;x++;y--;}plot_circle_points(x0, y0, x, y);}}delay(5000);closegraph();return 0;}```以上是一个简单的使用C语言实现中点画圆算法的程序代码。
【计算机图形学】基本图形元素:圆的⽣成算法圆的特征圆被定义为到给定中⼼位置(xc,yc)距离为r的点集。
圆⼼位于原点的圆有四条对称轴x=0,y=0, x=y和x=-y。
若已知圆弧上⼀点(x,y),可以得到其关于四条对称轴的其它7个点,这种性质称为⼋分对称性。
因此,只要扫描转换⼋分之⼀圆弧,就可以求出整个圆弧的象素集。
显⽰圆弧上的⼋个对称点的算法:void CirclePoints(int x,int y,int color){ Putpixel(x,y,color); Putpixel(y,x,color);Putpixel(-x,y,color); Putpixel(y,-x,color);Putpixel(x,-y,color); Putpixel(-y,x,color);Putpixel(-x,-y,color); Putpixel(-y,-x,color);}中点画圆算法果我们构造函数 F(x,y)=x2+y2-R2,则对于圆上的点有F(x,y)=0,对于圆外的点有F(x,y)>0,对于圆内的点F(x,y)<0 。
与中点画线法⼀样,构造判别式:d=F(M)=F(xp+1,yp-0.5)=(xp+1)2+(yp-0.5)2-R2若 d<0,则应取P1为下⼀象素,⽽且再下⼀象素的判别式为:d=F(xp+2,yp-0.5)=(xp+2)2+(yp-0.5)2-R2=d+2xp+3若d≥0,则应取P2为下⼀象素,⽽且下⼀象素的判别式为d=F(xp+2,yp-1.5)=(xp+2)2+(yp-1.5)2-R2=d+2(xp-yp)+5我们这⾥讨论的第⼀个象素是(0,R),判别式d的初始值为:d0=F(1,R-0.5)=1.25-R【算法流程图】【算法代码】void PaintArea::drawCircleMiddle(QPainter &painter,const QPoint ¢er, int r) {int x,y,deltax,deltay,d;x=0;y=r;deltax=3;deltay=2-3-3;d=1-r;while(x<y){if(d<0){d+=deltax;deltax+=2;x++;}else{d+=(deltax+deltay);deltax+=2;deltay+=2;x++;y++;}painter.drawPoint(center.x()+x,center.y()+y);painter.drawPoint(center.x()+x,center.y()-y);painter.drawPoint(center.x()-x,center.y()+y);painter.drawPoint(center.x()-x,center.y()-y);painter.drawPoint(center.x()+y,center.y()+x);painter.drawPoint(center.x()+y,center.y()-x);painter.drawPoint(center.x()-y,center.y()+x);painter.drawPoint(center.x()-y,center.y()-x);}}Bresenham画圆算法思想参见直线的Bresenham画法【算法流程图】【算法代码】void PaintArea::drawCircleBresenham(QPainter &painter,const QPoint ¢er, int r) {int x,y,delta,delta1,delta2,direction;x=0;y=r;delta=2*(1-r);while(y>=0){painter.drawPoint(x,y);if(delta<0){ delta1=2*(delta+y)-1;if(delta1<=0)direction=1; else direction=2; }else if(delta>0){ delta2=2*(delta-x)-1;if(delta2<=0)direction=2; else direction=3; }else direction=2;switch(direction){case 1:x++;delta+=2*x+1; break;case 2:x++; y--; delta+=2*(x-y+1); break;case 3:y--;delta+=(-2*y+1); break;}}}椭圆弧⽣成算法基本同圆弧算法,只是⽅程变得复杂F(x,y)=(bx)^2+(ay)^2-(ab)^2.对称性:4分对称,画第⼀象限分段依据:斜率为⼀点上段圆弧:下段圆弧:【椭圆中点算法流程图】【算法代码】void PaintArea::drawEllipseMiddle(QPainter &painter,int xCenter,int yCenter, int Rx, int Ry) {int Rx2=Rx*Rx;int Ry2=Ry*Ry;int twoRx2=2*Rx2;int twoRy2=2*Ry2;int p,x=0,y=Ry,px=0,py=twoRx2*y;void ellipsePlotPoints(QPainter&,int,int,int,int);ellipsePlotPoints(painter,xCenter,yCenter,x,y);//Region1p=round(Ry-(Rx2*Ry)+(0.25*Rx2));while(px<py){x++;px+=twoRy2;if(p<0)p+=Ry2+px;else{y--;py-=twoRx2;p+=Ry2+px-py;}ellipsePlotPoints(painter,xCenter,yCenter,x,y);}//Region2p=round(Ry2*(x+0.5)*(x+0.5)+Rx2*(y-1)*(y-1)-Rx2*Ry2);while(y>0){y--;py-=twoRx2;if(p>0)p+=Rx2-py;else{ x++;px+=twoRy2;p+=Rx2-py+px;}ellipsePlotPoints(painter,xCenter,yCenter,x,y);}}void ellipsePlotPoints(QPainter &painter,int xCenter,int yCenter,int x,int y){ painter.drawPoint(xCenter+x,yCenter+y);painter.drawPoint(xCenter-x,yCenter+y);painter.drawPoint(xCenter+x,yCenter-y);painter.drawPoint(xCenter-x,yCenter-y);}软件截图这个绘图软件是⽤QT写的,我会另外写⼀篇介绍编程结构,待续~转载请注明出处:。
计算机图形学实验报告实验二Bresenham算法画圆并填充学号:09009202 姓名:陶园成绩:东南大学计算机科学与工程学院二〇一一年十一月一.实验题目Bresenham算法画圆并填充二.算法思想1.首先,真实的线条是连续的,但是计算机中的线条是离散的,是由很多点组成的,那么画线的重点就是如何高效地找到这些离散的点来更好地画出想要的图形。
2.实验要求用Bresenham算法实现画圆。
那么首先先要了解Bresenham算法是一种什么算法。
经过查阅,我找到Bresenham直线算法和画圆算法。
直线是圆的基础。
Bresenham直线算法是用来描绘由两点所决定的直线的算法,它会算出一条线段在 n 维光栅上最接近的点。
这个算法只会用到较为快速的整数加法、减法和位元移位,常用于绘制电脑画面中的直线。
是计算机图形学中最先发展出来的算法。
Bresenham画圆算法又称中点画圆算法,与Bresenham 直线算法一样,其基本的方法是利用判别变量来判断选择最近的像素点,判别变量的数值仅仅用一些加、减和移位运算就可以计算出来。
为了简便起见,考虑一个圆心在坐标原点的圆,而且只计算八分圆周上的点,其余圆周上的点利用对称性就可得到。
Bresenham直线算法流程图圆的八对称性所以,只需要知道圆上的一个点的坐标 (x, y) ,利用八对称性,就能得到另外七个对称点的坐标。
和直线算法类似,Bresenham画圆算法也是用一系列离散的点来近似描述一个圆。
Bresenham画圆算法的流程图三.源代码#include "stdlib.h"#include "math.h"#include <gl/glut.h>//按坐标画点void draw(GLint xCoord, GLint yCoord){glBegin(GL_POINTS);//以点的形式glVertex2i(xCoord, yCoord);//在(xCoord, yCoord)坐标下画点glEnd();glFlush();//强制刷新}void Circle(GLint x,GLint y){int a=abs(x);//将x的绝对值赋给aint b=abs(y);//将y的绝对值赋给bint c=a*-1;//使c=a的相反数int d=b*-1;//使d=b的相反数draw(x, y); draw(y, x);draw(-x, y); draw(y, -x);draw(x, -y); draw(-y, x);draw (-x, -y); draw(-y, -x);//按照圆的对称性以圆心为对称点将四个象限的圆周画出for(int i=c;i<=a;i++){for(int j=d;j<=b;j++){draw(i,j);}}//以a,b,c,d为边界用点填充该圆}//主函数void BresenhamCircle(GLint r){int d, d1, d2, direct;GLint x,y;x=0;y=r;d = 2*(1-r);while(y>=0){Circle(x,y);if(d < 0){d1 = 2* (d+ y) -1;if(d1 <=0)direct = 1;elsedirect = 2;}else{if( d > 0){d2 = 2*(d-x)-1;if(d2 <= 0)direct = 2;elsedirect = 3;}elsedirect = 2;}switch(direct){case 1:x++;d+=2*x + 1;break;case 2:x++; y--;d+=2*(x-y+1) + 1;break;case 3:y--;d+=-2*y + 1;break;}}}void RenderScene(void){BresenhamCircle(50);//主函数调用}//当窗口大小改变时由GLUT函数调用void ChangeSize(GLsizei width, GLsizei Height){GLfloat aspectRatio;if (Height == 0){Height = 1;}glViewport(0, 0, width, Height);//指定视口矩形左下角glMatrixMode(GL_PROJECTION);//指定当前矩阵,对投影矩阵应用随后的矩阵操glLoadIdentity();// 装载单位矩阵aspectRatio = (GLfloat)width / (GLfloat) Height;if (width <= Height){glOrtho(-100.0, 100.0, -100.0 / aspectRatio, 100.0 / aspectRatio, 1.0, -1.0);}else{glOrtho(-100.0 * aspectRatio, 100.0 * aspectRatio, -100.0, 100.0, 1.0, -1.0);}glMatrixMode(GL_MODELVIEW);//指定当前矩阵,对模型视景矩阵堆栈应用随后的矩阵操作glLoadIdentity();// 装载单位矩阵}//主程序入口void main(void){glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//设置初始显示模式,指定单缓存窗口,指定RGB 颜色模式的窗口glutCreateWindow("圆");//创建窗口,窗口名称为“圆”glutDisplayFunc(RenderScene);//进行画图glutReshapeFunc(ChangeSize);//重画回调函数glutMainLoop();//进入GLUT事件处理循环,让所有的与“事件”有关的函数调用无限循环}四.结果截屏五.出现问题及解决方案1.对于如何填充整个圆一开始没有好的方法,后来决定每画一个点,就将该横坐标的所有纵坐标点画出,从下到上,整个填充圆从中间到两边形成。
在C++中,绘制圆形需要使用一些基本的几何和数学公式。
如果你想在一个二维平面上绘制一个圆形,你可以使用极坐标系中的公式:r = ρ * cos(θ)r = ρ * sin(θ)其中,ρ是半径,θ是角度(通常从0到2π)。
如果你想要在一个像素矩阵(例如二维数组)上绘制一个圆形,你可能需要写一个循环,检查每个像素是否在圆内。
以下是一个简单的C++代码示例,它在N*N的二维数组上绘制一个圆心在(N/2, N/2)的圆形。
该圆形的半径是N/2-1。
```cpp#include <iostream>#include <vector>void drawCircle(std::vector<std::vector<int>>& matrix, int n) {for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {double distance = std::sqrt((i - n / 2) * (i - n / 2) + (j - n / 2) * (j - n / 2));if (distance <= n / 2 - 1) {matrix[i][j] = 1; // Set the pixel to be in the circle} else {matrix[i][j] = 0; // Set the pixel to be outside the circle}}}}int main() {int n = 5; // Define the size of the circlestd::vector<std::vector<int>> matrix(n, std::vector<int>(n, 0)); // Initialize a n*n matrix with zerosdrawCircle(matrix, n); // Draw the circle// Now you can print the matrix or do something elsewith it.return 0;}```这个代码会创建一个N*N的二维数组,并使用上述算法将数组中的每个元素设置为1(如果该点在圆内)或0(如果该点在圆外)。
实验三圆生成算法的实现班级 学号 姓名 分数一、实验目的和要求:通过圆生成算法的上机调试,掌握:1.VC++图形函数的使用方法;2.圆和椭圆弧的生成原理;3.理解圆生成的基本原理,掌握几种常见的圆生成算法。
二、实验内容:1、以函数形式编写圆的生成算法,然后在VCAD绘图小系统中的绘图----圆子菜单下找到合适的程序修改点,通过调试来验证你编写的画圆算法的正确性。
2、以函数形式编写角度DDA椭圆弧生成算法,然后在VCAD 绘图小系统中的绘图----圆弧子菜单下找到合适的程序修改点,将本实验要求你编写的画圆弧算法插入工程文件中,通过调试来验证你编写的画圆弧算法的正确性。
3、利用中点画图算法,在屏幕上生成任意一段1/8弧。
利用图的对称性,将(1)题生成的圆弧扩展为一个整圆。
三、实验结果分析:1、圆被定义为到给定中心位置(x,y)距离为r的点集2、比较三种算法的结果:像素逼近效果由好到差依次为:B算法、DDA算法、中点算法执行速度由快到慢依次为:中点算法、DDA算法、B算法1.程序代码:void CMyView::DrawCir(int Start, int R, int a, int b){CDC* pDc=GetDC();int x,y;int e=Start-R;x=Start;y=R;pDc->SetPixel(y+a,x+b,RGB(0,0,255));pDc->SetPixel(-y+a,x+b,RGB(0,0,255));pDc->SetPixel(y+a,-x+b,RGB(0,0,255));pDc->SetPixel(-y+a,-x+b,RGB(0,0,255)); pDc->SetPixel(x+a,y+b,RGB(0,0,255));pDc->SetPixel(-x+a,y+b,RGB(0,0,255));pDc->SetPixel(x+a,-y+b,RGB(0,0,255));pDc->SetPixel(-x+a,-y+b,RGB(0,0,255)); if(e<0){e=e+2*x+3;x++;}pDc->SetPixel(x,y,RGB(0,0,255));while(x<y){if(e<0){e=e+2*x+3;x++;}else{e=e+2*(x-y)+5;x++;y--;}pDc->SetPixel(y+a,x+b,RGB(0,0,255)); pDc->SetPixel(-y+a,x+b,RGB(0,0,255)); pDc->SetPixel(y+a,-x+b,RGB(0,0,255)); pDc->SetPixel(-y+a,-x+b,RGB(0,0,255)); pDc->SetPixel(x+a,y+b,RGB(0,0,255)); pDc->SetPixel(-x+a,y+b,RGB(0,0,255)); pDc->SetPixel(x+a,-y+b,RGB(0,0,255)); pDc->SetPixel(-x+a,-y+b,RGB(0,0,255));}}void CMyView::OnDrawCir(){CMyView::DrawCir(0,50,200,300);}2.程序代码:#include<graphics.h>void circlepoints(int x,int y,int color){int m,n,xasp,yasp;float aspectratio;m=200;n=200;getaspectratio(&xasp,&yasp);aspectratio = xasp/yasp;putpixel(x+m,y*aspectratio+n,color);putpixel(y+m,x*aspectratio+n,color);putpixel(-y+m,x*aspectratio+n,color);putpixel(-x+m,y*aspectratio+n,color);putpixel(y+m,-x*aspectratio+n,color);putpixel(x+m,-x*aspectratio+n,color);putpixel(-x+m,-y*aspectratio+n,color);putpixel(-y+m,-x*aspectratio+n,color);}void midpointcircle(int r,int c){int x,y;float d;x=0; y=r; d=5.0/4-r;circlepoints(x,y,c);while(y>x){if(d<=0)d+=2.0*x+3;else{d+=2.0*(x-y)+5;y--;}x++;circlepoints(x,y,c);}}main(){int a,b;int graphdriver = DETECT;int graphmode = 0;initgraph(&graphdriver,&graphmode,””);cleardevice( );a= 200; b= 2;midpointcircle(a,b);getch( );closegraph( );}.1.运行结果:2.运行结果:。
#include <assert.h>#include <cmath>#include <iostream>#include <vector>#include <glut.h>using namespace std;typedef vector<int> list;vector<list> ls, cs;int old_x, old_y, new_x, new_y, cx, cy, cr; int mouse_type;/* breseman画线算法*/void line(int x1, int y1, int x2, int y2) { glBegin(GL_POINTS);if (x1==x2 && y1==y2) {glVertex2i(x1, y1);return;}if (x1>x2) {swap(x1, x2);swap(y1, y2);}glVertex2d(x1, y1);int dy=abs(y2-y1);int dx=abs(x2-x1);if (dx>=dy) {int incy=(dy!=0?dy/(y2-y1):0);int p=2*dy-dx;int dy2=2*dy;int dd2=2*(dy-dx);int x, y=y1;for (x=x1+1; x<=x2; ++x) {if (p<0) {glVertex2i(x, y);p+=dy2;}else {y+=incy;glVertex2i(x, y);p+=dd2;}}}else {if (y1>y2) {swap(x1, x2);swap(y1, y2);}int incx=(dx!=0?dx/(x2-x1):0);int p=2*dx-dy;int dx2=2*dx;int dd2=2*(dx-dy);int x=x1, y;for (y=y1+1; y<=y2; ++y) {if (p<0) {glVertex2i(x, y);p+=dx2;}else {x+=incx;glVertex2i(x, y);p+=dd2;}}}glEnd();}/* 中点圆算法*/void circle(int cx, int cy, int r) { int x=0, y=r;float p=1.25-r;while (x<=y) {glBegin(GL_POINTS);glVertex2i(cx+x, cy+y);glVertex2i(cx-x, cy+y);glVertex2i(cx-x, cy-y);glVertex2i(cx+x, cy-y);glVertex2i(cx+y, cy+x);glVertex2i(cx-y, cy+x);glVertex2i(cx-y, cy-x);glVertex2i(cx+y, cy-x);glEnd();if (p<0) {++x;p+=2*x+1;}else {p+=2*x-2*y+5;++x;--y;}}}void draw(){int i;for (i=0; i<ls.size(); ++i)line(ls[i][0], ls[i][1], ls[i][2], ls[i][3]);for (i=0; i<cs.size(); ++i)circle(cs[i][0], cs[i][1], cs[i][2]);if(mouse_type == 1)line(old_x, old_y, new_x, new_y);if(mouse_type == 3)circle(cx, cy, cr); //圆上的点和半径}void display() {glClear(GL_COLOR_BUFFER_BIT);glColor3i(0, 0, 0);draw();glutSwapBuffers();}void keyboard( unsigned char key, int x, int y) {switch (key) {case 27:exit (0);break;case 'a':case 'A':break;default:if (key<='z' && key>='a' || key<='Z' && key>='A' || key<='9' && key>='0'){ cout<<char(key);}else{cout<<"\n字符码为"<<static_cast<int>(key);display();}}}void mouseclick( int button, int state, int x, int y ){cout<<"("<<x<<","<<y<<")";switch ( button ) {case GLUT_LEFT_BUTTON:if ( state == GLUT_DOWN ) {cout<<"左键被按下";old_x = x;old_y = 600-y;mouse_type = 1;}else if ( state == GLUT_UP ) {cout<<"左键被松开";list l;l.push_back(old_x);l.push_back(old_y);l.push_back(x);l.push_back(600-y);ls.push_back(l);mouse_type = 0;glutPostRedisplay();for(int i=0; i<ls.size(); ++i)cout<<endl<<"line_"<<i<<": "<<ls[i][0]<<","<<ls[i][1]<<" "<<ls[i][2]<<","<<ls[i][3];}break;case GLUT_MIDDLE_BUTTON:break;case GLUT_RIGHT_BUTTON:if ( state == GLUT_DOWN ) {cout<<"右键被按下";cx = x;cy = 600-y;mouse_type = 3;}else if ( state == GLUT_UP ) {cout<<"右键被松开";list l;l.push_back(cx);l.push_back(cy);cr=int(sqrt(double(x-cx)*(x-cx)+(600-y-cy)*(600-y-cy))+0.5);l.push_back(cr);cs.push_back(l);mouse_type = 2;glutPostRedisplay();for(int i=0; i<cs.size(); ++i)cout<<endl<<"circle_"<<i<<": "<<cs[i][0]<<","<<cs[i][1]<<" "<<cs[i][2];}break;}}void screenmotion(int x, int y){if(mouse_type == 1){new_x = x;new_y = 600-y;cout<<endl<<"new-line:"<<old_x<<","<<old_y<<" "<<new_x<<","<<new_y<<endl; }else if(mouse_type == 3){cr=int(sqrt(double(x-cx)*(x-cx)+(600-y-cy)*(600-y-cy))+0.5);cout<<endl<<"new-circle: "<<cx<<","<<cy<<" "<<cr<<endl;}glutPostRedisplay();}void init() {glClearColor(0.2, 0.5, 0.8, 0.0); //背景颜色glMatrixMode(GL_PROJECTION);gluOrtho2D(-1.0, 600, 0.0, 601);}int main(int argc, char** argv) {glutInit(&argc, argv);glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);glutInitWindowPosition(100, 50); //图框在屏幕的位置glutInitWindowSize(600, 600); //边框大小glutCreateWindow("图元算法"); //图框边显示的字init();glutDisplayFunc(display);glutMotionFunc(screenmotion);glutKeyboardFunc( keyboard );glutMouseFunc( mouseclick );glutMainLoop();return 0;}。