【转】从零开始学图形学:10分钟看懂贝塞尔曲线

转自:https://zhuanlan.zhihu.com/p/344934774

从零开始学图形学:10分钟看懂贝塞尔曲线

引入

在画画的时候,你可能会遇到画曲线的情况。比如你想画一个肥宅的大肚子轮廓,此时你随手一画,发现不好看,感觉太鼓了,于是你只能重新画,再画一遍,发现太小了,于是只能再重新画,如此反复许多次之后,你终于画对了。

作为一个天才小画家,你心里想,如果有一个小滑块,可以在保证曲线平滑的情况下,通过拉动滑块实现曲线形状的调节,那不就不用来回画了吗!

嘿,您别说,还真有,这个东西就叫做贝塞尔曲线(Bézier curve),有了这个,你便可以像这样调节曲线:

是不是很熟悉?没错!贝塞尔曲线广泛应用于各种绘图相关的软件中,甚至计算机中的字体设计就全靠贝塞尔曲线来控制。

接下来,我们详细讲一讲贝塞尔曲线的原理。

一个简单的例子

讲之前,我们先看一张图:

这里的 P0、P1、P2 分别称之为控制点,贝塞尔曲线的产生完全与这三个点位置相关。

这也就意味着,我们可以通过调节控制点的位置,进而调整整个曲线。

贝塞尔曲线是一个对强迫症极其友好的曲线,看这个动图就让人很舒适,而它的构造方法也一样让人很舒适。

最开始,对于绿色线段的两头 Q0 和 Q1,将其分别放在 P0 和 P1 的位置,此时让它们运动,要求:Q0 往 P1 方向,Q1 往 P2 方向,分别匀速运动,并且同时到达线段的另一头。

转化成数学公式,即为

 

在绿色线段上再取一个点 B ,如果 B 在绿色线段上的运动也满足上述的规律,那岂不是很爽!所以不妨再规定:

 

令上述等式等于 t,t 肯定是 [0,1] 的,其意义是点在它所处线段的位置。那么随着 t 的增大,Q0、Q1、B 的位置也就随之确定了!最终 B 的轨迹,便构成了贝塞尔曲线。

递归性质

仔细观察一下上述的构造过程,我们可以观察到:

首先,有三个控制点;

三个控制点形成两个线段,每个线段上有一个点在运动,于是得到两个点;

两个点形成一个线段,这个线段上有一个点在运动,于是得到一个点;

最后一个点的运动轨迹便构成了贝塞尔曲线!

我们发现,实际上是每轮都是 n 个点,形成 n-1 条线段,每个线段上有一个点在运动,那么就只关注这 n-1 个点,循环往复。最终只剩一个点时,它的轨迹便是结果。

那么,似乎最开始的控制点,也不一定是三个?如果是四个、五个,甚至更多呢?

当然有——

如此一来,你会发现贝塞尔曲线内的递归结构。实际上,上述介绍的分别是三阶、四阶、五阶的贝塞尔曲线,贝塞尔曲线可以由阶数递归定义。

公式

到了最讨厌的公式环节。

点在线段上,可以用  来表示。如果你把整个递归的每一步都按这个展开,那么最终可以得到如下公式:

 

分段贝塞尔曲线

虽然贝塞尔曲线的阶数可以很高,但是如果曲线的阶数过高,调整控制点对曲线的影响就比较小,调整起来相当麻烦。

 

于是,我们常常使用分段的贝塞尔曲线,保证每一小段不会太复杂。这样每次只用调小段,还可以做到只调局部不影响大局,那就相当舒服了。

分段带来的唯一问题是,曲线在段与段的交界处,如何保证平滑?

所谓平滑,其实就是一阶导数连续,也就是左右导数的极限相同。

对两侧的贝塞尔曲线求导,分别代入 t=0 和 t=1 (即贝塞尔曲线的开始和结束时间),让二者相等。此时能发现,当两侧控制点与分段交接点共线且形成的线段长度相等时,满足曲线平滑性质。

 

再分享一个网站,可以在线玩贝塞尔曲线:链接

实验

内容:

  1. 完成贝塞尔曲线的递归定义函数。
  2. 对曲线进行反走样(Anti-Aliasing, AA)。

解析

简单的不得了,直接带入点在线段上的公式即可。

cv::Point2f recursive_bezier(const std::vector<cv::Point2f> &control_points, float t) 
{// TODO: Implement de Casteljau's algorithmif(control_points.size() == 1) return control_points[0];std::vector<cv::Point2f> a;for(int i = 0;i+1 < control_points.size();i ++) {auto p = control_points[i] + t * (control_points[i+1] - control_points[i]);a.push_back(p);}return recursive_bezier(a, t);
}

