注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Search的博客

不断学习中!

 
 
 

日志

 
 

Cohen-SutherLand  

2012-11-25 15:12:05|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

/*--------------------------------------------------------------

                 使用Cohen-Sutherland算法裁剪线段

                    (c)  2004-06-18

  --------------------------------------------------------------*/


#include <windows.h>


#define ROUND(a) ((int)(a+0.5))

#define MAXLINE 1000

#define LEFT_EDGE 0x1

#define RIGHT_EDGE 0x2

#define BOTTOM_EDGE 0x4

#define TOP_EDGE 0x8


#define INSIDE(a) (!a)

#define REJECT(a,b) (a&b)

#define ACCEPT(a,b) (!(a|b))


void lineDDA(HDC hdc, POINT p1, POINT p2, COLORREF rgb);

void drawWindow(HDC hdc, POINT winMin,  POINT winMax, COLORREF rgb);

void invalidateWindow(HWND hwnd, POINT winMin, POINT winMax);

typedef struct Line {

POINT p1, p2;

} Line;


unsigned char encode(POINT pt, POINT winMin, POINT winMax)

{

//决定pt所在的位置

unsigned char code = 0x00;

if (pt.x < winMin.x)

code = code | LEFT_EDGE;

if (pt.x > winMax.x)

code = code | RIGHT_EDGE;

if (pt.y < winMin.y)

code = code | BOTTOM_EDGE;

if (pt.y > winMax.y)

code = code | TOP_EDGE;

return code;

}


void swapPts(POINT *p1, POINT *p2)

{

POINT tmp;

tmp = *p1;

*p1 = *p2;

*p2 = tmp;

}


void swapCodes(unsigned char *c1, unsigned char *c2)

{

unsigned char tmp;

tmp = *c1;

*c1 = *c2;

*c2 = tmp;

}


void clipLine(HDC hdc, POINT winMin, POINT winMax, POINT p1, POINT p2)

{

unsigned char code1, code2;

int done = FALSE, draw = FALSE;

float m;


while (!done)

{

//得到两点的位置

code1 = encode(p1, winMin, winMax);

code2 = encode(p2, winMin, winMax);

//两点都在窗口内么

if (ACCEPT(code1, code2))

{

done = TRUE;

draw = TRUE;

}

else

{

//两点都在窗口外么

if (REJECT(code1, code2))

{

done = TRUE;

}

else

{

if (INSIDE(code1))

{

swapPts(&p1, &p2); /*确保p1在窗口之外*/

swapCodes(&code1, &code2);

}

if (p2.x != p1.x)

{

/*使用斜率(m)来找到直线和边界的交点*/

m = (float) (p2.y - p1.y) / (p2.x - p1.x);

}

//如果pt1在窗口左边

if (code1 & LEFT_EDGE)

{

//算出直线与左边界的交点

p1.y += (long)((winMin.x - p1.x) * m);

p1.x = winMin.x;

}

else

{

if (code1 & RIGHT_EDGE)

{

p1.y += (long) ((winMax.x - p1.x) * m);

p1.x = winMax.x;

}

else

{

if (code1 & BOTTOM_EDGE)

{

/*只有直线不是竖直的才要更新*/

if (p2.x != p1.x)

{

p1.x += (long)((winMin.y - p1.y) / m);

}

p1.y = winMin.y;

}

else

{

if (code1 & TOP_EDGE)

{

if (p2.x != p1.x)

{

p1.x += (long) ((winMax.y - p1.y) / m);

}

p1.y = winMax.y;

}

}

}

}

}

}

}

if (draw)

{

//如果需要,画出直线

lineDDA(hdc, p1, p2, RGB(0, 255, 0));

}

}



//窗口函数说明

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);



//初始化窗口类

//WinMain函数说明

int WINAPI WinMain( HINSTANCE hInstance,HINSTANCE hPrevInst, LPSTR lpszCmdLine, int nCmdShow)

{

HWND hwnd ;

MSG Msg ;

WNDCLASS wndclass ;

char lpszClassName[] = "窗口"; //窗口类名

char lpszTitle[]= "My_Windows"; //窗口标题名


        //窗口类的定义

wndclass.style = 0; //窗口类型为缺省类型

wndclass.lpfnWndProc = WndProc ; //窗口处理函数为WndProc

wndclass.cbClsExtra = 0 ; //窗口类无扩展

wndclass.cbWndExtra = 0 ; //窗口实例无扩展

wndclass.hInstance = hInstance ; //当前实例句柄

wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION) ;

//窗口的最小化图标为缺省图标

wndclass.hCursor = LoadCursor( NULL, IDC_ARROW) ;

//窗口采用箭头光标

wndclass.hbrBackground = GetStockObject( WHITE_BRUSH) ;

