OpenGL扫描线填充算法详解扫描线填充算法详解
本文实例为大家分享了OpenGL扫描线填充算法,供大家参考,具体内容如下
说明说明
把最近一系列的图形学经典算法实现了一下。课业繁忙,关于该系列的推导随后再写。但是在注释里已经有较为充分的分析。
分情况讨论分情况讨论
注意对于横线需要特别讨论,但是对于垂直线却不必特别讨论。想一想为什么?
代码代码
#include <iostream>
#include <GLUT/GLUT.h>
#include <map>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
int hmin,hmax; //记录扫描线开始和结束的位置
struct Line { //定义线段的结构体
float dx,x,y,ym; //不用记录K直接记录dx和x即可
Line(float x1,float y1,float x2,float y2) {
if(y1==y2){ //单独讨论横直线的情况
this->y = y1;
this->ym = y1;
if(x1 < x2){
dx = x1; x = x2;
}else{
dx =x2;x = x1;}
}else if(y2<y1){ //选择靠上者的x值
this -> x = x2; //记录上方的x值一方便处理关键时刻(用于插入AET排序)
this ->y = y2; //记录上方的y值,用于排序
this -> ym = y1; //靠下者ym
}else{
this -> x = x1;
this ->y = y1;
this -> ym = y2;
}
dx = (x2-x1)/(y2-y1);
}
};
typedef list<Line> TESTLIST;
vector<vector<Line>> con; //记录重要事件表(有序),当然这个也可以使用优先队列
list<Line> AET; //滚动记录活动边表,这里将
//该边表完整存储的意义不大所以采用滚动存储的方式
map<int, int> mapper; //用于数据(y值)离散化处理
int x1,y1,x2,y2; //描述构成直线的两个端点
int x0,y0; //记录图形开始位置
float h_min,h_max; //画线开始和结束的位置
int flag = 1; //用于记录用户点击的次数,单次画点,双次画线。
int if_drawable = 1; //当用户再次点击鼠标时不在更改信息
int window_size=600; //这是我们显示界面的大小
vector<vector<Line>> con2;
int level = 1;
/*
操作说明:算法没有严格的图形绘制检查。仅为了图形学算法的演示。
您使用鼠标【左键】进行绘制点,请您保证没有线是交叉的。
当您点击鼠标【右键】绘制最后一个点。系统会自动将其与起始点相连。
整体思路描述:使用map将y的值离散化,用有序表记录“关键事件”主要
是加入边(一条或者两条)删除边操作。在用一个滚动的活动边表进行遍历画线。
*/
void show_v(Line a){
/*
函数说明:显示点的信息
*/
cout << "(" <<a.x << "," << a.y <<")";
cout << " (" <<a.dx<<")" << "下限:"<<a.ym;
cout << " -- "<<endl;
}
bool higher(const vector<Line> & l1, const vector<Line>& l2) {
//将关键事件表中的line按照y值进行排序;
//注意我们的画布是从上到下不断递增从左到右不断递增
return l1[0].y < l2[0].y;//可以保证一定至少有一个不然map不会映射到
}
bool AET_lefter(const Line & l1, const Line & l2) {
评论0