对于 AA ,只需要在曲线附近做点插值就行,满足离曲线越近的像素的像素值越高,越远的越低,即可。这里随便写了点:

  1. For 2*2 grids,  for each  .
void bezier(const std::vector<cv::Point2f> &control_points, cv::Mat &window) 
{// TODO: Iterate through all t = 0 to t = 1 with small steps, and call de Casteljau's // recursive Bezier algorithm.double delta = 0.001;for(double t = 0;t <= 1;t += delta) {auto point = recursive_bezier(control_points, t);int w = 1;for(int i = -w+1;i <= w;i ++) {for(int j = -w+1;j <= w;j ++) {int x = point.x + i, y = point.y + j;double dist = sqrt(pow(point.x-x,2) + pow(point.y-y,2));window.at<cv::Vec3b>(y, x)[1] = std::min(window.at<cv::Vec3b>(y, x)[1] + 255 * std::max(2-exp(dist),0.0), 255.0);// auto k = abs(((int)(point.x+1-i))-point.x) * abs(((int)(point.y+1-j))-point.y);// window.at<cv::Vec3b>(y, x)[1] = std::min(window.at<cv::Vec3b>(y, x)[1] + 255 * k, 255.0f);}}}}

注:图源网络、games101课件

 

本文首发于知乎专栏图形图像与机器学习,以后会常更新,欢迎大家的关注与催更。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/436003.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flex 学习随笔 ---- 使用WebService 与数据库连接

任何一个网络工具&#xff0c; 如果不能和数据打交道&#xff0c;那它就是失败的。 还好Flex是可以的&#xff0c;由于本人刚学&#xff0c;就用asp.netc#来讲下这个简单的连接。 Flex 和数据库通讯现在只能使用Service&#xff0c;如httpservice,rpcservice,webservice等等。 …

第三方登录android代码,Android Learning:微信第三方登录(示例代码)

这两天&#xff0c;解决了微信第三方授权登录的问题&#xff0c;作为一个新手&#xff0c;想想也是一把辛酸泪。我想着&#xff0c;就把我的遇到的坑给大家分享一下&#xff0c;避免新手遇到我这样的问题能够顺利避开。步骤一 微信开发者平台我开始的解决思路是&#xff0c;去这…

对象与函数

摘自《UMLOOPC嵌入式C语言开发精讲》 11.3 对象与函数11.3.1 函数的角色经济诺贝尔奖得主H.A.Simon&#xff08;H.A.Simon&#xff0c;计算机人工智能之父&#xff09;在其1962年的文章《The Architecture of Complexity》中说道&#xff1a;“从小系统建造成庞大系统时&…

android打包工具多渠道批量打包,Android 快速渠道批量打包详解教程-美团多渠道打包方案...

今天写一篇文章来总结下android批量打渠道包美团版本。之前项目上一直用的是gradle 批量打包方式&#xff0c;那个速度啊真是令人发指&#xff0c;15个渠道得跑上半个小时&#xff0c;出去吃顿饭回来&#xff0c;还在跑。特别是赶上项目上线的话&#xff0c;如果给测试提交了正…

【转】云社区 博客 博客详情 二维异形件排版算法介绍(一)

转自&#xff1a;https://bbs.huaweicloud.com/blogs/175385 【摘要】 排样问题&#xff08;Nesting Problem&#xff09;又称为下料问题(Cutting and stock problems)或填充问题(Packing Problem)&#xff0c;其目标是在材料切割过程中寻找一个较高的材料利用率。排样问题属于…

android 微信两个服务的,微信上线两个新功能

微信又上线新功能了&#xff01;一个与你的钱包相关&#xff0c;一个与你的微信号相关&#xff0c;赶紧来看看吧微信支付分全面开放每个微信用户都拥有自己的一个分数值 &#xff0c;且每月根据综合数据更新一次。达到一定的分值门槛&#xff0c;用户即可享受超千项便捷服务。这…

【转】二维异形件排版算法介绍(二)

转自&#xff1a;https://bbs.huaweicloud.com/blogs/196289【摘要】 二维不规则异形件主要有两种策略&#xff1a;分别是基于可行解的排样策略和基于重叠移除的排样策略。所谓基于可行解的排样策略&#xff0c;是指在排样过程中零件之间始终是不重叠的&#xff0c;而基于重叠移…

【转】介绍一些免费/开源的医学影像后处理工具

转自&#xff1a;https://blog.csdn.net/liaopiankun0618/article/details/84328331 来源&#xff1a;融视影像科技 综述 医学影像的处理有两个特质。一是复杂&#xff0c;整个处理流程涉及多种算法&#xff0c;需要调整的参数较多。二是发展快&#xff0c;从采集、重建到后…

android gradle 语法,Gradle 1.语法

8种机械键盘轴体对比本人程序员&#xff0c;要买一个写代码的键盘&#xff0c;请问红轴和茶轴怎么选&#xff1f;gradle 语法解析:gradle的语法十分简洁,以至于看起来跟像是配置文件。先看一个简单的android项目完整的gradle脚本&#xff1a;build.gradle123456789101112131415…

【转】二维异形件排版算法介绍(三)

转自&#xff1a;https://bbs.huaweicloud.com/blogs/203947 【摘要】 相比于基于可行解的排样算法&#xff0c;重叠移除算法在改变解的状态时&#xff0c;允许零件之间发生重叠&#xff0c;然后采用分离技术消除重叠&#xff0c;直到达到算法的终止条件为止。重叠移除算法的关…

【转】Dicom格式文件解析器!!!!!!!

转自&#xff1a;https://www.cnblogs.com/assassinx/archive/2013/01/09/dicomViewer.html Dicom全称是医学数字图像与通讯&#xff0c;这里讲的暂不涉及通讯的问题 只讲*.dcm 也就是diocm格式文件的读取&#xff0c;读取本身是没啥难度的 无非就是字节码数据流处理。只不过确…

【转】医学影像调窗技术!!!!

转自&#xff1a;https://www.cnblogs.com/assassinx/p/3139505.html 在年初的时候做过一个dicom格式文件解析&#xff0c;当时只是提了下。看着跟别人的显示出来也差不多 其实是我想太简单了。整理了下思路 这里提供正确的调窗代码。 医学影像 说得挺高科技的 其实在这个过程…

【转】理解字节序 大端字节序和小端字节序

转自&#xff1a;https://www.cnblogs.com/gremount/p/8830707.html 以下内容参考了 http://www.ruanyifeng.com/blog/2016/11/byte-order.html https://blog.csdn.net/yishengzhiai005/article/details/39672529 1. 计算机硬件有两种储存数据的方式&#xff1a;大端字节序…

创建windows服务,定时监控网站应用程序池

最近网站总是报"Timer_Connection"错误,导致该网站所使用的应用程序池由于错误过多停止运行,网站也就出现了service unvaliable,无法访问,在网上查了很多资料,结果很让人无奈,这个问题已经困扰我了很久,一直没有得到解决,后来同事发来一篇文章让我有了新的解决方法,虽…

【转】Qtcreator中常用快捷键和小技巧

转自&#xff1a;https://blog.csdn.net/imxiangzi/article/details/48863855 https://blog.csdn.net/jh1513/article/details/52346802 快捷键及对应含义 下载地址&#xff1a;http://download.csdn.net/detail/jh1513/9615209 快捷键 功能 Esc 切换到代码编辑状态 F1 …

【转】VS编译时自动引用Debug|Release版本的dll

转自&#xff1a;https://www.cnblogs.com/KevinYang/archive/2011/04/10/2011879.html 公司一些早期的项目&#xff0c;把所有工程都放到一个解决方案下了&#xff0c;导致整个解决方案编译很慢&#xff0c;而且也不便于类库的复用和维护。因此我们决定把工程按照功能划分到不…

【转】DICOM之Print!!!!!!!!!

转自&#xff1a;https://blog.csdn.net/weixin_41556165/article/details/81064531 基本概念&#xff1a; Film:在DICOM协议中使用Film来统称不同的Hard Copy&#xff0c;例如photographic film和paper。 DICOM Print的数据流由Print Session、Print Job、Print&#xff08;h…

静态html js文件上传,js实现动态添加上传文件页面

发邮件是需要添加一些文件&#xff0c;每添加一个文件&#xff0c;页面上可以显示一个表单文件上传选项。此功能为&#xff1a;初始时刻只有一个添加按钮&#xff0c;当点击添加文件时&#xff0c;会增加一个选择文件和删除区域&#xff0c;同时显示上传按钮&#xff0c;当点击…

WINCE6.0文件系统及存储管理器

*******************************LoongEmbedded******************************** 作者&#xff1a;LoongEmbedded 时间&#xff1a;2010.12.03 类别&#xff1a;WINCE嵌入式系统 ********************************LoongEmbedded******************************** Filesys.…

【转】Wireshark网络抓包(一)——数据包、着色规则和提示

转自&#xff1a;https://www.cnblogs.com/strick/p/6261463.html 一、数据包详细信息 Packet Details面板内容如下&#xff0c;主要用于分析封包的详细信息。 帧&#xff1a;物理层、链路层 包&#xff1a;网络层 段&#xff1a;传输层、应用层 1&#xff09;Frame 物理层…