编码实现Cohen-Sutherland端点编码算法(用矩形窗口裁剪一条直线段)
#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#define LEFT 1//0001
#define RIGHT 2//0010
#define BOTTOM 4//0100
#define TOP 8//1000
int XL = 100,XR = 500,YB = 500,YT = 100;
int encode(int x,int y)
{
//书上的编码规则
int c=0;
if(x<XL) c=c|LEFT;
else if(x>XR) c=c|RIGHT;
if(y>YB) c=c|BOTTOM;
else if(y<YT) c=c|TOP;
return c;
}
// 使用中点算法画任意斜率的直线(包括起始点,不包括终止点)
void DisplayLine(int x1, int y1, int x2, int y2, int color)
{
int x = x1, y = y1;
int a = y1 - y2, b = x2 - x1;//a,b分别为x和y的增量
//考虑四种情况,分别计算增量
int cx = (b >= 0 ? 1 : (b = -b, -1));
int cy = (a <= 0 ? 1 : (a = -a, -1));
putpixel(x, y, color);
int d, d1, d2;
if (-a <= b) // 斜率绝对值 <= 1
{
d = 2 * a + b;
d1 = 2 * a;
d2 = 2 * (a + b);
while(x != x2)
{
if (d < 0)
y += cy, d += d2;
else
d += d1;
x += cx;
putpixel(x, y, color);
}
}
else // 斜率绝对值 > 1
{
d = 2 * b + a;
d1 = 2 * b;
d2 = 2 * (a + b);
while(y != y2)
{
if(d < 0)
d += d1;
else
x += cx, d += d2;
y += cy;
putpixel(x, y, color);
}
}
}
//画裁剪区域:Breasenham方法和中点画线法均不能画出该裁剪区域
void DisplayRec(int x1,int y1,int x2,int y2,int color){
DisplayLine(x1-50,y1,x2+50,y1,color);
DisplayLine(x2,y1-50,x2,y2+50,color);
DisplayLine(x2+50,y2,x1-50,y2,color);
DisplayLine(x1,y2+50,x1,y1-50,color);
}
//直线裁剪算法
void C_S_Line_CLip(int x1,int y1,int x2,int y2,int XL,int XR,int YB,int YT)
{
//根据书上的算法步骤走
int code1,code2,code;
int x,y;
code1=encode(x1,y1);//对端点P1进行编码
code2=encode(x2,y2);//对端点P2进行编码
while(code1!=0||code2!=0)
{
//相交不为0,第二种情况,全舍去
if((code1&code2)!=0) return;//整条直线段都在窗口外侧,故简弃
code=code1;
if(code==0) code=code2;//如果P1点在窗口内,则将code2赋给code,然后判断P2点的位置
if((LEFT&code)!=0)//线段与左边界相交
{ //根据三角形相似的知识求出P1P2直线段与左边界的交点
x=XL;
y=y1+(y2-y1)*(XL-x1)/(x2-x1);
}
else if((RIGHT&code)!=0)//线段与右边界相交
{ //根据三角形相似的知识求出P1P2直线段与右边界的交点
x=XR;
y=y1+(y2-y1)*(XR-x1)/(x2-x1);
}
else if((BOTTOM&code)!=0)//线段与下边界相交
{ //根据三角形相似的知识求出P1P2直线段与下边界的交点
y=YB;
x=x1+(x2-x1)*(YB-y1)/(y2-y1);
}
else if((TOP&code)!=0)//线段与上边界相交
{ //根据三角形相似的知识求出P1P2直线段与上边界的交点
y=YT;
x=x1+(x2-x1)*(YT-y1)/(y2-y1);
}
if(code==code1){
x1=x;
y1=y;
code1=encode(x,y);
}
else{
x2=x;
y2=y;
code2=encode(x,y);
}
}
DisplayLine(x1,y1,x2,y2,RED);
return;
}
int main()
{
initgraph(800,800);//根据测试结果初始化图形界面
//画裁剪区域
DisplayRec(XL,YT,XR,YB,GREEN);
//裁剪直线
DisplayLine(200,100,300,145,BLUE);
C_S_Line_CLip(200,100,300,145,150,350,350,150);//全部区域外
C_S_Line_CLip(200,200,250,250,150,350,350,150);//区域内
DisplayLine(50,180,400,180,YELLOW);
C_S_Line_CLip(50,180,400,180,150,350,350,150);//部分区域内
// 按任意键退出
getch();
closegraph();
return 0;
}