直线段裁剪算法

直线段裁剪算法一:Cohen-Sutherland算法

//编译环境:Visual C++ 6.0,EasyX_20190219(beta)
#include <graphics.h>
#include <conio.h>
#include <iostream>
#define left 1
#define right 2
#define bottom 4
#define top 8
using namespace std;
//设置裁剪框的大小和位置
double xl=120,xr=320,yt=240,yb=150;

//编码
void encode(double x,double y,int &code)
{
   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;}
   code=c;
}

//Cohen-Sutherland裁剪算法
int CS_LineClip(double x1,double y1,double x2,double y2)
{
   int code1,code2,code;
   int x,y;
   encode(x1,y1,code1);
   encode(x2,y2,code2);
   while(code1!=0||code2!=0)//都在里面时,直接画线,否则进行判断
   {
     if((code1&code2)!=0)  return 0;//都在外面舍弃
	 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;encode(x,y,code1);}
	 else
	 {x2=x;y2=y;encode(x,y,code2);}
   }
   line(x1,y1,x2,y2);
   return 0;
}


int main()
{   
	double x1,y1,x2,y2;
    initgraph(640, 480);  
    POINT points[]={ {xl,yt}, {xr,yt}, {xr,yb}, {xl,yb}};
	polygon(points,4);
    //用鼠标来获取两个点的坐标
	MOUSEMSG m;        // 定义结构体保存鼠标消息
    while (true)
    {flag:
        m = GetMouseMsg();// 获取一次鼠标消息
        switch (m.uMsg)//判断鼠标信息类型
        {
            case WM_LBUTTONDOWN:
			x1 = m.x; y1 = m.y;    //鼠标第一次按下时,获取鼠标当前坐标
            while (true)
            {
                m = GetMouseMsg();// 再次获取一条鼠标消息
                switch (m.uMsg)
                {
                case WM_LBUTTONDOWN:
					x2 = m.x; y2 = m.y;//鼠标第二次按下时,得到坐标
					setcolor(RED);
					line(x1, y1, x2, y2);
					setcolor(YELLOW);
					CS_LineClip(x1, y1, x2, y2);
					goto flag;
                }
            }
		}
	} 
	_getch();
	closegraph();
return 0;
}

演示如下所示:
在这里插入图片描述
直线段裁剪算法二:梁友栋-Barsky线段裁剪算法

//编译环境:Visual C++ 6.0,EasyX_20190219(beta)
#include<graphics.h>
#include<conio.h>
#include<iostream>
using namespace std;

//设置裁剪框的大小和位置,全局变量
double xl=120,xr=250,yt=270,yb=160;

bool ClipT(double q,double d,double &t0,double &t1)
{//当线段完全不可见时,返回false,否则,返回true
	double r;
	if(q<0)
	{
		r=(double)d/(double)q;
     	if(r>t1)
		  return false;
	    else if(r>t0)
		{t0=r;return true;}
	}
	else if(q>0)
	{
		r=(double)d/(double)q;
		if(r<t0)
			return false;
		else if(r<t1)
		{t1=r;return true;}
	}
	else if(d<0)
		return false;
	return true;
}


//梁友栋-Barsky线段裁剪算法
void LiangBarskyLineClip(double x0,double y0,double x1,double y1)
{
	double delatx,delaty,t0,t1;
	t0=0;t1=1;
	delatx=x1-x0;
	if(ClipT(-delatx,x0-xl,t0,t1))
		if(ClipT(delatx,xr-x0,t0,t1))
		{
			delaty=y1-y0;
			if(ClipT(-delaty,y0-yb,t0,t1))
				if(ClipT(delaty,yt-y0,t0,t1))
				{
					line((int)(x0+t0*delatx),(int)(y0+t0*delaty),
					     (int)(x0+t1*delatx),(int)(y0+t1*delaty));
					return;
				}
		}
}
int main()
{
	
	double x0,x1,y0,y1;
	initgraph(640,480);
    POINT points[]={ {xl,yt}, {xr,yt}, {xr,yb}, {xl,yb}};
	polygon(points,4);
	//用鼠标来获取两个点的坐标
	MOUSEMSG m;	
    while (true)
    {flag:
        m = GetMouseMsg();// 获取一次鼠标消息
        switch (m.uMsg)//判断鼠标信息类型
        {
            case WM_LBUTTONDOWN:
			x0 = m.x; y0 = m.y;    //鼠标第一次按下时,获取鼠标当前坐标
			//circle(x0,y0,2);
            while (true)
            {
                m = GetMouseMsg();// 再次获取一条鼠标消息
                switch (m.uMsg)
                {
                case WM_LBUTTONDOWN:
					x1 = m.x; y1 = m.y;//鼠标第二次按下时,得到坐标
					//circle(x1,y1,2);
					//
					setcolor(RED);
					//line(x0, y0, x1, y1);
					setcolor(YELLOW);
					LiangBarskyLineClip(x0,y0,x1,y1);
					goto flag;
                }
            }
		}
	} 
    
	_getch();
	closegraph();
	return 0;
}

直线时裁剪框以内的线段,演示如下:
在这里插入图片描述

  • 7
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Cohen-Sutherland直线裁剪算法是一种用于裁剪直线算法。它通过对直线的端点进行编码,并利用位运算来决定是否需要进行裁剪算法的步骤如下: 1. 将裁剪窗口分为九个区域,对应于二进制编码的九个位: - 0000: 线段完全在裁剪窗口内部 - 0001: 线段与窗口左边界相交 - 0010: 线段与窗口右边界相交 - 0100: 线段与窗口下边界相交 - 1000: 线段与窗口上边界相交 - 0101: 线段与窗口左下角相交 - 1001: 线段与窗口左上角相交 - 0110: 线段与窗口右下角相交 - 1010: 线段与窗口右上角相交 2. 对直线的两个端点进行编码,并根据编码判断线段是否需要进行裁剪。 - 如果两个端点的编码都为0000,表示线段完全在裁剪窗口内部,无需裁剪。 - 如果两个端点的编码的逻辑与运算结果不为0000,表示线段与窗口有交点,需要进行裁剪。 - 如果两个端点的编码的逻辑与运算结果为0000,表示线段与窗口无交点,且整条线段都在裁剪窗口外部,无需裁剪。 3. 如果线段需要进行裁剪,则根据需要裁剪的边界进行处理: - 如果线段与左边界相交,则根据线段方向求出相交点的坐标,并更新线段的起点。 - 如果线段与右边界相交,则根据线段方向求出相交点的坐标,并更新线段的终点。 - 如果线段与下边界相交,则根据线段方向求出相交点的坐标,并更新线段的起点。 - 如果线段与上边界相交,则根据线段方向求出相交点的坐标,并更新线段的终点。 4. 重复步骤2和步骤3,直到线段不需要裁剪或者已经被完全裁剪。 中点分割算法是另一种裁剪直线算法。它通过递归地将线段分割为左半边和右半边,并对每一半进行裁剪,直到无法再分割或者线段完全在裁剪窗口内部。 这两种算法都可以用来实现直线裁剪,具体选择哪种算法取决于具体的应用场景和需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值