图形学初步--裁剪算法之Liang-Barsky算法
一、概念
裁剪是CG中许多重要问题的基础,裁剪最典型的用途是确定场景中或画面中位于给定区域之内的部分。由于在一个典型的场景之中,需要对大量的点、线段进行裁剪,因此裁剪算法的效率十分重要。
关于裁剪有一些很常见的算法,比如说Cohen-Sutherland线段细分裁剪算法、中点分割算法、Cyrus-Beck算法、Liang-Barsky算法。这篇文章重点讲Liang-Barsky算法。剩下的那些算法有空再补。
二、Liang-Barsky算法
参考博客:
https://www.cnblogs.com/keguniang/p/9688126.html
https://blog.csdn.net/pleasecallmewhy/article/details/8393445
首先知道直线和裁剪框的位置关系,如下图:
可以看到直线可能完全在裁剪框的外面,也可能完全在裁剪框的里面,或者和裁剪框相交。
所以是裁剪的规则是这样的:
如果直线的两个端点都在窗口边界之内,如ab,则直线保留;如果直线的一个端点在窗口边界之内,另一个端点在窗口边界之外,如ef,则应从直线与边界的交点处裁剪掉边界之外的线段;如果直线的两个端点都在窗口边界之外,有两种情况:一种情况如ij,直线全部在窗口之外,应该全部裁减掉;另一种情况如gh,直线横穿窗口边界,应该保留相交的片段,裁减掉剩余的片段;
那么怎么去判断呢? 在讲述判断步骤之前我们要了解一个基础理论,那就是编码:
图中阴影部分是裁剪框,我们把这个区域分成了9份,采用了四位数标识线段的端点位于九个区域的哪个区域位置,从右往左数:
第一个位置为1-------如果线段端点位于窗口左侧第二个位置为1------如果线段端点位于窗口右侧第三个位置为1------如果线段端点为窗口下面第四个位置为1------如果线段位于窗口上面
------------------------------------------------------------------接下来是算法推导-----------------------------------------------------------------------------
如下图所示
1.我们用方程表示直线P1P2,其中t就是直线的斜率,t∈[0,1]:
裁剪区域内部可以表达为两个不等式:
把直线方程代入得到不等式:
即
2.把直线看成是一条有方向的线段,把窗口的四条边及其延长线分成两类:入边和出边
入边:左边界和下边界------从裁剪框外向裁剪框内
出边:右边界和上边界------从裁剪框内向裁剪框外
3.分情况讨论
①d=0,q<0, 说明直线与裁剪框平行,并且位于裁剪框的外面,直线为不可见,可抛弃,直接结束
q>=0,说明直线在它所平行的窗口边界的内部,还需进一步计算确定直线是否在窗口内、外、或者相交
②d<0,说明直线是从裁剪边界的外部延伸到内部
③d>0, 说明直线是从裁剪边界的内部延伸到外部
对于d≠0,可以利用式子计算直线与边界k的交点的参数u。对于每条直线,可以计算直线位于裁剪窗口内线段的参数d1和d2
d1的值是由那些使得直线是从外部延伸到内部的窗口边界决定。对于这些边计算ri = qi/di.
d1 = max(ri,0)
d2的值是由那些使得直线是从内部延伸到窗口边界决定
d2 = min(ri,1)
如果d1>d2,这条直线完全在窗口的外面,不可见,可抛弃,否则,根据参数u的两个值,计算出裁剪后线段的端点
如果没有看懂,可以看该博主的https://blog.csdn.net/pleasecallmewhy/article/details/8393445
所以伪代码如下:
#Liang-Barsky two-dimensional clipping algorithm
#P1 and P2 are the line end points with components x1,y1,x2,y2
#tL and tU are the lower and upper parametric limits
#xL,xR,yB,yT are the left,right,bottom and top window edgesfunction clipt(d,q,tL,tU):clipt performs trivial rejection tests and findsthe max of the lower set of parameter values and the min of the upper set of parameter valuesvisible = trueif d=0 and q<0 then #line is outside and parallel to edgevisible = falseelse if d < 0 then #looking for upper limitt = q/dif t>tU then #check for trivial invisiblevisible = falseelse if t>tL then #find the min of the maxtL = tend ifelse if d>0 then #look for the lower limitt = q/dif t<tL then #check for trivial invisiblevisible = falseelse if t<tU then #find the max of the mintU = tend ifend ifreturn visibleend functionstart the main funciton:tL=0,tU=1delatx = x2-x1if clipt(-delatx,x1-xL,tL,tU) = true then #left edgeif clipt(delatx,xR-x1,tL,tU) = true then #right edgedeltay = y2-y1if clipt(-deltay,y1-yB,tL,tU) = true then #bottom edgeif clipt(deltay,yT-y1,tL,tU) = true then #top edgeif tU<1 then x2 = x1+tU*delatxy2 = y1+tU*deltayend ifif tL>0 thenx1 = x1+tL*deltaxy1 = y1+tL*deltayend ifDraw P1,P2end ifend ifend ifend iffinish
最终实现的代码如下:
#include <windows.h>
#include <GL/glut.h>
#include <math.h>
#include<stdio.h>
float xmin,xmax,ymin,ymax;void myinit(void)
{glShadeModel (GL_FLAT);glClearColor (1.0, 1.0, 1.0, 0.0);
}void myReshape(int w, int h)
{glViewport(0, 0, w, h);glMatrixMode(GL_PROJECTION);glLoadIdentity();if (w <= h) gluOrtho2D (0.0, 1.0, 0.0, 1.0*(GLfloat)h/(GLfloat)w);else gluOrtho2D (0.0, 1.0*(GLfloat)w/(GLfloat)h, 0.0, 1.0);glMatrixMode(GL_MODELVIEW);
}int Clip(float p,float q,float *tL,float *tU)
{ int flag=1;/*flag为标志变量0表示舍弃1表示可见*/ float r; if (p<0.0) { r=q/p; if (r>*tU)flag=0; else if (r>*tL) {*tL = r;/*m取进入点最大参数值*/ } } else if (p>0.0) { r=q/p; if (r<*tL)flag=0; else if (r<*tU) {*tU = r;/*n取离开点的最小值*/ } } else if (q<0 && p==0) //平行于边界而且在界外的线 flag=0; return flag;
}
void myclip()
// line clipping algorithm
{float dx, dy, x1,tL,tU, x2, y1, y2;tL = 0, tU = 1.0;printf("请输入线段的两个顶点坐标x1,y1,x2,y2:\n");scanf("%f%f%f%f",&x1,&y1,&x2,&y2);glBegin(GL_LINES); glColor4f (0.0, 0.0, 0.0, 0.0); glVertex2f(x1, y1); // line startpoint glVertex2f(x2, y2); // line endpoint glEnd(); dx=x2-x1; if (Clip(-dx, x1 - xmin, &tL, &tU))if (Clip(dx, xmax - x1, &tL, &tU)){dy=y2-y1; if (Clip(-dy, y1 - ymin, &tL, &tU))if (Clip(dy, ymax - y1, &tL, &tU)){ if (tU<1.0) { x2 = x1 + tU*dx;//通过n求得裁剪后的p2端点 y2 = y1 + tU*dy;} if (tL>0.0){ x1 = x1 + tL*dx;//通过m求得裁剪后的p1端点 y1 = y1 + tL*dy;} glBegin(GL_LINES); glColor4f (1.0, 0.0, 0.0, 1.0); glVertex2f( x1, y1); // clipped line startpoint glVertex2f( x2, y2); // clipped line endpoint glEnd();} } }void display(void){glClear(GL_COLOR_BUFFER_BIT);printf("请分别输入矩形的左右下上边界:\n");scanf("%f%f%f%f",&xmin,&xmax,&ymin,&ymax);glColor4f (1.0, 1.0, 0.0, 0.75);glBegin(GL_POLYGON);glVertex2f( xmin, ymin); // Bottom LeftglVertex2f( xmax, ymin); // Bottom LeftglVertex2f( xmax, ymax); // Bottom RightglVertex2f( xmin, ymax); // Bottom RightglEnd();myclip();glFlush();
}/* Main Loop* Open window with initial window size, title bar, * RGBA display mode, and handle input events.*/
int main(int argc, char** argv)
{glutInit(&argc, argv);glutInitDisplayMode (GLUT_SINGLE | GLUT_RGBA);//define size and the relative positon of the applicaiton window on the displayglutInitWindowSize (500, 500); glutInitWindowPosition (100, 100);//init the defined window with "argv[1]" as topic showed on the top the windowglutCreateWindow (argv[0]);// opengl setupmyinit ();//define callbacksglutDisplayFunc(display); glutReshapeFunc(myReshape);//enter the loop for displayglutMainLoop();return 1;
}
在运行该代码之前需要配置opengl环境,若没有配置,请参考该博客:https://blog.csdn.net/keneyr/article/details/83626935
代码运行结果如下:
图形学初步--裁剪算法之Liang-Barsky算法相关推荐
- 图形学初步--------种子填充算法
上篇博文讲到了填充算法的扫描线填充,这篇博文讲解另一大算法思路----------种子填充. 一.概念 种子填充算法假设在多边形或区域内部至少有一个像素是已知的.然后设法找到区域内所有其他像素,并对它 ...
- 裁剪任意直线段 liang-barshky算法 c
一. 实验目的. 使用liang-barshky算法实现裁剪任意直线段实验工具 二. 实验工具 VC6.0 三. 实验步骤 思想:以直线的参数方程为基础: X=x1 + u(x2-x1) Y =y1 ...
- 计算机图形学第一次上机——中点线算法和中点圆算法
计算机图形学第一次上机实验 课程实验报告 目录 计算机图形学第一次上机实验 课程实验报告 一.实验目的 二.实验环境 三.实验内容 1.中点线算法 2.中点圆算法 四.实验心得 附录:程序源代码 一. ...
- 算法(一) 算法初步
算法(一) 算法初步 1. 十进制转为二进制(除二取余法) 简单的求值方法: 给出一个数字x,求x十进制各位相加的和 (将它转化为二进制呢?) temp=1; while(x>0){ ans+= ...
- 算法设计与分析——算法基础初步了解
算法的概念 算法:一个有计算步骤构成的序列,可以将一组输入值转换成相应的输出值.或可以用例解决一个明确的问题. 问题:输入及相应输出的描述: 算法的特点:确定性.可行性.输入和输出及有穷性. 正确的算 ...
- 图形学基础笔记I:直线和圆的光栅算法、中点线算法、中点圆算法
实际现代显卡支持的图元就只有点.线.三角形.这是基于这样的事实: 实际对于 3D 来说肯定全是基于三角形的 geometry - OpenGL: Is it more efficient to use ...
- 经典算法书籍推荐以及算法书排行【算法四库全书】
经典算法书籍推荐以及算法书排行[算法四库全书] 作者:霞落满天 https://linuxstyle.blog.csdn.net/ https://blog.csdn.net/21aspne ...
- 数据挖掘算法_算法篇(01) 数据挖掘算法初探
前言 无论是传统行业,还是互联网行业.掌握数据,就是掌握规律.当你了解了市场数据,对它进行分析,就可以得到市场规律.当你掌握了产品自身的数据,对它进行分析,就可以了解产品的用户来源.用户画像等等.所以 ...
- hash的算法 java_【数据结构与算法】一致性Hash算法及Java实践
追求极致才能突破极限 一.案例背景 1.1 系统简介 首先看一下系统架构,方便解释: 页面给用户展示的功能就是,可以查看任何一台机器的某些属性(以下简称系统信息). 消息流程是,页面发起请求查看指定机 ...
- 最佳适应算法和最坏适应算法_算法:好,坏和丑陋
最佳适应算法和最坏适应算法 by Evaristo Caraballo 通过Evaristo Caraballo 算法:好,坏和丑陋 (Algorithms: The Good, The Bad an ...
最新文章
- JavaScript 爆红后,微软为何还要开发 TypeScript?
- 程序员总结:帮助你早些明白一些道理
- 简述Linux文件系统通过i节点把文件的逻辑结构和物理结构转换的工作过程。
- 打工人一次性考过高项的备考指南(52.50.50)
- 数据科学学习课件:实用数据挖掘与人工智能
- 班尼机器人怎么拆_512个焊点独自焊完,武汉一高中生在机器人比赛中摘得五块奖牌...
- SAP Fiori Launchpad tile跳转目标的解析逻辑
- LeetCode 881. 救生艇(贪心,双指针)
- java nio 面试题_10个最高频的Java NIO面试题剖析!
- python工厂模式和单例模式_python之单例模式和工厂模式
- ARCore学习指引四剑客:原生、Unity、Unreal和WebAR
- android自定义鼠标指针,修改Android系统的鼠标光标
- 原型工具Axure:Axure的实用小技巧
- 硬盘录像机常见问题解答硬盘录像机故障解决
- C++语言里的pow函数(初学)
- c 语言编程规则,C语言编程之 makfile规则.doc
- 为什么使用PHP语言?Web开发使用的PHP优势是什么?
- 奥维互动地图GEE协议历史影像分析与应用
- 2022完整版青龙面板对接傻妞机器人
- net start mysql:无法启动