计算机图形学实验(三)——中点画圆算法实现及其源码

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40755094/article/details/84146529

1.中点画圆算法简介:(以第一象限内靠近Y轴的1/8圆为例)

  • 由于圆的对称性,只需要考虑1/8的圆上的点。举例:(x,y),(y,x),(x,y),(y,x),(-x,y),(-y,x),(x,-y),(y,-x),(-x,-y),(-y,-x).
  • 引入构造函数:F(x,y)=x^2+y^2-r^2F(x,y)>0,F(x,y)=0,F(x,y)<0 分别表示点在圆外,圆上,圆内。
  • 如图3-8所示:P(x_{k},y_{k}),P_{1}(x_{k+1},y_{k}),P_{2}(x_{k+1},y_{k-1}),M(x_{k+1},y_{k}-0.5).M是P1和P2中点。
  • 当F(M)<0时,说明M在圆内,进而得知P1离圆弧更近;否则P2离圆弧更近(相等的情况,P1,P2都可以).
  • 构造判别式:d=F(M).(详细内容可参考图片)

                                     

 

2.源码展示:

#include<iostream>
#include<graphics.h>
#include <iomanip>
#include<conio.h>
using namespace std;
#define x0 400
#define y0 300                                                           //定义全局变量x0,y0:坐标轴中心(x0,y0)
void Middle_point_draw_circle(int x1, int y1, int r) {
	int d0, x = 0, y = r;
	d0 = 1 - r;
	cout << "*初始点为:   (" << x << "," << y << ")" << endl;        //输出初始点坐标(x,y)
	cout << "******P(k)  (X(k+1),Y(k+1))" << endl;
	Sleep(50);
	while(x<y) {
		if (d0 >= 0) {
			cout << noshowpos << fixed << setw(10) << setfill('*') << d0<< "    ";
			//加上头文件iomanip.输出格式调整:非负数不显示正号,输出宽度为10字符,宽度不足则右边用填充字符填充
			d0 = d0 + 2 * (x - y) + 5;                               //d0一定要先比x,y更新
			x = x + 1;                                               //因为d0表达式中的x,y是上一个点
			y = y-1;
			/*
			cout << "(" << (x + x1) << "," << (y + y1) << ")" << "(" << (-x + x1) << "," << (y + y1) << ")";
			cout << "(" << (y + x1) << "," << (x + y1) << ")" << "(" << (-y + x1) << "," << (x + y1) << ")";
			cout << "(" << (x + x1) << "," << (-y + y1) << ")" << "(" << (-x + x1) << "," << (-y + y1) << ")";
			cout << "(" << (y + x1) << "," << (-x + y1) << ")" << "(" << (-y + x1) << "," << (-x + y1) << ")"<<endl;
			*/
			putpixel(((x + x1) + x0), (y0-(y + y1)),RED);            //(x,y)
			putpixel(((-x + x1) + x0), (y0 - (y + y1)), RED);        //(-x,y)
			putpixel(((y + x1) + x0), (y0 - (x + y1)), RED);         //(y,x)
			putpixel(((-y + x1) + x0), (y0 - (x + y1)), RED);        //(-y,x)
			putpixel(((x + x1) + x0), (y0 - (-y + y1)), RED);        //(x,-y)
			putpixel(((-x + x1) + x0), (y0 - (-y + y1)), RED);       //(-x,-y)
			putpixel(((y + x1) + x0), (y0 - (-x + y1)), RED);        //(y,-y)
			putpixel(((-y + x1) + x0), (y0 - (-x + y1)), RED);       //(-y,-x)
			Sleep(150);
		}
		else {
			cout << noshowpos << fixed << setw(10) << setfill('*') << d0 << "    ";
			d0 = d0 + 2 * x + 3;
			x = x + 1;
			y = y ;
			/*
			cout << "(" << (x + x1) << "," << (y + y1) << ")" << "(" << (-x + x1) << "," << (y + y1) << ")" ;
			cout << "(" << (y + x1) << "," << (x + y1) << ")" << "(" << (-y + x1) << "," << (x + y1) << ")";
			cout << "(" << (x + x1) << "," << (-y + y1) << ")" << "(" << (-x + x1) << "," << (-y + y1) << ")";
			cout << "(" << (y + x1) << "," << (-x + y1) << ")" << "(" << (-y + x1) << "," << (-x + y1) << ")"<<endl;
			*/
			putpixel(((x + x1) + x0), (y0 - (y + y1)), RED);         //(x,y)
			putpixel(((-x + x1) + x0), (y0 - (y + y1)), RED);        //(-x,y)
			putpixel(((y + x1) + x0), (y0 - (x + y1)), RED);         //(y,x)
			putpixel(((-y + x1) + x0), (y0 - (x + y1)), RED);        //(-y,x)
			putpixel(((x + x1) + x0), (y0 - (-y + y1)), RED);        //(x,-y)
			putpixel(((-x + x1) + x0), (y0 - (-y + y1)), RED);       //(-x,-y)
			putpixel(((y + x1) + x0), (y0 - (-x + y1)), RED);        //(y,-y)
			putpixel(((-y + x1) + x0), (y0 - (-x + y1)), RED);       //(-y,-x)
			Sleep(150);
		}
	}
}
int main() {
	int x1, y1, r;
	cout << "请输入中点画圆算法圆心坐标(x1,y1)和圆的半径r" << endl;
	cin >> x1 >> y1 >> r;
	initgraph(x0 * 2, y0 * 2);		         //坐标轴X
	line(x0, 0, x0, y0 * 2);			 //初始化图形窗口大小
	line(0, y0, x0 * 2, y0);			 //坐标轴Y
	Middle_point_draw_circle(x1, y1, r);             //中点画圆算法
	_getch();                                        //等待一个任意输入结束
	closegraph();                                    //关闭图形窗口
	//Middle_point_draw_circle(x1, y1, r);
	//_getch();
	return 0;
}


3.结果展示:

 1)这个是测试输出的结果(代码里注释掉了)  

2)画图结果:(由于给定坐标太小,画圆也较小)

4.代码心得:

    1) 加入头文件#include <iomanip.h>,实现使用操作运算子来控制输出格式。

    2) 计算初始的pk时,p0=1.25-r,为简化运算,改为p0=1-r,不影响结果正确性。

    3) 注意pk的正负号影响的是(x(k+1,)y(k+1)),而不是(x(k),y(k)).

    4) 循环终止条件时x==y时,用while循环比较好。

    5)画圆的时候是八个方向同时进行,挺有趣的。

    6) 水平有限,代码以及讲述有误之处,欢迎指正。

猜你喜欢

转载自blog.csdn.net/qq_40755094/article/details/84146529