// ConsoleApplication41.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "iostream"
#include "vector"
#include "algorithm"
#include "GL/glut.h"
#define color_0 color(0,0,0)
#define color_1 color(0.25,0.9,0.8)
#define color_2 color(0.15,0.8,0.6)
#define color_3 color(1,0,0)
#define color_4 color(0,0,1)
#define color_5 color(1,1,0)
using namespace std;
const unsigned int maxn = 700;
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;
int setpoint_[maxn][maxn];
struct edge {
float y2;
float x1;
float 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 ans = 0;
int time = 0;
int keytime = 0;
int time3 = 0;
float x1, y1_, x2, y2; //划线算法的 两个端点
float x3, y3, x4, y4, x5, y5, xmove0, ymove0, xmove1, ymove1;
float xr3, yr3;
float r1, c1, r2, c2;
int xpro, ypro;
int r;
float sf = 1;
int asn = 0;
bool determine = false;
bool check = true;
class color {
public:
float r, g, b;
color(float r_, float g_, float b_) {
r = r_, g = g_, b = b_;
}
color() {};
};
class screen
{
private:
color p[maxn][maxn];
int hight;
int width;
int length;
int xo, yo;
public:
screen(int a, int b, int c, int d, int e);
void initscreen();
void setpoint(int x, int y, color rgb);
void reviselength(int x); //修改方格的长度
int getlength();
void newxoyo(int x, int y); //修改方格左下角的x,y
int getxo();
int getyo();
int mapped_x(int x);
int mapped_y(int y);
void show();
void filling(int a, int b, int c);
};
screen::screen(int a, int b, int c, int d, int e) {
hight = a, width = b, length = c, xo = d, yo = e;
for (int i = 0; i < width; i++)
for (int j = 0; j < hight; j++) {
p[i][j] = color_0;
}
}
int screen::getlength() {
return length;
}
void screen::initscreen() {
memset(setpoint_, 0, sizeof setpoint_);
for (int i = 0; i < width; i++)
for (int j = 0; j < hight; j++) {
p[i][j] = color_0;
}
}
void screen::setpoint(int x, int y, color rgb) {
if (x < 0 || y < 0 || x >= 700 || y >= 700)
return;
p[x][y] = rgb;
}
void screen::reviselength(int x) {
length = length + x;
}
void screen::newxoyo(int x, int y) {
xo = x;
yo = y;
}
int screen::getxo() {
return xo;
}
int screen::getyo() {
return yo;
}
int screen::mapped_x(int x) {
return int(float(x - xo) / float(length));
}
int screen::mapped_y(int y) {
return int(float(700 - y - yo) / float(length));
}
void screen::show() {
glColor3f(0.5, 0.5, 0.5);
glBegin(GL_QUADS);
glVertex2i(xo, yo);
glVertex2i(xo, yo + hight*length);
glVertex2i(xo + width*length, yo + hight*length);
glVertex2i(xo + width*length, yo);
glEnd();
glFlush();
glColor3f(0.4, 0.6, 0.7);
glBegin(GL_LINES);
for (int i = 0; i <= hight; i++) {
glVertex2i(xo, yo + i*length);
glVertex2i(xo + width*length, yo + i*length);
}
for (int i = 0; i <= width; i++) {
glVertex2i(xo + i*length, yo);
glVertex2i(xo + i*length, yo + hight*length);
}
glEnd();
glFlush();
glBegin(GL_QUADS);
for (int i = 0; i < width; i++)
for (int j = 0; j < hight; j++) {
if (p[i][j].r != 0 || p[i][j].g != 0 || p[i][j].b != 0)
{
glColor3f(p[i][j].r, p[i][j].g, p[i][j].b);
glVertex2i(xo + i*length, yo + j*length);
glVertex2i(xo + i*length, yo + j*length + length);
glVertex2i(xo + i*length + length, yo + j*length + length);
glVertex2i(xo + i*length + length, yo + j*length);
}
}
glEnd();
glFlush();
}
void screen::filling(int a, int b, int c) { //填充y值为c ,x值从a到b的区域
for (int i = a + 1 ; i < b ; i++) {
if (setpoint_[i][c])
continue;
else
{
p[i][c] = color_1;
}
}
return;
}
screen matrix(50, 50, 14, 0, 0);
float fabs_(float a) {
return a > 0 ? a : -a;
}
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, w, 0.0, h);
}
void init() {
glClearColor(1.0, 1.0, 1.0, 0.0);
glMatrixMode(GL_PROJECTION);
gluOrtho2D(0.0, 700.0, 0.0, 700.0);
}
float sqrt_(float fToBeSqrted)
{
double x = 1.0;
while (fabs(x*x - fToBeSqrted) > 1e-5)
{
x = (x + fToBeSqrted / x) / 2;
}
return x;
}
void wheel_xy(int button ,int xe,int ye) {
if (button == GLUT_WHEEL_UP) {
float xx = 3 / float(matrix.getlength());
int rox = int(float(matrix.getxo()) -float(xe - matrix.getxo())*xx);
int roy = int(float(matrix.getyo()) - float(700 - ye - matrix.getyo())*xx);
matrix.newxoyo(rox, roy);
matrix.reviselength(3);
}
else if (button == GLUT_WHEEL_DOWN) {
float xx = 3 / float(matrix.getlength());
int rox = int(float(matrix.getxo()) + float(xe - matrix.getxo())*xx);
int roy = int(float(matrix.getyo()) + float(700 - ye - matrix.getyo())*xx);
matrix.newxoyo(rox, roy);
matrix.reviselength(-3);
}
}
void mouse_drag(int button,int state,int x,int y) {
if (button == GLUT_RIGHT_BUTTON)
{
if (state == GLUT_DOWN) {
printf("?");
determine = true;
xmove0 = x;
ymove0 = 700 - y;
xpro = matrix.getxo();
ypro = matrix.getyo();
}
else
determine = false;
}
}
void setpoint(int x, int y, int x0, int y0) {
matrix.setpoint(x0 + x, y0 + y, color_1);
matrix.setpoint(x0 + y, y0 + x, color_1);
matrix.setpoint(x0 - x, y0 - y, color_1);
matrix.setpoint(x0 - y, y0 - x, color_1);
matrix.setpoint(x0 + x, y0 - y, color_1);
matrix.setpoint(x0 - x, y0 + y, color_1);
matrix.setpoint(x0 - y, y0 + x, color_1);
matrix.setpoint(x0 + y, y0 - x, color_1);
}
void middlecircle(int x, int y, int r) {
int x0 = x, y0 = y;
matrix.setpoint(r1, c1, color_1);
matrix.setpoint(x, y, color_1);
int p = 1 - r;
setpoint(0, r, x0, y0);
x = 0;
y = r;
while (x < y) {
x++;
if (p < 0)
p += 2 * x + 1;
else {
y--;
p += 2 * (x - y) + 1;
}
setpoint(x, y, x0, y0);
}
}
void DDA() {
float dx = x2 - x1;
float dy = y2 - y1_;
float steps, k;
float xincreament;
float yincreament;
if (fabs_(dx) > fabs_(dy))
steps = fabs_(dx);
else
steps = fabs_(dy);
xincreament = float(dx) / float(steps);
yincreament = float(dy) / float(steps);
float xt = x1;
float yt = y1_;
for (k = 1; k < steps; k++) {
xt += xincreament;
yt += yincreament;
int x3 = int(xt + 0.5);
int y3 = int(yt + 0.5);
matrix.setpoint(x3, y3, color_2);
setpoint_[x3][y3] = 1;
}
matrix.setpoint(int(x2), int(y2), color_2);
setpoint_[int(x2)][int(y2)] = 1;
}
void mydisplay() {
glClear(GL_COLOR_BUFFER_BIT);
matrix.show();
glutSwapBuffers();
glutPostRedisplay();
}
bool empty_edge_table() {
for (int i = minx_y; i < maxn; i++) {
if (edge_table[i] != NULL)
return false;
}
return true;
}
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;
matrix.filling(int(x_1 + 0.5), int(x_2 + 0.5), 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 display() { //扫描线算法的display
for (int i = 0; i < point_amount; i++) {
x1 = Point[i][0];
y1_ = Point[i][1];
x2 = Point[(i + 1) % point_amount][0];
y2 = Point[(i + 1) % point_amount][1];
DDA();
}
for (int i = 0; i < point_amount; i++) {
x1 = Point[i][0];
y1_ = Point[i][1];
matrix.setpoint(x1, y1_, color_3 );
}
}
void mymouse1(int button, int state, int x, int y) { //画圆
if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
keytime++;
if (keytime == 1) {
matrix.initscreen();
r1 = float(matrix.mapped_x(x));
c1 = float(matrix.mapped_y(y));
matrix.setpoint(r1, c1, color_1);
matrix.show();
}
if (keytime == 2) {
check = false;
r2 = float(matrix.mapped_x(x));
c2 = float(matrix.mapped_y(y));
keytime = 0;
r = int(sqrt_((r2 - r1)*(r2 - r1) + (c2 - c1)*(c2 - c1)) + 0.5);
middlecircle(int(r1), int(c1), r);
matrix.show();
glutSwapBuffers();
}
}
wheel_xy(button, x, y);
mouse_drag(button, state, x, y);
}
void mymouse2(int button, int state, int x, int y) { //移动划线
if (button == GLUT_LEFT_BUTTON) {
if (state == GLUT_DOWN) {
time++;
if (time == 1) {
x1 = float(matrix.mapped_x(x));
y1_ = float(matrix.mapped_y(y));
matrix.setpoint(int(x1), int(y1_), color_2);
}
else if (time == 2) {
check = false;
time = 0;
x2 = float(matrix.mapped_x(x));
y2 = float(matrix.mapped_y(y));
DDA();
matrix.setpoint(int(x1), int(y1_), color_2);
matrix.setpoint(int(x2), int(y2), color_2);
}
}
}
wheel_xy(button, x, y);
mouse_drag(button, state, x, y);
}
/* void mymouse3(int button, int state, int x, int y) {
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN) {
time++;
if (time == 1) {
x3 = float(x / matrix.getlength());
y3 = float((700 - y) / matrix.getlength());
matrix.setpoint(x3, y3, 0.4, 0.4, 0.4);
}
else if (time == 2) {
x4 = float(x / matrix.getlength());
y4 = float((700 - y) / matrix.getlength());
matrix.setpoint(x4, y4, 0.4, 0.4, 0.4);
}
if (time == 3) {
time = 0;
x5 = float(x / matrix.getlength());
y5 = float((700 - y) / matrix.getlength());
matrix.setpoint(x5, y5, 0.4, 0.4, 0.4);
}
}
} */
void mymouse4(int button, int state, int x, int y) { //扫描线填充算法
if (button == GLUT_LEFT_BUTTON)
if (state == GLUT_DOWN) {
Point[point_amount][0] = matrix.mapped_x(x);
Point[point_amount][1] = matrix.mapped_y(y);
point_amount++;
matrix.initscreen();
matrix.setpoint(matrix.mapped_x(x), matrix.mapped_y(y),color_2);
display();
memset(setpoint_, 0, sizeof setpoint_);
if (matrix.mapped_y(y) < minx_y)
minx_y = matrix.mapped_y(y);
}
if (button == GLUT_RIGHT_BUTTON) {
if (state == GLUT_DOWN) {
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]; //存放边的两个顶点
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];
EDGE_PRO[i][0][0] = Point[(i + 1) % point_amount][0];
EDGE_PRO[i][0][1] = Point[(i + 1) % point_amount][1];
}
}
display();
padding();
matrix.show();
point_amount = 0;
}
}
wheel_xy(button,x,y);
mouse_drag(button, state, x, y);
}
void passivemotion(int x, int y) { //鼠标移动,没有键按下
if (time == 0 && check == true) {
matrix.initscreen();
matrix.setpoint((x - matrix.getxo()) / matrix.getlength(), (700 - y - matrix.getyo()) / matrix.getlength(), color_2);
matrix.show();
}
if (time == 1) { //画线算法中,已经获得一个端点
glClear(GL_COLOR_BUFFER_BIT);
x2 = float((x - matrix.getxo()) / matrix.getlength());
y2 = float((700 - y - matrix.getyo()) / matrix.getlength());
matrix.initscreen();
DDA();
matrix.setpoint(int(x1), int(y1_), color_2);
matrix.show();
glutSwapBuffers();
}
if (keytime == 1) { // 画圆算法中,已经获得圆心
glClear(GL_COLOR_BUFFER_BIT);
r2 = float((x - matrix.getxo()) / matrix.getlength());
c2 = float((700 - y - matrix.getyo()) / matrix.getlength());
r = int(sqrt_((r2 - r1)*(r2 - r1) + (c2 - c1)*(c2 - c1)) + 0.5);
matrix.initscreen();
middlecircle(int(r1), int(c1), r);
matrix.show();
glutSwapBuffers();
}
}
void activemotion(int x, int y) { //鼠标移动,有键按下
if (determine == true) {
xmove1 = x;
ymove1 = 700 - y;
int dx = xmove1 - xmove0;
int dy = ymove1 - ymove0;
matrix.newxoyo(xpro + dx, ypro + dy);
matrix.show();
}
}
void mykeyboard(unsigned char key, int x, int y) { //键盘
if (key == '1') { //键盘输入1时 画圆算法
keytime = 0;
matrix.initscreen();
matrix.show();
glutMouseFunc(mymouse1);
glutMotionFunc(activemotion);
glutPassiveMotionFunc(passivemotion);
}
if (key == '2') { //键盘输入2时 画线算法
matrix.initscreen();
matrix.show();
glutMouseFunc(mymouse2);
glutPassiveMotionFunc(passivemotion);
glutMotionFunc(activemotion);
}
if (key == '4') {
point_amount = 0;
matrix.initscreen();
matrix.show();
glutMouseFunc(mymouse4);
glutMotionFunc(activemotion);
}
}int main(int argc, char **argv)
{
matrix.initscreen();
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowPosition(300, 0);
glutInitWindowSize(700, 700);
glutCreateWindow("syp's window");
init();
glutDisplayFunc(mydisplay);
glutReshapeFunc(reshape);
glutKeyboardFunc(mykeyboard);
glutMainLoop();
return 0;
}
Opengl Scan-Line Fill of Convex Polygons (方格)
猜你喜欢
转载自blog.csdn.net/curtern/article/details/80624271
今日推荐
周排行