opengl算法学习--- 直线裁剪算法

Posted springfield-psk

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opengl算法学习--- 直线裁剪算法相关的知识,希望对你有一定的参考价值。

裁剪是从数据集合提取信息的过程,它是计算机图形学许多重要问题的基础。裁剪典型的用途就是从一个大的场景中提取所需的信息,以显示某一局部场景或视图。比如浏览地图时,对感兴趣的区域放大显示,此时窗口内显示的内容会相应减少。确定图形的哪些部分在窗口内,哪些部分在窗口外(不可见区域),只显示窗口内的那部分图形,这个选择处理过程就是裁剪。
这里详细讲述两种算法

Cohen-Sutherland编码裁剪算法

稍后再补

Liang-Barsky算法

概念
技术图片

Liang-Barsky算法的基本思想是,从 A、B 和 P1中找出最靠近 P2的点,如图所示为 P1;从C 、D 和 P2中找出最靠近P1的点,显然为C 点;也即 PC1即为裁剪后部分。

具体实现
技术图片
对于区域内存在的线段P1P2,根据两点坐标构造方程

[x=x_{1}+u(x_{2}-x_{1}) ]

[y=y_{1}+u(y_{2}-y_{1}) ]

(Delta x=x_{2}-x_{1} Delta y=y_{2}-y_{1})
即可推出

[x=x_{1}+uDelta x ]

[y=y_{1}+uDelta y ]

技术图片
Liang-Barsky算法通过计算两端点截取后的u值,绘制截取后的线段,设截取后线段的两端点u为(u_{1}、u_{2})
(u_{1})初始值=0,即线段初始点,(u_{2})初始值=1,即线段终点
对于x而言

[x_{l} leqslant x leqslant x_{r} ]

同理

[y_{b} leqslant y leqslant y_{t} ]

[Rightarrow left{egin{matrix} x_{l} leqslant x_{1}+uDelta x leqslant x_{r} y_{b} leqslant y_{1}+uDelta y leqslant y_{t} end{matrix} ight. ]

即可推得

[Rightarrow left{egin{matrix} uDelta x leqslant x_{r}-x_{1} -uDelta x leqslant x_{1}-x_{l} uDelta y leqslant y_{t}-y_{1} -uDelta y leqslant y_{1}-y_{b} end{matrix} ight. ]

构造

[p_{k} leqslant q_{k} ,k={1,2,3,4} ]

每个k对应上式每种情况

[Rightarrow left{egin{matrix} p_{1}=Delta x & q_{1}=x_{r}-x_{1} p_{2}=-Delta x & q_{2}=x_{1}-x_{l} p_{3}=Delta y & q_{3}=y_{t}-y_{1} p_{4}=-Delta y & q_{4}=y_{1}-y_{b} end{matrix} ight. ]

(p_{k}=0)时,该线段平行于轮廓线
如果(q_{k}<0)
当k=1时,(x_{r}<x_{1})
当k=2时,(x_{1}<x_{l})
当k=3时,(y_{t}<y_{1})
当k=4时,(y_{1}<y_{b})
可推出若(q_{k}<0)时,该线段位于裁剪区域外
如果(q_{k}geqslant 0)
则该线段位于区域内
(p_{k} eq 0)时,
此时线段延长线与轮廓线交点在上式中u值(=frac{q_{k}}{p_{k}})
(p_{k}<0) 则该线段部分为由边界外到边界内,(u_{1}=max(u_{1},u))
(p_{k}>0) 则该线段部分为由边界内到边界外,(u_{2}=min(u_{2},u))
通过以上过程,可推出截取后线段两端点的(u_{1})(u_{2}),若(u_{1}>u_{2}),则该线段不为于裁剪区域内

代码实现

void LiangBarsky(Point p1,Point p2,Rectan rec)
{
    float u1=0,u2=1,p[4],q[4];
    p[0]=p1.x-p2.x;p[1]=p2.x-p1.x;
    p[2]=p1.y-p2.y;p[3]=p2.y-p1.y;
    q[0]=p1.x-rec.xl;q[1]=rec.xr-p1.x;
    q[2]=p1.y-rec.yb;q[3]=rec.yt-p1.x;
    for(int i=0;i<4;i++)
    {
        if(!p[i] && q[i]<0) return ;
        else if(p[i])
        {
            float u=q[i]/p[i];
            if(p[i]<0) u1=max(u1,u);
            else u2=min(u2,u);
        }
    }
    if(u1>u2) return ;
    drawline(Point(p1.x+u1*(p2.x-p1.x),p1.y+u1*(p2.y-p1.y)),Point(p1.x+u2*(p2.x-p1.x),p1.y+u2*(p2.y-p1.y)),BLUE);
}

以上是关于opengl算法学习--- 直线裁剪算法的主要内容,如果未能解决你的问题,请参考以下文章

opengl算法学习--直线绘制

OpenGL学习进程(13)第十课:基本图形的底层实现及算法原理

实验二 直线生成算法

裁剪算法——Cohen-Sutherland算法

计算机图形学:直线段扫描转换算法

视频二次裁剪时间计算出原片的时间片段算法