#include "stdafx.h"
#include "stdlib.h"
#include "gl\glut.h"
#include "iostream"
#include "vector"
#include "algorithm"
using namespace std;
const unsigned int maxn = 700;
bool judge = false;
struct edge {
float y2; //当前边的较高的那个端点的y值
float x1; //当前边的较小的那个端点的x值
float m; //m是边的斜率的倒数
edge *next;
friend bool operator <(const edge&e1, const edge&e2) {
return e1.x1 < e2.x1;
}
}; //用vector 构建活化边表
edge *edge_table[maxn]; // edge_table
struct node {
int x, y;
node(int a, int b) {
x = a, y = b;
}
};
int flag[maxn]; //用于标记边那些特定的 要y-1的点
int visit[maxn]; //用于在寻找 特定点 时 标记删除掉的点
int point_amount = 0; //顶点的个数(边的个数)
int Point[maxn][2];
int EDGE_PRO[maxn][2][2]; //没有处理的边
int minx_y = INT_MAX;
void init() {
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 700.0, 0.0, 700.0);
for (int i = 0; i < maxn; i++) {
edge_table[i] = NULL;
}
}
bool empty_edge_table() {
for (int i = minx_y; i < maxn; i++)
if (edge_table[i] != NULL)
return false;
return true;
}
void filling(float a, float b, float c) { //填充y值为c ,x值从a到b的区域
glColor3f(0.4, 0.4, 0.4);
glBegin(GL_LINES);
glVertex2i(a, c);
glVertex2i(b, c);
glEnd();
glFlush();
return;
}
void padding() {
for (int i = 0; i < point_amount; i++) { //寻找需要y-1的边 用flag记录
int mult1 = Point[i][1] - Point[(i + 1) % point_amount][1];
int mult2 = Point[i][1] - Point[(i + point_amount - 1) % point_amount][1];
if (mult1*mult2 < 0) {
if (mult1 < 0)
flag[(i + point_amount - 1) % point_amount] = 1;
else
flag[i] = 1;
}
}
for (int i = 0; i < point_amount; i++) { //建立edge_table
edge *p; edge *q;
p = (edge*)malloc(sizeof edge);
p->y2 = EDGE_PRO[i][1][1];
if (flag[i])
p->y2 = p->y2 - 1;
p->x1 = EDGE_PRO[i][0][0];
p->m = float(EDGE_PRO[i][1][0] - EDGE_PRO[i][0][0]) / float(EDGE_PRO[i][1][1] - EDGE_PRO[i][0][1]);
p->next = NULL;
q = edge_table[EDGE_PRO[i][0][1]];
if (q == NULL) {
q = p;
edge_table[EDGE_PRO[i][0][1]] = q;
}
else {
while (q->next != NULL)
q = q->next;
q->next = p;
}
}
vector<edge>active_edge; //声明活化边表
int y = minx_y; //y从y值最小的扫描线开始
while (!active_edge.empty() || !empty_edge_table()) { //当活化边表不会空 或者 edge_table 不为空就一直执行
if (edge_table[y] != NULL) {
//判断扫描线+1后需不需要从edge_table中添加新的边到 活化边表中去
edge *q;
q = edge_table[y];
active_edge.push_back(*q);
while (q->next != NULL) {
q = q->next;
active_edge.push_back(*q);
}
edge_table[y] = NULL;//将edge_table中的第y个置空
}
sort(active_edge.begin(), active_edge.end());//将活化边表中的边按照x值从小到大排序
for (unsigned int i = 0; i < active_edge.size(); i++) {
if (i + 1 == active_edge.size())
break;
float x_1 = active_edge[i].x1;
float x_2 = active_edge[i + 1].x1;
filling(x_1, x_2, y);
i++;
}
y++;
for (unsigned int i = 0; i < active_edge.size(); i++) { //如果扫描线的y值+1后,活化边表中存在 不再会和扫描线相交的边 就将这条边从活化边表中删除
if (y > active_edge[i].y2) {
active_edge.erase(active_edge.begin() + i);
i--;
}
else {
float x_1 = active_edge[i].x1 + active_edge[i].m; //新加入的线段的最低点 没有考虑
active_edge[i].x1 = x_1; //偶数对的获得扫描在图形内部的区域
}
}
cout << y << endl;
}
}
void mydisplay() {
}
void display() {
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(0.4, 0.4, 0.4);
glBegin(GL_LINES);
for (int i = 0; i < point_amount; i++) {
glVertex2i(Point[i][0], Point[i][1]);
glVertex2i(Point[(i + 1) % point_amount][0], Point[(i + 1) % point_amount][1]);
}
glEnd();
glFlush();
padding();
}
void mymouse(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN) { //如果点击左键 记录这是鼠标的坐标 为一个端点的坐标
Point[point_amount][0] = x;
Point[point_amount][1] = 700 - y;
point_amount++;
if (700 - y < minx_y)
minx_y = 700 - y;
}
if (button == GLUT_RIGHT_BUTTON) {
if (state == GLUT_DOWN) {
printf("%d", point_amount);
for (int i = 0; i < point_amount; i++) {
if (Point[i][1] < Point[(i + 1) % point_amount][1]) {
EDGE_PRO[i][0][0] = Point[i][0]; //存放边的两个顶点 将y值小的存放在EDGE_PRO[i][0][1]中
EDGE_PRO[i][0][1] = Point[i][1];
EDGE_PRO[i][1][0] = Point[(i + 1) % point_amount][0];
EDGE_PRO[i][1][1] = Point[(i + 1) % point_amount][1];
}
else {
EDGE_PRO[i][1][0] = Point[i][0]; //存放边的两个顶点
EDGE_PRO[i][1][1] = Point[i][1]; //将y值小的存放在EDGe_PRO[i][0[1]中 ,方便以后建立edge_table
EDGE_PRO[i][0][0] = Point[(i + 1) % point_amount][0];
EDGE_PRO[i][0][1] = Point[(i + 1) % point_amount][1];
}
}
display();
}
}
}
int main(int argc, char **argv)
{
memset(visit, 0, sizeof visit);
memset(flag, 0, sizeof flag);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
glutInitWindowPosition(20, 20);
glutInitWindowSize(700, 700);
glutCreateWindow("syp's window");
init();
glutDisplayFunc(mydisplay);
glutMouseFunc(mymouse);
glutMainLoop();
return 0;
}
Opengl Scan-Line Fill of Convex Polygons
猜你喜欢
转载自blog.csdn.net/curtern/article/details/80516387
今日推荐
周排行