#include "stdafx.h"
#include "编码裁剪法.h"
//鼠标画线小程序
#include <glut.h>
#define N 1000 //maximum line numbers
int ww, hh; // for display window width and height
int line[N][4], k = 0; //for line's endpoint coordinates and line number
int flag = 1;
int xa, ya, xb, yb; //矩形两个对角线的坐标
class wcPt2D { public: float x, y; };
wcPt2D p1, p2, winMin, winMax;
void Myinit(void);
void Reshape(int w, int h);
void myMouse(int button, int state, int x, int y);
void myMotion(int x, int y);
void Display(void);
void drawlines();
void mykeyboard(unsigned char key, int x, int y);
void drawbox();
void drawcliplines();
void LBLineClip(float xleft, float xright, float ybottom, float ytop, float x1, float y1, float x2, float y2);
bool LBclipTest(float p, float q, float& u1, float& u2);
GLubyte encode(wcPt2D pt, wcPt2D winMin, wcPt2D winMax);
void swapPts(wcPt2D *p1, wcPt2D *p2);
void swapCodes(GLubyte *c1, GLubyte *c2);
void lineClipCohSuth(wcPt2D winMin, wcPt2D winMax, wcPt2D p1, wcPt2D p2);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
char *argv[] = { "hello ", " " };
int argc = 2; // must/should match the number of strings in argv
glutInit(&argc, argv); //初始化GLUT库;
glutInitWindowSize(800, 600); //设置显示窗口大小
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); //设置显示模式;(注意双缓冲)
glutCreateWindow("鼠标画线小程序演示"); // 创建显示窗口
Myinit();
glutDisplayFunc(Display); //注册显示回调函数
glutMouseFunc(myMouse); //注册鼠标按钮回调函数
glutMotionFunc(myMotion); //注册鼠标移动回调函数
glutReshapeFunc(Reshape); //注册窗口改变回调函数
glutKeyboardFunc(mykeyboard); //注册键盘回调函数
glutMainLoop(); //进入事件处理循环
return 0;
}
void Myinit(void)
{
//glPolygonMode(GL_FRONT, GL_LINE);
glClearColor(0.0, 0.0, 0.0, 0.0);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glLineWidth(3.0);
}
//渲染绘制子程序--------------------------------------------------------------------------
void Display(void)
{
glClear(GL_COLOR_BUFFER_BIT); //刷新颜色缓冲区;
if (flag == 1)
{
drawlines(); //画线子程序;
}
if (flag == 2)
{
drawlines(); //画线子程序;
drawbox(); //画矩形
}
if (flag == 3)
{
drawbox();
drawcliplines();
}
glutSwapBuffers(); //双缓冲的刷新模式;
}
//-----------------------------------------------
void Reshape(int w, int h) //窗口改变时自动获取显示窗口的宽w和高h
{
glMatrixMode(GL_PROJECTION); //投影矩阵模式
glLoadIdentity(); //矩阵堆栈清空
glViewport(0, 0, w, h); //设置视区大小
gluOrtho2D(0, w, 0, h); //设置裁剪窗口大小
ww = w;
hh = h;
}
//鼠标按钮响应事件..
void myMouse(int button, int state, int x, int y)
{
if (flag == 1)
{
if (button == GLUT_LEFT_BUTTON&&state == GLUT_DOWN)
{
line[k][0] = x; //线段起点x坐标
line[k][1] = hh - y; //线段终点y坐标
}
if (button == GLUT_LEFT_BUTTON&&state == GLUT_UP)
{
line[k][2] = x; //线段起点x坐标
line[k][3] = hh - y; //线段终点y坐标
k++;
glutPostRedisplay();
}
}
if (flag == 2)
{
if (button == GLUT_LEFT_BUTTON&&state == GLUT_DOWN)
{
xa = x; //矩形起点x坐标
ya = hh - y; //矩形终点y坐标
}
if (button == GLUT_LEFT_BUTTON&&state == GLUT_UP)
{
xb = x; //矩形起点x坐标
yb = hh - y; //矩形终点y坐标
k++;
flag = 3;
glutPostRedisplay();
}
}
}
//鼠标移动时获得鼠标移动中的坐标-----------------------------------------------------
void myMotion(int x, int y)
{
if (flag == 1)
{
//get the line's motion point
line[k][2] = x; //动态终点的x坐标
line[k][3] = hh - y; //动态终点的y坐标
glutPostRedisplay();
}
if (flag == 2)
{
//get the line's motion point
xb = x; //动态终点的x坐标
yb = hh - y; //动态终点的y坐标
glutPostRedisplay();
}
}
//画线子程序
void drawlines()
{
for (int i = 0; i <= k; i++) //********
{
glBegin(GL_LINES);
glVertex2f(line[i][0], line[i][1]);
glVertex2f(line[i][2], line[i][3]);
glEnd();
}
}
//键盘响应函数
void mykeyboard(unsigned char key, int x, int y)
{
switch (key)
{
case '1':
flag = 1;
break;
case '2':
flag = 2;
break;
}
//参数修改后调用重画函数,屏幕图形将发生改变
glutPostRedisplay();
}
void drawbox()
{
glRectf(xa, ya, xb, yb);
}
void drawcliplines()
{
for (int i = 0; i <= k; i++) //********
{
//glBegin(GL_LINES);
//glVertex2f(line[i][0], line[i][1]);
//glVertex2f(line[i][2], line[i][3]);
//glEnd();
//LBLineClip(min(xa, xb), max(xa, xb), min(ya, yb), max(ya, yb), line[i][0], line[i][1], line[i][2], line[i][3]);
winMin.x = min(xa, xb);
winMin.y = min(ya, yb);
winMax.x = max(xa, xb);
winMax.y = max(ya, yb);
p1.x = line[i][0];
p1.y = line[i][1];
p2.x = line[i][2];
p2.y = line[i][3];
lineClipCohSuth(winMin, winMax, p1, p2);
}
}
// 裁剪线段子函数--梁友栋
void LBLineClip(float xleft, float xright, float ybottom, float ytop, float x1, float y1, float x2, float y2)
{
float u1 = 0.0, u2 = 1.0;
float deltax = x2 - x1, deltay = y2 - y1;
if (LBclipTest(-deltax, x1 - xleft, u1, u2))
{
if (LBclipTest(deltax, xright - x1, u1, u2))
{
deltay = y2 - y1;
if (LBclipTest(-deltay, y1 - ybottom, u1, u2))
{
if (LBclipTest(deltay, ytop - y1, u1, u2))
{
if (u2 < 1.0)
{
x2 = x1 + u2*deltax;
y2 = y1 + u2*deltay;
}
if (u1 > 0.0)
{
x1 = x1 + u1*deltax;
y1 = y1 + u1*deltay;
}
glBegin(GL_LINES);
glVertex2f(x1, y1);
glVertex2f(x2, y2);
glEnd();
}
}
}
}
}
//判断是否需要裁减子函数
bool LBclipTest(float p, float q, float& u1, float& u2)
{
float u;
bool Cliptest = true;
if (p > 0.0)
{
u = q / p;
if (u < u1)
{
Cliptest = false;
}
else if (u < u2)
{
u2 = u;
}
}
else if (p < 0.0)
{
u = q / p;
if (u > u2)
{
Cliptest = false;
}
else if (u > u1)
{
u1 = u;
}
}
else
{
if (q < 0.0)
{
Cliptest = false;
}
}
return Cliptest;
}
/* Define a four-bit code…*/
const GLint winLeftBitCode = 0x1;
const GLint winRightBitCode = 0x2;
const GLint winBottomBitCode = 0x4;
const GLint winTopBitCode = 0x8;
inline GLint inside(GLint code) { return GLint(!code); }
inline GLint reject(GLint code1, GLint code2) { return GLint(code1 & code2); }
inline GLint accept(GLint code1, GLint code2) { return GLint(!(code1 | code2)); }
GLubyte encode(wcPt2D pt, wcPt2D winMin, wcPt2D winMax)
{
GLubyte code = 0x00;
if (pt.x<winMin.x) code = code | winLeftBitCode;
if (pt.x>winMax.x) code = code | winRightBitCode;
if (pt.y<winMin.y) code = code | winBottomBitCode;
if (pt.y>winMax.y) code = code | winTopBitCode;
return (code);
}
void swapPts(wcPt2D *p1, wcPt2D *p2)
{
wcPt2D tmp;
tmp = *p1; *p1 = *p2; *p2 = tmp;
}
void swapCodes(GLubyte *c1, GLubyte *c2)
{
GLubyte tmp;
tmp = *c1; *c1 = *c2; *c2 = tmp;
}
void lineClipCohSuth(wcPt2D winMin, wcPt2D winMax, wcPt2D p1, wcPt2D p2)
{
GLubyte code1, code2;
GLint done = false, plotLine = false;
GLfloat m;
while (!done) {
code1 = encode(p1, winMin, winMax);
code2 = encode(p2, winMin, winMax);
if (accept(code1, code2)) {
done = true;
plotLine = true;
}
else
if (reject(code1, code2))
done = true;
else {
/* Label the point outside the window as p1*/
if (inside(code1)) {
swapPts(&p1, &p2);
swapCodes(&code1, &code2);
}
if (p2.x != p1.x) m = (p2.y - p1.y) / (p2.x - p1.x);
if (code1 & winLeftBitCode) {
p1.y += (winMin.x - p1.x)*m;
p1.x = winMin.x;
}
else
if (code1 & winRightBitCode) {
p1.y += (winMax.x - p1.x)*m;
p1.x = winMax.x;
}
else
if (code1 & winBottomBitCode) {
/*Need to update p1.x for nonvertical lines only*/
if (p2.x != p1.x)
p1.x += (winMin.y - p1.y) / m;
p1.y = winMin.y;
}
else
if (code1 & winTopBitCode) {
if (p2.x != p1.x)
p1.x += (winMax.y - p1.y) / m;
p1.y = winMax.y;
}
} //for else;
} // for while;
if (plotLine)
{
glBegin(GL_LINES);
glVertex2f(p1.x, p1.y);
glVertex2f(p2.x, p2.y);
glEnd();
}
} // for linelipCohSuth();