Cohen-Sutherland算法

算法思路


分别判断直线 ( 线段 ) 的两个端点落在哪个区域。判断的方法是将端点和裁剪框的边界比较。然后确定线段与矩形框上边界的交点 ( 四舍五入取整 ) ,端点落在 C 区域无需求交点,落在其他区域需要。当端点落在 N S W E 区域时只要将裁剪框边界值带入直线方程即可。当某端点落在 NW NE SW SE 区域时有两个交点 C D B 端点位于 S SW 区域类似)。如图:

C D 选正确的。

两个端点确定了位置之后,有下面几种情况:


1.       两个端点位于裁剪框边界同一侧,无法裁剪。


2.       端点都在 C 区域,无需裁剪。

具体算法

//返回0-成功,1-无法裁剪,线段不在裁剪框中,-1失败
//使用两点式求交点 y-y0 = (x-x0)*(y1-y0)/(x1-x0)
//y = (x-x0)*(y1-y0)/(x1-x0) + y0;
//x = (y-y0)*(x1-x0)/(y1-y0) + x0;
//浮点数+0.5再赋给整数即可将浮点数四舍五入
int Cohen_Sutherland::Clip_line(int LineX1,int LineY1,int LineX2,int LineY2 ,
                            int RectX1,int RectY1,int RectX2,int RectY2 ,
                            int &LineX3,int &LineY3,int &LineX4,int &LineY4 )
{
#define CLIP_CODE_C        0x0000
#define CLIP_CODE_W        0x0001
#define CLIP_CODE_E        0x0002
#define CLIP_CODE_S        0x0004
#define CLIP_CODE_N        0x0008
#define CLIP_CODE_SW       0x0005
#define CLIP_CODE_SE       0x0006
#define CLIP_CODE_NW       0x0009
#define CLIP_CODE_NE       0x000a

    int Code1 = 0,Code2 = 0,Temp = -1;

    LineX3 = LineX1;
    LineY3 = LineY1;
    LineX4 = LineX2;
    LineY4 = LineY2;

    if (RectX1 > RectX2)
    {
        Temp = RectX2;
        RectX2 = RectX1;
        RectX1 = Temp;
    }
    if (RectY1 > RectY2)
    {
        Temp = RectY2;
        RectY2 = RectY1;
        RectY1 = Temp;
    }

    if (LineX1 < RectX1)
    {
        Code1 |= CLIP_CODE_W;
    }
    if (LineX1 > RectX2)
    {
        Code1 |= CLIP_CODE_E;
    }
    if (LineY1 < RectY1)
    {
        Code1 |= CLIP_CODE_N;
    }
    if (LineY1 > RectY2)
    {
        Code1 |= CLIP_CODE_S;
    }
    if (LineX2 < RectX1)
    {
        Code2 |= CLIP_CODE_W;
    }
    if (LineX2 > RectX2)
    {
        Code2 |= CLIP_CODE_E;
    }
    if (LineY2 < RectY1)
    {
        Code2 |= CLIP_CODE_N;
    }
    if (LineY2 > RectY2)
    {
        Code2 |= CLIP_CODE_S;
    }

    if (Code1 & Code2)
    {
        return 1;
    }
    if (Code1==0 && Code2==0)
    {
        return 0;
    }
    switch(Code1)
    {
    case CLIP_CODE_C:
        break;
    case CLIP_CODE_W:
        {
            LineX3 = RectX1;
            LineY3 = (LineX3-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            break;
        }
    case CLIP_CODE_E:
        {
            LineX3 = RectX2;
            LineY3 = (LineX3-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            break;
        }
    case CLIP_CODE_S:
        {
            LineY3 = RectY2;
            LineX3 = (LineY3-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            break;
        }
    case CLIP_CODE_N:
        {
            LineY3 = RectY1;
            LineX3 = (LineY3-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            break;
        }
    case CLIP_CODE_SW:
        {
            LineY3 = RectY2;
            LineX3 = (LineY3-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX3 < RectX1)
            {
                LineX3 = RectX1;
                LineY3 = (LineX3-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    case CLIP_CODE_SE:
        {
            LineY3 = RectY2;
            LineX3 = (LineY3-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX3 > RectX2)
            {
                LineX3 = RectX2;
                LineY3 = (LineX3-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    case CLIP_CODE_NW:
        {
            LineY3 = RectY1;
            LineX3 = (LineY3-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX3 < RectX1)
            {
                LineX3 = RectX1;
                LineY3 = (LineX3-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    case CLIP_CODE_NE:
        {
            LineY3 = RectY1;
            LineX3 = (LineY3-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX3 > RectX2)
            {
                LineX3 = RectX2;
                LineY3 = (LineX3-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    }

    switch(Code2)
    {
    case CLIP_CODE_C:
        break;
    case CLIP_CODE_W:
        {
            LineX4 = RectX1;
            LineY4 = (LineX4-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            break;
        }
    case CLIP_CODE_E:
        {
            LineX4 = RectX2;
            LineY4 = (LineX4-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            break;
        }
    case CLIP_CODE_S:
        {
            LineY4 = RectY2;
            LineX4 = (LineY4-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            break;
        }
    case CLIP_CODE_N:
        {
            LineY4 = RectY1;
            LineX4 = (LineY4-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            break;
        }
    case CLIP_CODE_SW:
        {
            LineY4 = RectY2;
            LineX4 = (LineY4-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX4 < RectX1)
            {
                LineX4 = RectX1;
                LineY4 = (LineX4-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    case CLIP_CODE_SE:
        {
            LineY4 = RectY2;
            LineX4 = (LineY4-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX4 > RectX2)
            {
                LineX4 = RectX2;
                LineY4 = (LineX4-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    case CLIP_CODE_NW:
        {
            LineY4 = RectY1;
            LineX4 = (LineY4-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX4 < RectX1)
            {
                LineX4 = RectX1;
                LineY4 = (LineX4-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    case CLIP_CODE_NE:
        {
            LineY4 = RectY1;
            LineX4 = (LineY4-LineY1)*(LineX2-LineX1)/(LineY2-LineY1) + LineX1 + 0.5;
            if (LineX4 > RectX2)
            {
                LineX4 = RectX2;
                LineY4 = (LineX4-LineX1)*(LineY2-LineY1)/(LineX2-LineX1) + LineY1 + 0.5;
            }
            break;
        }
    }

    if (LineX3<RectX1 || LineX3>RectX2
        || LineX4<RectX1 || LineX4>RectX2
        || LineY3<RectY1 || LineY4>RectY2
        || LineX4<RectY1 || LineY4>RectY2)
    {
        return 1;
    }

    return 0;
}

值得注意的地方:

四舍五入取整可以将浮点数 +0.5 赋给整型实现。

两点式直线方程 ,y-y0 = (x-x0)*(y1-y0)/(x1-x0).

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值