计算机图形学-改进的有效边表算法

利用AET表对扫描线进行存储

利用C++实现,VS2019测试通过,使用了glut库

#include<GL/glut.h>
#include<iostream>
#include<math.h>
#include<stdlib.h>

using namespace std;

#define WINDOW_WIDTH 400
#define WINDOW_HEIGHT 400

//AET表数据结构
typedef struct tEdge
{
	int ymax;//扫描线的最大值
	float xi, dx;//当前x值和导数dx
	struct tEdge* next;
} Edge;

//点坐标的数据结构
struct Point
{
	int x;
	int y;
}point;

//初始化窗口函数
void init(void)
{
	glClearColor(1.0, 1.0, 1.0, 0.0);//设置背景颜色为白色
	glMatrixMode(GL_PROJECTION);
	gluOrtho2D(0.0, 400.0, 0.0, 400.0);//投影视图
	glLineWidth(12.0f);   //直线宽度
}

//画点函数
void setPixel(GLint x, GLint y)
{
	glBegin(GL_POINTS);
	glVertex2i(x, y);
	glEnd();
	glFlush();
}

void insertEdge(Edge* list, Edge* edge)
{
	Edge* p, * q = list;
	p = q->next;
	while (p != NULL)
	{
		if (edge->xi < p->xi)
			p = NULL;
		else
		{
			q = p;
			p = p->next;
		}
	}
	edge->next = q->next;
	q->next = edge;
}

int yNext(int k, int cnt, Point* pts)
{
	int j;
	if ((k + 1) > (cnt - 1))
		j = 0;
	else
		j = k + 1;
	while (pts[k].y == pts[j].y)
	{
		if ((j + 1) > (cnt - 1))
			j = 0;
		else
			j++;
		return (pts[j].y);
	}
}

void makeEdgeRec(Point lower, Point upper,int yComp, Edge* edge, Edge* edges[])
{
	edge->dx = (float)(upper.x - lower.x) / (upper.y - lower.y);
	edge->xi = lower.x;
	if (upper.y < yComp)
	{
		edge->ymax = upper.y - 1;
	}
	else
		edge->ymax = upper.y;
	insertEdge(edges[lower.y], edge);
}

void buildEdgeList(int num, Point* pts, Edge* edges[])
{
	Edge* edge;
	Point v1, v2;
	int i, yPrev = pts[num - 2].y;
	v1.x = pts[num - 1].x;
	v1.y = pts[num - 1].y;
	for (i = 0; i < num; i++)
	{
		v2 = pts[i];
		if (v1.y != v2.y)
		{
			edge = new Edge[num];
			if (v1.y < v2.y)
			{
				makeEdgeRec(v1, v2, yNext(i, num, pts), edge, edges);

			}
			else
				makeEdgeRec(v2, v1, yPrev, edge, edges);
		}
		yPrev = v1.y;
		v1 = v2;
	}
}

void buildActiveList(int scan, Edge* active, Edge* edges[])
{
	Edge* p, * q;
	p = edges[scan]->next;
	while (p)
	{
		q = p->next;
		insertEdge(active, p);
		p = q;
	}
}

void fillScan(int scan, Edge* active)
{
	Edge* p1, * p2;
	int i;
	p1 = active->next;
	while (p1)
	{
		p2 = p1->next;
		for (i = p1->xi; i < p2->xi; i++)
		{
			setPixel((int)i, scan);
		}
		p1 = p2->next;
	}
}

void deleteAfter(Edge* q)
{
	Edge* p = q->next;
	q->next = p->next;
	delete(p);
}

void updateActiveList(int scan, Edge* active)
{
	Edge* q = active, * p = active->next;
	while (p)
	{
		if (scan >= p->ymax)
		{
			p = p->next;
			deleteAfter(q);
		}
		else
		{
			p->xi = p->xi + p->dx;
			q = p;
			p = p->next;
		}
	}
}

void resortActiveList(Edge* active)
{
	Edge* q, * p = active->next;
	active->next = NULL;
	while (p)
	{
		q = p->next;
		insertEdge(active, p);
		p = q;
	}
}

void scanFill(int num, Point* pts)
{
	Edge* edges[WINDOW_HEIGHT], * active;
	int i, scan;
	for (i = 0; i < WINDOW_HEIGHT; i++)
	{
		edges[i] = new Edge[num];
		edges[i]->next = NULL;
	}
	buildEdgeList(num, pts, edges);
	active = new Edge;
	active->next = NULL;
	for (scan = 0; scan < WINDOW_HEIGHT; scan++)
	{
		buildActiveList(scan, active, edges);
		if (active->next)
		{
			fillScan(scan, active);
			updateActiveList(scan, active);
			resortActiveList(active);
		}
	}
}

void myDraw(void)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glColor3f(0.0, 0.0, 0.0);
	//修改顶点坐标
	Point pts[] = { {100,40},{220,140},{280,80},{350,300},{200,380},{50,280},{100,40} };
	scanFill(4, pts);
	glFlush();
}

void main(int argc, char** argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowPosition(200, 200);
	glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
	glutCreateWindow("扫描线算法");
	init();
	glutDisplayFunc(myDraw);
	glutMainLoop();
}

测试结果:

参考资料:http://www.doc88.com/p-9903152408428.html

  • 4
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豆豆豆豆芽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值