计算机图形学扫描算法

// saomiaofa20-3-30-1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include<gl/GLUT.H>
#include<math.h>
#include<string>
#include <iostream>
using namespace std;

const int POINTNUM = 7;
typedef struct XET {
    
    
	float x;
	float dx, ymax;
	struct XET* next;
}AET,NET;

struct point {
    
    
	float x;
	float y;
	point(){
    
    }
	point(float x, float y) {
    
    
		this->x = x;
		this->y = y;
	}
}polypoint[POINTNUM] = {
    
    };

void input() {
    
    
	cout << "Please input point:" << endl;
	for (int i = 0; i < POINTNUM; i++) {
    
    
		cin >> polypoint[i].x >> polypoint[i].y;
	}
}

void saomiao() {
    
    
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_POINTS);
	glColor3f(0.8, 0.5, 0.5);
	int MaxY = 0;
	int MinY = 1000;
	for (int i = 0; i < POINTNUM; i++) {
    
    
		if (polypoint[i].y > MaxY) {
    
    
			MaxY = polypoint[i].y;
		}
		if (polypoint[i].y < MinY) {
    
    
			MinY = polypoint[i].y;
		}
	}
	//初始化AET NET表
	AET *pAET = new AET;
	pAET->next = NULL;
	NET *pNET[1024];
	for (int i = MinY; i <= MaxY; i++) {
    
    
		pNET[i] = new NET;
		pNET[i]->next = NULL;
	}
	//填NET表
	for (int i = MinY; i <= MaxY; i++)
	{
    
    
		for (int j = 0; j < POINTNUM; j++)
		{
    
    
			if (polypoint[j].y == i)
			{
    
    
				if (polypoint[(j - 1 + POINTNUM) % POINTNUM].y > polypoint[j].y) //左边的点
				{
    
    
					NET *p = new NET;
					p->x = polypoint[j].x;
					p->ymax = polypoint[(j - 1 + POINTNUM) % POINTNUM].y;
					p->dx = (polypoint[(j - 1 + POINTNUM) % POINTNUM].x - polypoint[j].x) / (polypoint[(j - 1 + POINTNUM) % POINTNUM].y - polypoint[j].y);
					p->next = pNET[i]->next;
					pNET[i]->next = p;
				}

				if (polypoint[(j + 1 + POINTNUM) % POINTNUM].y > polypoint[j].y)  //右边的点
				{
    
    
					NET *p = new NET;
					p->x = polypoint[j].x;
					p->ymax = polypoint[(j + 1 + POINTNUM) % POINTNUM].y;
					p->dx = (polypoint[(j + 1 + POINTNUM) % POINTNUM].x - polypoint[j].x) / (polypoint[(j + 1 + POINTNUM) % POINTNUM].y - polypoint[j].y);
					p->next = pNET[i]->next;
					pNET[i]->next = p;
				}
			}
		}
	}
	//建立更新AET
	for (int i = MinY; i <= MaxY; i++){
    
    	
		//计算新的交点x,更新AET
		NET *p = pAET->next;
		while (p != NULL)  
		{
    
    
			p->x = p->x + p->dx;
			p = p->next;
		}

		//更新后新AET先排序
		//断表排序,不再开辟空间
		AET *tq = pAET;
		p = pAET->next;
		tq->next = NULL;
		while (p != NULL)  //按x排序
		{
    
    
			while (tq->next != NULL && p->x >= tq->next->x)
			{
    
    
				tq = tq->next;
			}

			NET *s = p->next;
			p->next = tq->next;
			tq->next = p;
			p = s;
			tq = pAET;
		}

		//(改进算法)先从AET表中删除ymax==i的结点
		AET *q = pAET;
		p = q->next;
		while (p != NULL)
		{
    
    
			if (p->ymax == i)
			{
    
    
				q->next = p->next;
				delete p;
				p = q->next;
			}
			else
			{
    
    
				q = q->next;
				p = q->next;
			}
		}

		//将NET中的新点加入AET,并用插入法按X值递增排序
		p = pNET[i]->next;
		q = pAET;
		while (p != NULL)
		{
    
    
			while (q->next != NULL && p->x >= q->next->x)
			{
    
    
				q = q->next;
			}

			NET *s = p->next;
			p->next = q->next;
			q->next = p;
			p = s;
			q = pAET;
		}
		p = pAET->next;
		while (p && p->next)
		{
    
    
			for (float j = p->x; j <= p->next->x; j++)	
				glVertex2f(j, i);
				//pDC->SetPixel(static_cast<int>(j), i, RGB(255, 0, 0));
			p = p->next->next;//考虑端点情况
		}
	}
	NET *phead = NULL;
	NET *pnext = NULL;
	//释放活跃边表
	phead = pAET;
	while (phead != NULL)
	{
    
    
		pnext = phead->next;
		delete phead;
		phead = pnext;
	}
	glEnd();
	glFlush();
}

int main(int argc, char **argv)
{
    
    	
	input();
	glutInit(&argc, argv);//窗口的初始化
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);//窗口谋模式的设定
	glutInitWindowPosition(50, 100);//窗口位置的设定
	glutInitWindowSize(400, 300);//窗口大小的设定
	glutCreateWindow("多边形的扫描填充");
	glClearColor(1.0, 1.0, 1.0, 0.0);
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 600.0, 0.0, 450.0);
	glutDisplayFunc(saomiao);//调用函数
	glutMainLoop();
	return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门提示: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_42964413/article/details/105727788