0.补充知识
向量点积:结果等于0, 两向量垂直; 结果大于0, 两向量夹角小于90度; 结果小于0, 两向量夹角大于90度.
直线的参数方程:(x1, y1)和(x2, y2)两点确定的直线, 其参数方程为x = x1+u(x2-x2); y = y1+u(y2-y1)

1.前言
Liang-Barsky算法是 Cyrus-Beck 算法的特例, 我们先来简单的了解Cyrus-Beck算法, Cyrus-Beck算法本质是每次通过裁剪窗口(任意凸多边形, 文章最后会说明为什么凹多边形不行)的一条边界来确定待裁剪线段的哪部分应当被留下, 最后, 对所有应该被留下的部分取交集, 便可以求得线段应当留下的部分.举个例子, 假设多边形ABCDE, 那么我们每次使用一条边(AB, BC, …), 延长这条边和待裁剪的线段, 那么最后两条直线必定相交或平行, 如果相交, 根据交点确定哪部分被留下, 如果平行, 根据坐标确定哪部分被留下. 而Liang-Barsky算法只是将这个裁剪窗口固定为了一个平行于坐标轴的矩形, 所以Liang-Barsky算法和Cyrus-Beck算法本质是一样的, 只是Liang-Barskys算法因为拥有更多信息(裁剪窗口是一个平行与坐标轴的矩形), 可以对其中一些步骤进行简化处理.

2.对于一条边界, 具体如何确定线段应当留下的部分?

2.1符号说明
AB:边界直线, 把整个平面划分为两部分, 我们约定向量AH所在区域称为内部区域, 另一部分称为外部区域
AH:边界直线的法向量, AH=(1,0)
CD:待裁剪线段,C(x1, y1), D(x2, y2),CD的向量表示为 (x1+u(x2-x1), y1+u(y2-y1))(0<=u<=1)
E,F,G:待裁剪线段上三点

2.2判定方法
向量AH*向量AG, 结果大于0, H点处于内部区域
向量AH*向量AF, 结果等于于0, F点位于边界上
向量AH*向量AE, 结果小于0, E点处于外部区域
所以, 通过AX(X为线段CD上任意一点)与法向量AH的乘积即可判定X点位于内部区域还是外部区域

3.对于任意凸多边形边界, 如何确定线段应当留下的部分?
任意凸多边形边界和直线边界没有本质区别, 如果对于矩形上的所有边, 点X都满足属于这条边的内部区域, 那么X就在矩形的内部区域.(比如图中的IG部分)

4.Liang-Barsky的算法流程以及算法中的p和q

4.1算法流程

以AB边为例, X为CD上任意一点, 矩形边界的左右上下边界分别为XL, XR, YT, YB
因为向量AH*向量AX>=0时, X点在AB的内部区域
所以我们现在求解这个不等式:
向量AH*向量AX>=0
向量AH*(向量OX-向量OA)>=0;
由CD的向量表示式可知
(1,0)*(x1+u(x2-x1)-XL, y1+u(y2-y1)-YA)>=0;(我们不用关心YA的具体值, 请不要在此纠结)
x1+u(x2-x1)-XL>=0;
假设x2-x1>0(图中是大于0, 但是对于任意直线, 可能大于0, 小于0, 等于0)
则u>=(XL-x1)/(x2-x1)时, 点X在直线AB的内部区域
假设x1-x2<0
则u<=(XL-x1)/(X2-X1)时, 点X在直线AB的内部区域
如果x2-x1=0,则简单判断x1和XL的大小, 如果x1<XL, 舍去, 否则保留
本步执行完后, 我们得到一个关于u的不等式

