计算机小白也看得懂的Liang-Barsky算法
个人博客:www.vectormoon.net
算法背景
Liang-Barsky算法由梁友栋和Barsky共同发表,是目前计算机图形学最经典的算法之一。他们认为线段裁剪的问题是:裁剪窗口是二维对象,而线段是一维对象,两个对象的维度不同不便比较。他们给出的解决思路是,将裁剪线段和裁剪窗口看为点集裁剪的结果是两个点集的交集。
算法思想
Liang-Barsky算法的主要思想有两部分:
- 用参数方程表示直线
- 将待裁剪直线看作是一个有方向的线
用参数方程表示直线
算法背景中提到Liang-Barsky算法的解决思路是,将裁剪线段和裁剪窗口看为点集裁剪的结果是两个点集的交集。那么裁剪线段如何转换点集呢?很显然用参数方程来表示直线。
设待裁剪线段为P1P2P_1P_2P1P2,其中P1=(x1,y1),P2=(x2,y2)P_1=(x_1,y_1),P_2=(x_2,y_2)P1=(x1,y1),P2=(x2,y2),用参数关系u表示有下图关系:
显见有如下关系:
{x=x1+u∗(x2−x1)=x1+u∗Δx0≤u≤1;y=y1+u∗(y2−y1)=y1+u∗Δy0≤u≤1.\begin{cases}x=x_1+u*(x2-x1)=x_1+u*\Delta x & 0\leq u \leq 1;\\y=y_1+u*(y2-y1)=y_1+u*\Delta y & 0\leq u \leq 1.\end{cases}{x=x1+u∗(x2−x1)=x1+u∗Δxy=y1+u∗(y2−y1)=y1+u∗Δy0≤u≤1;0≤u≤1.
当u=0u=0u=0时,x=x1,y=y1x=x_1,y=y_1x=x1,y=y1也就是P1P_1P1;
当u=1u=1u=1时,x=x2,y=y2x=x_2,y=y_2x=x2,y=y2也就是P2P_2P2;
当u=0.5u=0.5u=0.5时,也就是该直线中点位置。
由上面三种情况可以很容易归纳出该图像的几何意义:也就是u值即可表示要裁剪线段的多少
将待裁剪直线看作是一个有方向的线
从上面我们知道u的取值可以决定线段要裁剪的多少,那么u到底如何取值变成了现在的首要目标?
我们将四个窗口的交边分别定义成两类边:入边和出边
- 入边:指从裁剪窗口之外进入到裁剪窗口方向的边
- 出边:指从裁剪窗口之内延伸到窗口之外的边
待裁剪线段和裁剪窗口必定会有四个交点(包括与裁剪窗口延长线的交点)分别设四个交点分别为c1,c2,c3,c4c_1,c_2,c_3,c_4c1,c2,c3,c4。设待裁剪直线为P1P2P_1P_2P1P2。则有下图:
显见要裁剪线段为P1P_1P1和c3c_3c3所夹线段,所以u的选取就要从P1,c3P_1,c_3P1,c3所对应u1,u2u_1,u_2u1,u2入手,则显见有如下关系式:
u1=max(c1,c2,P1)u_1=max(c_1,c_2,P_1)u1=max(c1,c2,P1) u1u_1u1是两个入边和P1P_1P1对应u值的最小值
u2=min(c3,P2,c4)u_2=min(c_3,P_2,c_4)u2=min(c3,P2,c4) u2u_2u2是两个出边和P2P_2P2对应u值的最大值
u1,u2u_1,u_2u1,u2的值要满足u1<u2u_1<u_2u1<u2
只要求出u1,u2u_1,u_2u1,u2就能算出裁剪线段,但是要求出u1,u2u_1,u_2u1,u2的话,就又出现了两个新的问题:
- 如何算出四个交点c1,c2,c3,c4c_1,c_2,c_3,c_4c1,c2,c3,c4所对应的u值
- 如何确定哪两个边是出边,哪两个边是入边
四个交点对应的u值
在上面用参数方程表示直线章节中,我们提出了:
{x=x1+u∗(x2−x1)=x1+u∗Δx0≤u≤1;y=y1+u∗(y2−y1)=y1+u∗Δy0≤u≤1.\begin{cases}x=x_1+u*(x2-x1)=x_1+u*\Delta x & 0\leq u \leq 1;\\y=y_1+u*(y2-y1)=y_1+u*\Delta y & 0\leq u \leq 1.\end{cases}{x=x1+u∗(x2−x1)=x1+u∗Δxy=y1+u∗(y2−y1)=y1+u∗Δy0≤u≤1;0≤u≤1.
我们不妨先考虑下,在u为何值时,(x,y)(x,y)(x,y)位于裁剪窗口之内?我们设裁剪窗口的上边界为ymaxy_{max}ymax,下边界为yminy_{min}ymin,左边界为xminx_{min}xmin,右边界为xmaxx_{max}xmax,结合上式有:
{xmin≤x1+u∗Δx≤xmaxymin≤y1+u∗Δy≤ymax\begin{cases}x_{min}\leq x_1+u*\Delta x \leq x_{max}\\ y_{min}\leq y_1+u*\Delta y \leq y_{max}\end{cases}{xmin≤x1+u∗Δx≤xmaxymin≤y1+u∗Δy≤ymax
可以看出当
{x1+u∗Δx=xminx1+u∗Δx=xmaxy1+u∗Δy=yminy1+u∗Δy=ymax\begin{cases}x_1+u*\Delta x=x_{min}\\ x_1+u*\Delta x=x_{max}\\y_1+u*\Delta y = y_{min}\\y_1+u*\Delta y = y_{max}\end{cases}⎩⎪⎪⎪⎨⎪⎪⎪⎧x1+u∗Δx=xminx1+u∗Δx=xmaxy1+u∗Δy=yminy1+u∗Δy=ymax
时,为裁剪直线和四个边界的交点值,所以我们可以很轻松的算出四个对应的u值,此处不在赘述。
出入边的确定
上面我们只提到了不等式的四个特殊情况,不失一般性,这里我们写出不等式的所有情况:
{xmin≤x1+u∗Δx≤xmaxymin≤y1+u∗Δy≤ymax\begin{cases}x_{min}\leq x_1+u*\Delta x \leq x_{max}\\ y_{min}\leq y_1+u*\Delta y \leq y_{max}\end{cases}{xmin≤x1+u∗Δx≤xmaxymin≤y1+u∗Δy≤ymax
可化简为:
{u∗(−Δx)≤x1−xminu∗Δx≤xmax−x1u∗(−Δy)≤y1−yminu∗Δy≤ymax−y1\begin{cases} u*(-\Delta x) \leq x_1 - x_{min}\\ u*\Delta x \leq x_{max} - x_1\\ u*(-\Delta y) \leq y_1 - y_{min}\\ u*\Delta y \leq y_{max} - y_1\\ \end{cases}⎩⎪⎪⎪⎨⎪⎪⎪⎧u∗(−Δx)≤x1−xminu∗Δx≤xmax−x1u∗(−Δy)≤y1−yminu∗Δy≤ymax−y1
上面四种情况可以归纳成
u∗pk≤qk,k=1,2,3,4u*p_k\leq q_k,k=1,2,3,4u∗pk≤qk,k=1,2,3,4
使用穷举法可知:
- 当pk<0p_k<0pk<0时,线段从裁剪边界延长线的外部延伸到内部,也就是入边
- 当pk>0p_k>0pk>0时,线段从裁剪边界延长线的内部延伸到外部,也就是出边
显见,当pk=0p_k=0pk=0时,且qk<0q_k<0qk<0,则线段完全在边界外;若qk≥0q_k\geq 0qk≥0,则线段完全在边界内
代码实现
def Liang-Barsky(p_list, x_min, y_min, x_max, y_max):"""线段裁剪:param p_list: (list of list of int: [[x0, y0], [x1, y1]]) 线段的起点和终点坐标:param x_min: 裁剪窗口左上角x坐标:param y_min: 裁剪窗口左上角y坐标:param x_max: 裁剪窗口右下角x坐标:param y_max: 裁剪窗口右下角y坐标:return: (list of list of int: [[x_0, y_0], [x_1, y_1]]) 裁剪后线段的起点和终点坐标"""result = []if y_min > y_max:y_min, y_max = y_max, y_minx0, y0 = p_list[0]x1, y1 = p_list[1]p = [x0-x1, x1-x0, y0-y1, y1-y0]q = [x0-x_min, x_max-x0, y0-y_min, y_max-y0]u0, u1 = 0, 1for i in range(4):if p[i] < 0:u0 = max(u0, q[i]/p[i])elif p[i] > 0:u1 = min(u1, q[i]/p[i])elif (p[i] == 0 and q[i] < 0):result = [[0,0], [0,0]]return resultif u0 > u1:result = [[0,0], [0,0]]return resultif u0 > 0:res_x0 = int(x0 + u0*(x1-x0) + 0.5)res_y0 = int(y0 + u0*(y1-y0) + 0.5)if u1 < 1:res_x1 = int(x0 + u1*(x1-x0) + 0.5)res_y1 = int(y0 + u1*(y1-y0) + 0.5)result = [[res_x0, res_y0], [res_x1, res_y1]]return result
计算机小白也看得懂的Liang-Barsky算法相关推荐
- 小白一看就懂的前后端接口连接
作为刚入职的小白,总是听前辈们说"连接口很简单的 ,一看就懂",由于鄙人实在是才疏学浅,实在是绕的头晕眼花,不知道怎么肥事.于是耐心用一下午仔细研究每一句代码,研究他们之间的联系, ...
- 小白都看得懂的使用Python生成随机验证码图片,以及后续优化方案
环境:Anaconda3-2020.02 首先我们分解一下需要做什么: 生成随机的字母字符串 生成生成随机的背景色 生成随机的字体颜色 把随机的字符串用随机的颜色渲染,然后放到一块随机的背景色上面,基 ...
- Spring Framework框架起步,小白都看得懂(官翻版)!
写在开头 本篇章介绍Spring框架的完整的全部技术.写这篇文章的目的是,一方面为了给初入后端开发的才子一篇入门指导,另一方面是为了自己对于基础知识的查阅. Spring不一定是最好的框架(虽然综合能 ...
- C语言--getchar()函数超详细解析(多维度分析,小白一看就懂!!!)
目录 一.前言 二.什么是getchar()函数 三.getchar()函数的返回类型与机制 四.连续单个字符串 (代码演示) 五.getchar()函数其他用法,实战演练(重点) (1)按照题目写出 ...
- Modbus协议解析--小白一看就懂的协议
文章目录 提问三连 1.什么是Modbus? 2.Modbus用来干什么? 3.Modbus的内容是什么? 3.1 Modbus-RTU+Modbus-ASCII 3.1.1 Modbus-RTU协议 ...
- 计算机的大小端存储模式(计算机小白必看!)
目录 1.什么是大端小端 2.为什么会有大小端模式之分呢? 3.如何判断当前机器为大端字节序还是小端字节序 本文将介绍计算机存储数据时的大小端问题 1.什么是大端小端 大端(存储)模式,是指数据的低位 ...
- Arcgis: 利用xls文件绘制地图+细节参数调整(新手小白一看就懂)
软件版本: 用到的地理数据库: 国家基础地理数据400万 常用链接: 地图底图(国家基础地理数据 / 在线底图 / BIGEMAP抠底图) 标准底图服务系统 全国地理信息资源目录服务系统 在线经纬度转 ...
- php - 超详细将 pdf 文档格式转换为图片格式,将 offce pdf 演示文稿转成图像 png / jpg(小白一看就懂的详细教程,附带完整示例源代码)
效果图 其他教程都有点乱而且有bug,本文站在新手小白的角度比较靠谱,超详细的完整流程及详细注释代码. 本文实现了 php 将 pdf 文档转为图片(png / jpg),完整流程及示例源代码, 你可 ...
- 小白都看得懂的监督学习与无监督学习
hello~一晃就十一月啦!开始写简书也半个月啦!之前对机器学习中的监督学习与无监督学习,只是有个概念,前几天学习知识的时候,又遇到了,所以打算好好记录下来. 在理解监督学习和无监督学习之前,我们先来 ...
- python类定义学生信息_Python学生信息管理系统(注释最详细,小白都看的懂)
1 importos2 3 #学生系统基本功能 4 #增删查改 5 6 #如何实现该系统 7 #1.显示系统功能界面 8 #2.让用户选择功能 9 #3.判断用户选择的指定功能,然后完成相应的操作(增 ...
最新文章
- RONG出创新—2019年度春季学期“医工结合系列研讨会”圆满落幕
- OAM K8s 标准实现 Crossplane 项目进入 CNCF Sandbox
- Memcached 学习---(4)Memcached 连接
- 大数据如何助力农业发展
- 记一次远程协助的排错案例
- Spring Cloud Stream
- 抠图 php中文网,ps cs3怎么抠图
- 在推送Git之前合并多个提交[重复]
- SCI收录的文献类型与认证的文献类型
- www.etiger.vip DEVC++练习(入门)
- mysql 保留小数位数的一个方法
- 百度搜索引擎对站长越来越嚣张,已经放弃做什么百度优化咯
- 【listener hangs】监听hangs,导致新的连接无法连接数据库
- 计算机操作系统-文件管理
- vnpy 查询持仓量_vn.py 数据入库
- mysql实现postgres中pg_size_pretty函数
- 【商业信息】GB 11643—1999 公民身份号码
- 重做系统之后,如何配置java完整环境
- 窗口跑屏幕外面了怎么办
- Facebook速推帖子和Facebook广告有什么区别
热门文章
- 谷歌浏览器设置免跨域 Mac
- php性格属于哪类,狗狗性格分为6大类,你家是属哪一类?快来是看聪明型还是粘人型...
- 使用maven引用第三方jar包
- Encountered unexpected token:XXXXX
- 人间繁华江上明月,乃浮生一梦,惟真情长在——读沈君山《浮生再记》(并转书评)...
- PC机(笔记本)安装Linux系统
- python 对 PDF 的拆分 和合并
- 高德地图Amap绘制路线首尾相连问题
- php动态效果,jquery+php实现动态数字显示效果
- 使用Markdown进行计划安排(打钩)