算法原理
将线段分为以下三种情况处理
(1)若P1P2完全在窗口内,则显示该线段P1P2,–简取
(2)若P1P2完全在窗口外,则丢弃该线段。–简弃
(3)若线段不满足(1)(2)时,则把线段分为两段,其中一段完全在窗口外,再重复上述判断能否取或弃
编码
对于不同区域的点进行如下编码,假设窗口,左侧(XL)右侧(XR)上侧(YT)下侧(YB),
区域编码:对于点P(x,y) code=ABCD(二进制)
x < XL D=1 x > XR C=1
y < YB B=1 y > YT A=1
可获得该点对应得编码
如下图
对于之前得三种情况如下:
P1的编码 : code1 P2的编码 : code2
(1)完全在窗口内,则有 code1 | code2 = 0
(2)完全在窗口外,则有 code1 & code2 != 0
(3)与窗口相交,求交,将窗口外的线段丢弃,再进行裁剪
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);
}
源码
#include<iostream>
#include<easyx.h>
#include<graphics.h>
using namespace std;
#define LEFT 1
#define RIGHT 2
#define BOTTOM 4
#define TOP 8
#define XL 0
#define XR 200
#define YB 0
#define YT 100
int encode(float x,float y);
void Cohen_SutherLand(float x1,float y1,float x2,float y2);
void displayline(float x0,float y0,float x1,float y1,int color);
int main()
{
Cohen_SutherLand(-10,-10,200,200);
return 0;
}
int encode(float x,float y)
{
int code=0;
if(x<XL) code=code|LEFT;
else if(x>XR) code=code|RIGHT;
if(y<YB) code=code|BOTTOM;
else if(y>YT) code=code|TOP;
return code;
}
void Cohen_SutherLand(float x1,float y1,float x2,float y2)
{
initgraph(640,480);
setorigin(200,200);
displayline(XL,YB,XR,YB,0xFFFFFF);
displayline(XL,YT,XR,YT,0xFFFFFF);
displayline(XL,YB,XL,YT,0xFFFFFF);
displayline(XR,YB,XR,YT,0xFFFFFF);
int code1,code2,code;
float x,y;
code1=encode(x1,y1);
code2=encode(x2,y2);
while(code1!=0||code2!=0)
{
if((code1&code2)!=0)
return ;
code=code1;
if(code1==0)
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);
}
else
{
x2=x;
y2=y;
code2=encode(x,y);
}
}
displayline(x1,y1,x2,y2,0xFFFF00);
getchar();
getchar();
closegraph();
}
void displayline(float x0,float y0,float x1,float y1,int color)
{
int t;
float dx,dy,k,y,x;
dx=x1-x0;
dy=y1-y0;
k=dy/dx;
if(k<=1)
{
y=y0;
for(t=x0;t<=x1;t++)
{
putpixel(t,int(y+0.5),color);
y=y+k;
}
}
else
{
k=1/k;
x=x0;
for(t=y0;t<=y1;t++)
{
putpixel(int(x+0.5),t,color);
x=x+k;
}
}
}
运行结果:
所用包链接
EasyX
链接:https://pan.baidu.com/s/1UQn2-iFlgbSbIfze_c0lSg
提取码:6j7r