同理对矩形另外三条边做如上处理, 我们得到另外3个不等式
我们现在观察一下这四个不等式
因为AB边和IJ边的法向量x坐标值为-1和1
那么如果AB边算出的不等式是u>=(XL-x1)/(x2-x1), 则IJ边算出来一定是u<=(XR-x1)/(x2-x1)(因为IJ边计算时仅仅是把XL换成XR, 1换成-1, 不理解请自己按照上述步骤计算一下), 我们可以发现, 互相平行的两条边算出来的不等式一个是>=那么另一个一定是<=(其实就是一维裁剪, 确定线段的上限和下限).
那么对4条边分别进行如上处理, 会得到u<=ans1, u<=ans2, u>=ans3, u>=ans4这4个不等式
ans1,ans2为u可能的上限, ans3,ans4为u可能的下限
又因为参数方程实际上是表示一条直线, 而我们需要裁剪的是一条线段, 所以u应当在0和1之间
于是
令umax = min(ans1, ans2, 1);//因为是取交集, 所以我们应在可能的上限中取最小的那个
umin = max(ans3, ans4, 0);
如果umax<umin则没有线段位于裁剪窗口的内部
否则将参数u带进参数方程, 求得裁剪之后线段的两个端点
最后利用端点画出裁剪结果即可

4.2算法中的p和q
L, R, T, B是对应边上的一点
(1,0)*(x1+u(x2-x1)-XL, YL) >=0;
(-1,0)*(x1+u(x2-x1)-XR, YR) >=0;
(0,1)*(XB, y1+u(y2-y1)-YB) >=0;
(0,-1)*(XT, y1+u(y2-y1)-YT) >=0;
令p1 = -(x2 - x1); p2 = -p1
p3 = -(y2 - y1); p4 = -p3
上面的不等式变为
x1+u*p2-XL>=0;
-x1+u*p1+XR>=0;
y1+u*p4-YB>=0;
-y1+u*p3+YT>=0;
移项
u*p2>=XL-x1;
u*p1>=x1-XR;
u*p4>=YB-y1;
u*p3>=y1-YT;
同时乘上-1(为了让不等式组看起来有序)
u*p1<=x1-XL;
u*p2<=XR-x1;
u*p3<=y1-YB;
u*p4<=YT-y1;
令q1 = x1-XL;
...
q4 = YT-y1;
假设p1<0, p3<0
u>=q1/p1
u>=q3/p3
u<=...
u<=...
不等式取交集即可得到u的范围, 可以看到p和q并没有明显的物理意义, 请不要纠结于此
5.Liang-Barsky的c++代码实现

void LiangBarsky(int x1, int y1, int x2, int y2, int XL, int XR, int YT, int YB)
{int ansx1, ansx2, ansy1, ansy2;//三种类型//平行于y轴if (x1 - x2 == 0){if (x1<XL || x1>XR){return;}else{int ymin = max(YB, min(y1, y2));int ymax = min(YT, max(y1, y2));if (ymin <= ymax){ansx1 = ansx2 = x1;ansy1 = ymin;ansy2 = ymax;}else{return;}}}//平行于x轴else if (y1 - y2 == 0){if (y1<YB || y1>YT){return;}else{int xmin = max(XL, min(x1, x2));int xmax = min(XR, max(x1, x2));if (xmin <= xmax){ansy1 = ansy2 = y1;ansx1 = xmin;ansx2 = xmax;}else{return;}}}//不平行于坐标轴else{float p1, p2, p3, p4;float q1, q2, q3, q4;p1 = -(x2 - x1);p2 = -p1;p3 = -(y2 - y1);p4 = -p3;q1 = x1 - XL;q2 = XR - x1;q3 = y1 - YB;q4 = YT - y1;float u1, u2, u3, u4;u1 = q1 / p1;u2 = q2 / p2;u3 = q3 / p3;u4 = q4 / p4;float umin, umax;if (p1 < 0){if (p3 < 0){umin = max(0, max(u1, u3));umax = min(1, min(u2, u4));}else{umin = max(0, max(u1, u4));umax = min(1, min(u2, u3));}}else{if (p3 < 0){umin = max(0, max(u2, u3));umax = min(1, min(u1, u4));}else{umin = max(0, max(u2, u4));umax = min(1, min(u1, u3));}}if (umin <= umax){ansx1 = x1 + umin * (x2 - x1);ansx2 = x1 + umax * (x2 - x1);ansy1 = y1 + umin * (y2 - y1);ansy2 = y1 + umax * (y2 - y1);}elsereturn;}//调用函数重绘直线YourDrawFunc();return;
}

