基于EASYX库扫描线算法C++实现

基于EASYX库扫描线算法C++实现


扫描线算法的基本原理

基于EASYX库扫描线算法C++实现_第1张图片

* 作者在扫描线算法的基础上自己设计的更易于理解的地物填充绘制算法

流程图

基于EASYX库扫描线算法C++实现_第2张图片

代码

#include<graphics.h>
//#include
#include<iostream>
using namespace std;
//-----------------------------草图形-----------------------------//
void Grass(double x, double y, double hight, double width)
{
	setlinecolor(GREEN);
	line(x, y, x - hight / 2, y - width);
	line(x, y, x, y - width);
	line(x, y, x + hight / 2, y - width);
}
//-----------------------------林图形-----------------------------//
void Tree(double x, double y, double hight, double width)
{
	setlinecolor(GREEN);
	line(x, y, x - hight / 2, y - width);
	line(x, y, x + hight / 2, y - width);
	line(x, y - width, x, y + width);
}
//------------------求解方程的k,b值---------------------//
void function_line(double x1, double y1, double x2, double y2, double &k, double &b)
{
	if (x2 - x1 == 0) {
		k = -9999;
		b = x1;
		return;
	}
	k = (y2 - y1) / (x2 - x1);
	b = y1 - k * x1;
}
//------------------返回直线的y----------------------//
double solve_y(double k, double b, double x)
{
	return k * x + b;
}
//------------------返回直线的x----------------------//
double solve_x(double k, double b, double y)
{
	if (k == -9999)
		return b;
	return (y - b) / k;
}
//-------------------找出扫描线与边界相交的点,并储存在suitable_x[]中,把相交的点数储存在n中--------------//
//x[]-----------顶点x坐标
//y[]-----------顶点y坐标
//N-------------顶点的个数
//now_y---------当前的扫描线y
//suitable_x[]--扫描线与边界相交的点的x坐标
//n-------------相交的点数
void Suitable_x(double x[], double y[],int N, double now_y, double suitable_x[], int &n) 
{
	n = 0;
	int t = 0;
	double k, b;
	for (int i = 0; i < N; i++)
	{
		if (i == N - 1)
		{
			if (y[i] < now_y&& now_y <= y[0] || y[0] < now_y&& now_y <= y[i])//判断直线是否过最后一条直线
			{
				function_line(x[0], y[0], x[i], y[i], k, b);
				suitable_x[t++] = solve_x(k, b, now_y);
			}
		}
		else
		{
			if (y[i] < now_y&& now_y <= y[i + 1] || y[i + 1] < now_y&& now_y <= y[i])  //判断扫描线过哪条直线的范围
			{
				function_line(x[i], y[i], x[i + 1], y[i + 1], k, b);
				suitable_x[t++] = solve_x(k, b, now_y);//把交点的x储存在suitable_x[]中
			}
		}
	}
	n = t;
}
void sort_min_to_max(double suitable_x[],int n)        //排序----从小到大排序
{
	double temp;
	for (int i = 0; i < n - 1; i++)
	{
		for (int j = i + 1; j < n; j++) {
			if (suitable_x[i] > suitable_x[j]) {
				double temp = suitable_x[i];
				suitable_x[i] = suitable_x[j];
				suitable_x[j] = temp;
			}
		}
	}
}
double find_max(double elem[],int N)    //输出最大的元素值
{
	double max = elem[0];
	for (int i = 0; i < N; i++)
	{
		if (elem[i] > max)
		{
			max = elem[i];
		}
	}
	return max;
}
double find_min(double elem[],int N)     //输出最小的元素值
{
	double min = elem[0];
	for (int i = 0; i < N; i++)
	{
		if (elem[i] < min)
		{
			min = elem[i];
		}
	}
	return min;
}
int main()
{
	cout << "-----------------------------------------地物填充绘制算法--------------------------------------------\n\n";
	cout << "                                                                                        创建人:李景勃\n";
	cout << "                                                                                          时间:2018年10月24日\n";
	cout << "           10月24日是全部程序员值得开心的节日,也是自己重要的日子,23号完成,祝福全部程序员们!!!       \n\n\n";

	int N,ch;
	char color;
	double x[50],y[50];
	cout << "输入填充的多边形的顶点数:";
	cin >> N;
	cout << "依次输入地物的顶点坐标:";
	for (int i = 0; i < N; i++)
	{
		cout << "输入第" << i+1 << "个顶点的坐标:" << endl;
		cout << "x,y:";
		scanf_s("%lf,%lf",&x[i],&y[i]);
		/*cout << "x = "; cin >> x[i];
		cout << "y = "; cin >> y[i];*/
	}
	cout << "选择您填充的地物:  整个区域单颜色充填---请按0;草地---请按 1;林地---请按 2 ;   "; cin >> ch;
	if (ch == 0)
	{
		cout << "请选择颜色:BLACK 黑,DARKGRAY 深灰绿色   BLUE 蓝 LIGHTBLUE 亮蓝:GREEN 绿  CYAN 青  RED   红  MAGENTA 紫   BROWN 棕   YELLOW 黄   LIGHTGRAY 浅灰---注意是大写的英文\n ";
		cout << "如果想让颜色变亮请在颜色的前面加上LIGHT  \n";
		cout << "请输入颜色:";
		cin >> color;
	}


	initgraph(find_max(x, N)+100, find_max(y, N)+100);
	//int N = 9;
	//double x[50] = { 200,100,150,170,400,350,300,250,270 };
	//double y[50] = { 200,300,400,250,350,300,250,100,270 };
	double new_y[50] = { 0 };
	int n = 0;
	double suitable_x[10];
	//草的参数
	int hight = 12,
		width = 6;
	int space = 4;  //草之间的间隔


	setbkcolor(WHITE);  //设置背景色
	cleardevice();  //用背景色填充屏幕
	setlinecolor(BLACK);	//多边形的线条颜色
	for (int i = 0; i < N; i++)   //逆时针顶点相连构成闭合多边形
	{
		if (i == N - 1)
		{
			line(x[i], y[i], x[0], y[0]);
		}
		else
		{
			line(x[i], y[i], x[i + 1], y[i + 1]);
		}
	}

	double min_y = find_min(y,N),
		max_y = find_max(y,N);
	switch (ch)
	{
	case 0:
		//-------------------------像素填充面积-------------------------//
		for (int now_y = min_y; now_y <= max_y; now_y++)
		{
			Suitable_x(x, y, N, now_y, suitable_x, n);
			sort_min_to_max(suitable_x, n);  //从小到大排序
			for (int i = 0; i < n; i += 2)
			{
				for (int now_x = suitable_x[i]; now_x < suitable_x[i + 1]; now_x++)//确定在扫描线上,要填充的范围
				{
					putpixel(now_x, now_y, color);
				}
			}
		}
		break;
	case 1:
		//-------------------------草填充-------------------------//
		for (int now_y = min_y + width + space; now_y <= max_y; now_y += width + space)
		{
			Suitable_x(x, y, N, now_y, suitable_x, n);
			sort_min_to_max(suitable_x, n);  //从小到大排序
			for (int i = 0; i < n; i += 2)
			{
				for (int now_x = suitable_x[i] + hight / 2 + space + space; now_x < suitable_x[i + 1] - hight / 2; now_x += hight + space)//确定在扫描线上,要填充的范围
				{
					Grass(now_x, now_y, hight, width);
					Sleep(60);
				}
			}
		}
		break;
	case 2:
		//-------------------------树填充-------------------------//
		for (int now_y = min_y + width + space; now_y <= max_y; now_y += 2 * width + space)
		{
			Suitable_x(x, y, N, now_y, suitable_x, n);
			sort_min_to_max(suitable_x, n);  //从小到大排序
			for (int i = 0; i < n; i += 2)
			{
				double longth = suitable_x[i + 1] - suitable_x[i]-space;
				int num = longth / (hight+space);
				//double space_tmp = longth - num * (hight + space);
				//double space_ = space + space / num;
				for (int now_x = suitable_x[i] + hight / 2 +space+space; now_x < suitable_x[i + 1] - hight / 2&&num--; now_x += hight + space)//确定在扫描线上,要填充的范围
				{
					Tree(now_x, now_y, hight, width);
					Sleep(60);
				}
			}
		}
		break;
	default:
		cout << "填充失败!!!" << endl;
		break;
	}
	//closegraph();//关闭画框
	system("pause");
	return 0;
}

实现效果

基于EASYX库扫描线算法C++实现_第3张图片

基于EASYX库扫描线算法C++实现_第4张图片
基于EASYX库扫描线算法C++实现_第5张图片
基于EASYX库扫描线算法C++实现_第6张图片

谢谢阅读,欢迎来一起交流,一起学习!!

你可能感兴趣的:(计算机图形学)