//窗口背景为白色

wndclass.lpszMenuName = NULL ; //窗口中无菜单

wndclass.lpszClassName = lpszClassName ;

//窗口类名为"窗口示例"


 //窗口类注册

   if( !RegisterClass( &wndclass)) //如果注册失败则发出警告声音

{

MessageBeep(0) ;

return FALSE ;

}


        //创建窗口

hwnd=CreateWindow(lpszClassName, //窗口类名

lpszTitle, //窗口实例的标题名

WS_OVERLAPPEDWINDOW,//窗口的风格

CW_USEDEFAULT,

CW_USEDEFAULT, //窗口左上角坐标为缺省值

CW_USEDEFAULT,

CW_USEDEFAULT,, //窗口的高和宽为缺省值

NULL, //此窗口无父窗口

NULL, //此窗口无主菜单

hInstance, //创建此窗口的应用程序的当前句柄

NULL) ; //不使用该值


//显示窗口

ShowWindow( hwnd, nCmdShow) ;

//绘制用户区

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)

{

HDC hdc;

PAINTSTRUCT ps;


static POINT winMin, winMax;


static Line ln[MAXLINE];

static iCount;


static POINT p1, p2;

int i;


switch(message)

{

case WM_SIZE:

//确定窗口位置

winMin.x = LOWORD(lParam) / 4;

winMax.x = LOWORD(lParam) * 3 / 4;

winMin.y = HIWORD(lParam) / 4;

winMax.y = HIWORD(lParam) * 3 / 4;

iCount = 0;

UpdateWindow(hwnd);

return 0;



case WM_LBUTTONDOWN:

//得到每一个点

p1.x = LOWORD(lParam);

p1.y = HIWORD(lParam);

SetCapture(hwnd);

return 0;

case WM_MOUSEMOVE:

if (wParam & MK_LBUTTON)

{

hdc = GetDC(hwnd);

p2.x = LOWORD(lParam);

p2.y = HIWORD(lParam);

InvalidateRect(hwnd, NULL, TRUE);

UpdateWindow(hwnd);

lineDDA(hdc, p1, p2, RGB(255, 0, 0));

ReleaseDC(hwnd, hdc);

}

return 0;


case WM_LBUTTONUP:

p2.x = LOWORD(lParam);

p2.y = HIWORD(lParam);

ReleaseCapture();

//把p1, p2放进直线数组

ln[iCount].p1 = p1;

ln[iCount].p2 = p2;

iCount++;

InvalidateRect(hwnd, NULL, TRUE);

UpdateWindow(hwnd);

return 0;


case WM_PAINT:

hdc = BeginPaint(hwnd, &ps);

//画出窗口

drawWindow(hdc, winMin, winMax, RGB(0, 0, 255));

//画出所有剪裁过的线

for (i = 0; i < iCount; i++)

{

clipLine(hdc, winMin, winMax, ln[i].p1, ln[i].p2);

}

EndPaint(hwnd, &ps);

return 0;

case WM_DESTROY:

PostQuitMessage(0); //调用PostQuitMessage发出WM_QUIT消息

return 0;

}

return  DefWindowProc(hwnd,message,wParam,lParam);

}


void lineDDA(HDC hdc, POINT p1, POINT p2, COLORREF rgb)

{

//DDA算法画出p1,p2之间的直线

int dx = p2.x - p1.x, dy = p2.y - p1.y, steps, k;

float xIncrement, yIncrement, x = (float)p1.x, y = (float)p1.y;


if (abs(dx) > abs(dy))

steps = abs(dx);

else

steps = abs(dy);

xIncrement = dx/(float)steps;

yIncrement = dy/(float)steps;



SelectObject(hdc, CreatePen(PS_SOLID, 0, rgb));

//用rgb颜色画出出直线


SetPixel(hdc, ROUND(x), ROUND(y), rgb);

for (k = 0; k < steps; k++)

{

x += xIncrement;

y += yIncrement;

SetPixel(hdc, ROUND(x), ROUND(y), rgb);

}


DeleteObject(SelectObject(hdc, GetStockObject(BLACK_PEN)));

}


void drawWindow(HDC hdc, POINT winMin,  POINT winMax, COLORREF rgb)

{

POINT p1, p2;

p1 = winMin;

p2 = winMin;

p2.x = winMax.x;

lineDDA(hdc, p1, p2, rgb); //TOP EDGE

p1 = winMax;

lineDDA(hdc, p2, p1, rgb); //RIGHT EDGE

p2 = winMax;

p2.x = winMin.x;

lineDDA(hdc, p1, p2, rgb); //BOTTOM EDGE

p1 = winMin;

lineDDA(hdc, p1, p2, rgb); //LEFT EDGE

}


  评论这张
 
阅读(180)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017