6.教材上的算法流程和解题实例
相信有了上面的基础, 再回头看书上对于Liang-Barsky算法的讲解, 就不会一头雾水了.
相关内容在这篇博文中已经写的很清楚了, 故本文不在赘述.
[计算机图形学经典算法] Liang-Barsky(梁友栋-Barsky) 算法 (附Matlab代码): https://blog.csdn.net/soulmeetliang/article/details/79185603

7.从Liang-Barsky算法到Cyrus-Beck算法
7.1为什么凹多边形无法使用Cyrus-Beck算法?

因为凹多边形的边界不一定保证把平面区域分成多边形内部和外部两个区域

7.2Cyrus-Beck算法如何求得边界法向量?
Liang-Barsky算法因为裁剪窗口得特殊性, 每条边界得法向量我们作为已知量来处理. Cyrus-Beck中需要自己确定法向量, 思路如下: 根据边界(假定为AB)确定垂直于边界的法向量(a1, a2), 任取多边形除了本次边界上两点之外的任意一点P, 计算向量AP(BP)*a1, 大于0取a1, 否则取a2

7.3u的上下限对应关系
Liang-Barsky算法中, 我们知道平行的两条边一条提供上限则另一条提供下限. 对于更一般的凸多边形裁剪窗口, 则是与线段延长线相交的两条边界延长线对应的边界. 从不等式来看, xi+u*(xj-xi)中的(xj-xi)决定了得到u的上限还是下限, 可以据此实现上下限的区分.

8.参考资料

[计算机图形学经典算法] Liang-Barsky(梁友栋-Barsky) 算法 (附Matlab代码): https://blog.csdn.net/soulmeetliang/article/details/79185603

理解梁友栋-Barsky裁剪算法: https://blog.csdn.net/Daisy__Ben/article/details/51941608

梁友栋-Barsky算法原理: http://www.voidcn.com/article/p-niexnvwo-rv.html

作者:kkbeta

出处:https://www.cnblogs.com/kkbeta/

版权所有,欢迎保留原文链接进行转载:) 

