裁剪算法——cohen-sutherland算法

实验环境:VC6.0

算法思想:

  延长窗口的边,将二维平面分成9个区域,每个区域赋予4位编码CtCbCrCl,裁剪一条线段P1P2时,先求出所在的区号code1code2。若code1=0,且code2=0,则线段P1P2在窗口内,应取之。若按位与运算code1&code2,则说明两个端点同时在窗口的上方、下方、左方或右方,则可判断线段完全在窗口外,可弃之;否则,按第三种情况处理,求出线段与窗口某边的交点,在交点处把线段一分为二,其中必有一段在窗口外,可弃之,再对另一段重复上述处理。

 

1001

1000

1010

0001

0000

0010

0101

0100

0110

                  多边形裁剪编码

程序实现:

#include "stdafx.h"
#include<stdio.h>
#include<conio.h>
#include<graphics.h>
#define LEFT 1
#define RIGHT 2
#define BOTTOM 4
#define TOP 8
void midpointLine(int x0,int y0,int x1,int y1,int color)//中点画线算法
{
    int a,b,d1,d2,d,x,y;
    a=y0-y1;
    b=x1-x0;
    d=2*a+b;
    d1=2*a;
    d2=2*(a+b);
    x=x0;
    y=y0;
    putpixel(x,y,color);
    while(x<x1)
    {
        if(d<0)
        {
            x++;
            y++;
            d+=d2;
        }
        else
        {
            x++;
            d+=d1;
        }
        putpixel(x,y,color);
    }
}
int encode(int x,int y,int XL,int XR,int YB,int YT)//编码
{
    int c=0;
    if(x<XL) c|=LEFT;
    if(x>XR) c|=RIGHT;
    if(y<YB) c|=BOTTOM;
    if(y>YT) c|=TOP;
    return c;
}
void C_SLineClip(int x1,int y1,int x2,int y2,int XL,int XR,int YB,int YT)
{
    int code1,code2,code,x,y;
    code1=encode(x1,y1,XL,XR,YB,YT);
    code2=encode(x2,y2,XL,XR,YB,YT);
    while((code1 != 0) || (code2 != 0))
    {
        if((code1 & code2) != 0) 
        {
            midpointLine(x1,y1,x2,y2,RGB(0, 255, 0));//如果直线在裁剪窗口外就用绿色画出
            printf("线段在窗口外!");
            return;
        }
        if(code1 != 0) code=code1;
        else code=code2;
        if((LEFT & code) != 0)
        {
            x=XL;
            y=y1+(y2-y1)*(XL-x1)/(x2-x1);
        }
        else if((RIGHT & code) != 0)
        {
            x=XR;
            y=y1+(y2-y1)*(XR-x1)/(x2-x1);
        }
        else if((BOTTOM & code) != 0)
        {
            y=YB;
            x=x1+(x2-x1)*(YB-y1)/(y2-y1);
        }
        else if((TOP & code) != 0)
        {
            y=YT;
            x=x1+(x2-x1)*(YT-y1)/(y2-y1);
        }
        if(code == code1)
        {
            x1=x; y1=y; code1=encode(x,y,XL,XR,YB,YT);
        }
        else
        {
            x2=x; y2=y; code2=encode(x,y,XL,XR,YB,YT);
        }
    }
    midpointLine(x1,y1,x2,y2,RGB(255,0,0));//将裁减的直线用红色标注
    return;
}
int main(int argc, char* argv[])
{
    int gdriver=DETECT,gmode;
    int x1=20,y1=30,x2=250,y2=300,XL=10,XR=200,YT=400,YB=30;
    initgraph(&gdriver,&gmode,"c:\\tc");
    //setbkcolor(WHITE);
    cleardevice();
    midpointLine(x1,y1,x2,y2,RGB(0,255,0));//将被裁剪直线用绿色画出
    rectangle(10,400,200,30);//rectangle(int left,int top,int right,int bottom);//裁剪窗口
    C_SLineClip(x1,y1,x2,y2,XL,XR,YB,YT);// cohen sutherland算法
    getch();
    closegraph();
    return 0;
}

显示效果:

将在窗口内的线段设为红色,窗口外的线段设为绿色。

posted @ 2017-10-29 14:43  奇热行  阅读(706)  评论(0)    收藏  举报