前些天在做打乒乓程序,一连做了好几个,但做到多线程的版本的时候一直有问题,又加上临近考试了,所以那个先放一放,把图形学的课程设计题目先做一下,于是就做了下面这个程序:(不过那个多线程的版本打乒乓我以后一定补做它)
2:当线段的两个端点的4位编码全为0,则此线段全部在窗口内,可直接接受;
3:如果对线段的两个端点的4位编码进行逻辑与运算,结果为非零,则此线段在窗口之外可以直接舍弃;
4:这一线断既不能直接舍弃也不能直接接受,它可能与窗口相交。
当发生情况4时,我们需要对线段进行再分割,即找到与窗口一个边框的交点。根据交点的位置,赋予其四位编码,然后检查分割后的线段,对其进行接受、舍弃、分割。重复以上过程,直至不出现第4种情况为止。
三:程序说明及运行结果
启动2D LineClippping.exe,默认先画直线,你可以画不止一条直线,最后它们都将被裁剪,画完直线,点 DrawRectangle 按钮,开始画裁剪矩形,矩形只能画一个,画完矩形,点Clipping按钮,程序就完成了裁剪操作并且将结果显示在了客户区,如果你画线或者画矩形的中间对已画的图形不满意,可以按Restet 按钮随时清除所有已画图形,重新来过。最后完毕时,点右上角的关闭按钮即可退出程序。
1:开始画直线
2:画矩形:
3:裁剪后
四:程序源码
/Powered by alex 2006.6.6 曰完成//
#include<windows.h>
#define DRAWRECT 0 //for Button ID
#define CLIPPING 1
#define RESET 2
typedef struct line //store two vertex of every lines
{
int xStart,yStart;
int xEnd,yEnd;
}LINE,*PLINE;
LINE lines[100]; //maximun lines can deal with is 100
LINE line;
int j=0;
POINT rectLH,rectRL;
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void CSLineClip(PLINE,int,int,int,int); //This is the Code Fuction
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE prevInstance,PSTR szCmdLine,int iCmdShow)
{
static TCHAR szAppName[]="2D Line Clipping";
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
for(int i=0;i<100;i++){
lines[i].xStart=0;
lines[i].yStart=0;
lines[i].xEnd=0;
lines[i].yEnd=0;
}
wndclass.style=CS_HREDRAW | CS_VREDRAW |CS_DBLCLKS;
wndclass.lpfnWndProc=WndProc;
wndclass.cbClsExtra=0;
wndclass.cbWndExtra=0;
wndclass.hInstance=hInstance;
wndclass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor=LoadCursor(NULL,IDC_CROSS);
wndclass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName=NULL;
wndclass.lpszClassName=szAppName;
RegisterClass(&wndclass);
hwnd=CreateWindow(szAppName,"2D Line Clipping",WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,hInstance,NULL);
ShowWindow(hwnd,iCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&msg,NULL,0,0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam){
HWND hButtonRect;
HWND hButtonClipping;
HWND hButtonReset;
int cxChar,cyChar;
static PLINE head=lines;
int i=0;
enum Shape{Line,Rect};
static Shape WhatShape=Line;
HDC hdc;
PAINTSTRUCT ps;
RECT clientrect;
switch(message)
{
case WM_CREATE:
cxChar=LOWORD(GetDialogBaseUnits());
cyChar=HIWORD(GetDialogBaseUnits());
hButtonRect =CreateWindow(TEXT("BUTTON"),"DrawRectangle",WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,10*cxChar,28*cyChar,20*cxChar,7*cyChar/4,hwnd,(HMENU)DRAWRECT,((LPCREATESTRUCT)lParam)->hInstance,NULL);
hButtonClipping=CreateWindow(TEXT("BUTTON"),"Clipping", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,40*cxChar,28*cyChar,20*cxChar,7*cyChar/4,hwnd,(HMENU)CLIPPING,((LPCREATESTRUCT)lParam)->hInstance,NULL);
hButtonReset =CreateWindow(TEXT("BUTTON"),"Reset", WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,70*cxChar,28*cyChar,20*cxChar,7*cyChar/4,hwnd,(HMENU)RESET, ((LPCREATESTRUCT)lParam)->hInstance,NULL);
return 0;
case WM_LBUTTONDOWN:
if(WhatShape==Line)
{
line.xStart=(int)LOWORD(lParam);
line.yStart=(int)HIWORD(lParam);
}
else{
if(rectLH.x!=0 && rectLH.y!=0)
{
MessageBox(hwnd,"You can only draw one rectangle !","Error",MB_OK);
return 0;
}
rectLH.x=(int)LOWORD(lParam);
rectLH.y=(int)HIWORD(lParam);
}
return 0;
case WM_MOUSEMOVE:
if(wParam & MK_LBUTTON)
{
hdc=GetDC(hwnd);
SelectObject(hdc,GetStockObject(WHITE_PEN));
if(WhatShape==Line)
{
MoveToEx(hdc,line.xStart,line.yStart,NULL);
LineTo(hdc,line.xEnd,line.yEnd);
}
else
{
if(rectRL.x!=0 && rectRL.y!=0){
Rectangle(hdc,rectLH.x,rectLH.y,rectRL.x,rectRL.y);
}
}
if(WhatShape==Line)
{
line.xEnd=(int)LOWORD(lParam);
line.yEnd=(int)HIWORD(lParam);
}
else{
rectRL.x=(int)LOWORD(lParam);
rectRL.y=(int)HIWORD(lParam);
}
SelectObject(hdc,GetStockObject(BLACK_PEN));
if(WhatShape==Line)
{
MoveToEx(hdc,line.xStart,line.yStart,NULL);
LineTo(hdc,line.xEnd,line.yEnd);
}
else{
Rectangle(hdc,rectLH.x,rectLH.y,rectRL.x,rectRL.y);
}
ReleaseDC(hwnd,hdc);
InvalidateRect(hwnd,NULL,FALSE);
}
return 0;
case WM_LBUTTONUP:
if(WhatShape==Line){
line.xEnd=LOWORD(lParam);
line.yEnd=HIWORD(lParam);
lines[j].xStart=line.xStart;
lines[j].yStart=line.yStart;
lines[j].xEnd=line.xEnd;
lines[j].yEnd=line.yEnd;
j++;
}
else{
rectRL.x=(int)LOWORD(lParam);
rectRL.y=(int)HIWORD(lParam);
}
return 0;
case WM_COMMAND:
switch(LOWORD(wParam)){
case DRAWRECT:
if(lines[0].xStart==0 && lines[0].yStart==0){
MessageBox(hwnd,"You can only draw rectangle after you draw some lines !","Error",MB_OK);
break;
}
WhatShape=Rect;
break;
case CLIPPING:
if(lines[0].xStart==0 && lines[0].yStart==0){
MessageBox(hwnd,"Please draw at least one line to complete clipping !","Error",MB_OK);
break;
}
if(rectRL.x==0 && rectRL.y==0){
MessageBox(hwnd,"You haven't draw your clipping rectangle !","Error",MB_OK);
break;
}
for(head=lines;head->xStart!=0 && head->yStart!=0;head++)
{
CSLineClip(head,rectLH.x,rectRL.x,rectLH.y,rectRL.y);
}
head=lines;
hdc=GetDC(hwnd);
GetClientRect(hwnd,&clientrect);
Rectangle(hdc,clientrect.left-5,clientrect.top-5,clientrect.right+5,clientrect.bottom+5);
ReleaseDC(hwnd,hdc);
InvalidateRect(hwnd,NULL,FALSE);
break;
case RESET:
j=0;
WhatShape=Line;
head=lines;
for(int i=0;i<100;i++){
lines[i].xStart=0;
lines[i].yStart=0;
lines[i].xEnd=0;
lines[i].yEnd=0;
}
rectLH.x=0;
rectLH.y=0;
rectRL.x=0;
rectRL.y=0;
hdc=GetDC(hwnd);
GetClientRect(hwnd,&clientrect);
Rectangle(hdc,clientrect.left-5,clientrect.top-5,clientrect.right+5,clientrect.bottom+5);
ReleaseDC(hwnd,hdc);
InvalidateRect(hwnd,NULL,FALSE);
break;
}
return 0;
case WM_PAINT:
hdc=BeginPaint(hwnd,&ps);
if(rectRL.x!=0 && rectRL.y!=0){
Rectangle(hdc,rectLH.x,rectLH.y,rectRL.x,rectRL.y);
}
for(head=lines;head->xStart!=0 && head->yStart!=0;head++)
{
if(head->xStart!=-1 && head->yStart!=-1){
MoveToEx(hdc,head->xStart,head->yStart,NULL);
LineTo(hdc,head->xEnd,head->yEnd);
}
}
head=lines;
EndPaint(hwnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd,message,wParam,lParam);
}
typedef unsigned int outcode;
enum {TOP=0X8,BOTTOM=0X4,RIGHT=0X2,LEFT=0X1};
outcode CompOutCode(int x,int y,int xmin,int xmax,int ymin,int ymax)
{
outcode code=0;
if(y>ymax){
code |=BOTTOM;
}
else if(y<ymin){
code |=TOP;
}
if(x>xmax){
code |=RIGHT;
}
else if(x<xmin){
code |=LEFT;
}
return code;
}
void CSLineClip(PLINE current,int xmin,int xmax,int ymin,int ymax)
{
outcode outcode0,outcode1,outcodeOut;
bool accept=FALSE,done=FALSE;
int x0=current->xStart;
int y0=current->yStart;
int x1=current->xEnd;
int y1=current->yEnd;
outcode0=CompOutCode(x0,y0,xmin,xmax,ymin,ymax);
outcode1=CompOutCode(x1,y1,xmin,xmax,ymin,ymax);
int x,y;
while(outcode0 !=0 || outcode1 !=0)
{
if(outcode0 & outcode1) //Reject Directly!
{
current->xStart=-1;
current->yStart=-1;
current->xEnd=-1;
current->yEnd=-1;
break;
}
outcodeOut=outcode0?outcode0:outcode1;
if(outcodeOut & LEFT)
{
x=xmin;
y=y0+(int)(float(y1 - y0)*float(xmin-x0)/float(x1 - x0));
}
else if(outcodeOut & RIGHT)
{
x=xmax;
y=y0+int(float(y1-y0)*float(xmax-x0)/float(x1-x0));
}
else if(outcodeOut & BOTTOM)
{
y=ymax;
x=x0+int(float(x1-x0)*float(ymax-y0)/float(y1-y0));
}
else if(outcodeOut & TOP)
{
y=ymin;
x=x0+int(float(x1-x0)*float(ymin-y0)/float(y1-y0));
}
if(outcodeOut==outcode0)
{
current->xStart=x;
current->yStart=y;
outcode0=CompOutCode(x,y,xmin,xmax,ymin,ymax);
}
else
{
current->xEnd=x;
current->yEnd=y;
outcode1=CompOutCode(x,y,xmin,xmax,ymin,ymax);
}
}
}
END//