理解Liang-Barsky裁剪算法的算法原理相关推荐

  1. 中点分割裁剪算法 c语言,裁剪算法——中点分割算法/Liang-Barsky算法

    三.中点分割法 首先对直线段的端点进行编码. [核心思想:通过二分逼近来确定直线段与窗口的交点.] 具体方法: 1.若中点不在窗口内,则把[中点]和离窗口边界[最远点]构成的线段丢掉,以线段上的另一点 ...

  2. 理解梁友栋-Barsky裁剪算法

    学习图形学窗口裁剪算法时,很多教材只是对梁友栋-Barsky裁剪算法过程做了简单的介绍,并没有对原理过多的解释.老而学者如秉烛夜行,用了两三天时间终于搞明白算法原理. 消除指定区域内或区域外的图形部分 ...

  3. 计算机图形学:Cohen-Sutherland直线段剪裁算法及梁友栋-Barsky裁剪算法(算法原理及代码实现)

    一.算法实现原理 Cohen-Sutherland直线段剪裁算法: 算法原理: (1)判断线段两端是否都落在窗口内,如果是,则线段完全可见,否则进行下一步 (2)判断线段两端是否都落在窗口外,如果是, ...

  4. 深入理解 Java 虚拟机 - 你了解 GC 算法原理吗

    来自:好好学Java 虚拟机系列文章 深入理解 Java 虚拟机(第一弹) - Java 内存区域透彻分析 深入理解 Java 虚拟机(第二弹) - 常用 vm 参数分析 深入理解 Java 虚拟机- ...

  5. SMO(Sequential Minimal Optimization)算法的数学原理

    SMO算法的数学原理 前言 SVM问题回顾 SMO算法 两个朗格朗日乘子的解析解 选择哪两个乘子需要被优化的启发式方法 计算阈值 线性SVM的一个优化 代码细节 前言 紧跟着SVM数学原理之后,又拿出 ...

  6. DL之DNN之BP:神经网络算法简介之BP算法/GD算法之不需要额外任何文字,只需要八张图讲清楚BP类神经网络的工作原理

    DL之DNN之BP:神经网络算法简介之BP算法/GD算法之不需要额外任何文字,只需要八张图讲清楚BP类神经网络的工作原理 目录 BP类神经网络理解 1.信号正向传播FP 2.误差反向传播BP+GD B ...

  7. 深度学习算法 | LSTM算法原理简介及Tutorial

    北京 | 深度学习与人工智能研修 12月23-24日 再设经典课程  重温深度学习 阅读全文 > 正文共4880个字 17张图,预计阅读时间:13分钟. 1.背景 LSTM(Long Short ...

  8. 理解快速傅里叶变换(FFT)算法

     编注:这篇译文由@unblock 和@jingliang 共同完成. 再次推荐:<如果看了此文你还不懂傅里叶变换,那就过来掐死我吧[完整版]> 快速傅里叶变换(Fast Fourie ...

  9. Java中CAS(Compare And Swap,比较和交换)算法的技术原理简述

    - title: Java中CAS(Compare And Swap,比较和交换)算法的技术原理简述 - date: 2021/8/14 文章目录 CAS全称 Compare And Swap,是一种 ...

  10. Reddit 评级算法的工作原理

    Reddit 评级算法的工作原理 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python-with-elementtr ...

最新文章

  1. 从源码分析DEARGUI之背变换
  2. 微软程序在Android上跑,想在Win 10上运行Android应用?这类手机用户已经可以尝鲜...
  3. APK安装时如何拷贝apk里的文件到sdcard
  4. php获取当前设备,Linux_在Linux系统中使用lsblk和blkid显示设备信息的方法,今天我们将会向你展示如何使 - phpStudy...
  5. rto初始化和计算_TCP系列13—重传—3、协议中RTO计算和RTO定时器维护
  6. c#中ReadLine,Read,ReadKey的区别
  7. 数字人民币这一年,互联网企业做了什么?
  8. 路印zkRollup AMM将在月底启动流动性挖矿
  9. linux重定向权限不够,linux – 如何使用sudo将输出重定向到一个我没有权限写入的位置?...
  10. 【BZOJ-3573】米特运输 树形DP
  11. 计算机房用还原保护软件,“小哨兵”还原卡v9.1在机房的巧妙应用
  12. Android嵌入式组态软件
  13. Django DTL 加减乘除求余
  14. 金融 数据库 mysql_MySQL 和 PostgreSQL 哪个更适合做金融数据库
  15. mybatis-plus 属性为空时判断问题
  16. ios开发App的图标背景色不能是透明
  17. c++语言运算符,c++运算符
  18. Java插入Excel指定行
  19. nyoj 1237 最大岛屿(dfs)
  20. 肖特基二极管(SBD)和开关二极管的工作原理及选型的学习总结

热门文章

  1. 领峰:普通人如何炒白银技巧和方法有哪些
  2. 三个“清洁代码”技巧将使您的开发团队效率提高 50%
  3. Elasticsearch 7 Failed to parse value [analyzed] as only [true] or [false] are allowed.
  4. 微信小程序 满意度调查问卷
  5. 什么是AOP(通俗易懂)
  6. 电脑右下角音量键打不开,调不了音量大小的解决方法
  7. 【JAVA视频压缩】-------轻量级视频压缩组件JAVE
  8. Evenly Separated Strings
  9. Spring Cloud入门-Oauth2授权之JWT集成(Hoxton版本)
  10. C#百度OCR本地图片识别文字