计算机图形学-3.3用中点分割裁剪算法实现直线段裁剪
程序员文章站
2022-07-14 10:01:22
...
(1)算法设计原理
(2)程序关键代码
//处理(x1,y1)(x2,y2)两点,计算(x1,y1)的最近可见点得(xx,yy)
bool Mid_line1(double x1,double y1,double x2,double y2,int *x,int *y)
{
int code1,code2,code;
double xx,yy;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
if(code1==0)
{
*x=x1;*y=y1; //如果(x1,y1)在窗口内,(x1,y1)即是可见点
}
else if((code1&code2)!=0)
{
return false; //如果(x1,y1),(x2,y2)在窗口外的同一侧,直线在窗口外
}
else
{
do{
xx=(x1+x2)/2.0; //计算(x1,x2)(x2,y2)的中点
yy=(y1+y2)/2.0;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
encode(xx,yy,&code);
if(code==0) //新的中点在窗口内
{
x2=xx;
y2=yy;
encode(x2,y2,&code2);
}
else
{
if((code&code1)!=0) //在一侧
{
x1=xx;
y1=yy;
encode(x1,y1,&code1);
}
else
{
x2=xx;
y2=yy;
encode(x2,y2,&code2);
}
}*x=xx;*y=yy;
}while(pm(xx,yy));
}
return true;
}
//处理(xx,yy)(x2,y2)两点,计算(x2,y2)的最近可见点得(xxx,yyy)
bool Mid_line2(double x1,double y1,double x2,double y2,int *x,int *y)
{
//(xx,yy)在窗口内
int code1,code2,code;
double xx,yy;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
if(code2==0) //如果(x2,y2)也在窗口内,(xxx,yyy)是(x2,y2);
{
*x=x2;*y=y2;
}
else
{
do{
xx=(x1+x2)/2.0;
yy=(y1+y2)/2.0;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
encode(xx,yy,&code);
if(code==0)
{
x1=xx;
y1=yy;
encode(x1,y1,&code1);
}
else
{
x2=xx;
y2=yy;
encode(x2,y2,&code2);
}*x=xx;*y=yy;
}while(pm(xx,yy));
}
return true;
}
(3)运行结果截屏(对数据输入的说明)
完整代码:
#define xl 150
#define xr 300
#define yb 150
#define yt 300
#define LEFT 1
#define RIGHT 2
#define BOTTOM 4
#define TOP 8
#include <stdio.h>
#include <graphics.h>
#include <math.h>
#include<conio.h>
#include<math.h>
bool pm(double xx,double yy)
{
if(fabs(xx-xl)<1 || abs(xx-xr)<1 || abs(yy-yb)<1 || abs(yy-yt)<1)
return false;
else
return true;
}
//算出每个点的code
void encode(double x,double y,int *code)
{
int c=0;
if(pm(x,y)==false) //可见点记为窗口内
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;
*code=c;
}
//处理(x1,y1)(x2,y2)两点,计算(x1,y1)的最近可见点得(xx,yy)
bool Mid_line1(double x1,double y1,double x2,double y2,int *x,int *y)
{
int code1,code2,code;
double xx,yy;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
if(code1==0)
{
*x=x1;*y=y1; //如果(x1,y1)在窗口内,(x1,y1)即是可见点
}
else if((code1&code2)!=0)
{
return false; //如果(x1,y1),(x2,y2)在窗口外的同一侧,直线在窗口外
}
else
{
do{
xx=(x1+x2)/2.0; //计算(x1,x2)(x2,y2)的中点
yy=(y1+y2)/2.0;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
encode(xx,yy,&code);
if(code==0) //新的中点在窗口内
{
x2=xx;
y2=yy;
encode(x2,y2,&code2);
}
else
{
if((code&code1)!=0) //在一侧
{
x1=xx;
y1=yy;
encode(x1,y1,&code1);
}
else
{
x2=xx;
y2=yy;
encode(x2,y2,&code2);
}
}*x=xx;*y=yy;
}while(pm(xx,yy));
}
return true;
}
//处理(xx,yy)(x2,y2)两点,计算(x2,y2)的最近可见点得(xxx,yyy)
bool Mid_line2(double x1,double y1,double x2,double y2,int *x,int *y)
{
//(xx,yy)在窗口内
int code1,code2,code;
double xx,yy;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
if(code2==0) //如果(x2,y2)也在窗口内,(xxx,yyy)是(x2,y2);
{
*x=x2;*y=y2;
}
else
{
do{
xx=(x1+x2)/2.0;
yy=(y1+y2)/2.0;
encode(x1,y1,&code1);
encode(x2,y2,&code2);
encode(xx,yy,&code);
if(code==0)
{
x1=xx;
y1=yy;
encode(x1,y1,&code1);
}
else
{
x2=xx;
y2=yy;
encode(x2,y2,&code2);
}*x=xx;*y=yy;
}while(pm(xx,yy));
}
return true;
}
void main()
{
int xx=0;
int yy=0;
int xxx=0;
int yyy=0;
double x0,y0,x1,y1;
initgraph(640,480);
setlinecolor(WHITE);
line(xl,yt,xr,yt);
line(xl,yb,xr,yb);
line(xl,yt,xl,yb);
line(xr,yt,xr,yb);
//用鼠标来获取两个点的坐标
MOUSEMSG m;
while (true)
{flag:
m = GetMouseMsg();// 获取一次鼠标消息
switch (m.uMsg)//判断鼠标信息类型
{
case WM_LBUTTONDOWN:
x0 = m.x; y0 = m.y; //鼠标第一次按下时,获取鼠标当前坐标
setcolor(RED);
circle(x0,y0,2);
while (true)
{
m = GetMouseMsg();// 再次获取一条鼠标消息
switch (m.uMsg)
{
case WM_LBUTTONDOWN:
x1 = m.x; y1 = m.y;//鼠标第二次按下时,得到坐标
setcolor(RED);
circle(x1,y1,2);
setcolor(RED);
line(x0, y0, x1, y1);
if(Mid_line1(x0,y0,x1,y1,&xx,&yy) && Mid_line2(xx,yy,x1,y1,&xxx,&yyy))
{
setcolor(YELLOW);
line(xx,yy,xxx,yyy);
}
goto flag;
}
}
}
}
}