欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

计算机图形学-3.3用中点分割裁剪算法实现直线段裁剪

程序员文章站 2022-07-14 10:01:22
...

(1)算法设计原理
计算机图形学-3.3用中点分割裁剪算法实现直线段裁剪
(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)运行结果截屏(对数据输入的说明)
计算机图形学-3.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;
                }
            }
		}
	}
}

相关标签: 计算机图形学