android高级之贝塞尔曲线上基本概念德卡斯特里奥算法cexo

看到中间的上下两个曲线了吧,它们用到了,当然这是一个二阶贝塞尔【啥叫二阶贝塞尔呢?下面会学习到】,也是最最基础的,了解了基础的画法,对于它更加复杂的画法你也比较容易上手了,好,这是一个整体的目标。

首先要明白,对于贝塞尔曲线,它是分阶的,不同的阶数,其绘制的曲线效果也不一样,所以这里先来了解不同阶数的贝塞尔曲线的绘制情况。

先看一下效果:

一条直线。。不是贝塞尔是用来绘制曲线的么?是的,因为对于一阶贝塞尔实际没啥用,但是对于你了解它的概念是一个基础,等于它的核心目的其实就只是由两点控制的一条直线,绘制就是从一点绘制到另一点的整个轨迹,记住这个绘制过程,因为在理解二阶贝塞尔曲线的过程中,需要使用到它。

对于二阶贝塞尔曲线来说,应该是应用最最广泛的,也是核心中的核心,对于贝塞尔曲线不是还有更加高阶复杂的曲线么?而要理解更加复杂的贝塞尔曲线,理解二阶就成为一个必须要掌握的了,只有掌握了二阶的画法,你才能更加从容的面对更加复杂的贝塞尔曲线,所以这块务必要理解透。

先来直观的感受一下它的绘制过程:

嗯,此图来自于csdn,看完此效果之后是不是觉得挺酷炫的?而在上面QQ汽泡效果中的那个曲线,是不是跟这个二阶曲线能联系起来?这也就是为啥在之后的贝塞尔曲线的案例应用时QQ汽泡效果使用的是二阶贝塞尔的原因了,但是你能看懂它的绘制规则么?反正我光看这动图还是一脸懵逼的,所以接下来会了解其原理,这样才能真正理解它。

先明显对于二阶贝塞尔曲线是由三个点来进行构成的,如下:

其中AC这两点本来是应该绘制一条直线的对吧:

但是该直线需要受B点往下进行拖动,这个B其实就是一个控制点,正因为有这个控制点才会让本应该绘直线的最终变成了绘制曲线了,其实在我们电脑的绘制软件中也能直观的感受一下这个B点的控制点的魅力,比如我mac上用Paintbrush这个软件有一个曲线的绘制:

我要绘制一条曲线,也是先绘制一条直线,然后再通过对直线的拖拽才完成曲线的绘制的,如下:

所以,此时应该对于B点它的出现的意义有了直观的了解了吧,接下来重点是就来看一下这个曲线的绘制规则了,这里先把两点到控制点连接两条直线,如下:

然后曲线的整体绘制是由AB这条一阶贝塞尔曲线来控制:

那AC的这根曲线很显然也是由一大堆的点的连续构成的对吧,让曲线上的绘制点又是如何来确定的呢?现在整个曲线的控制是由AB这个贝塞尔曲线来控制,它是一个运动的轨迹【这一点必须要理解到位,它是不断在走的,不明白的可以看一下一阶贝塞尔曲线的那个动图】,也就是AB上走了多少个点,就会对应的生成曲线上的各个点,这里以AB上的某一个静止点进行分析,把它如何确定最终曲线上的绘制点的搞清楚了,你也就明白了整个曲线的绘制原理了,比如AB上的贝塞尔曲线走到D这个点了:

其中这条直线上的AD跟DB就有一个比例关系了对吧,这时在BC上也取一个点E,其比例跟D点比例一样【注意关键词,比例要一样】,如下:

好,此时将DE进行一个连线:

接下来的绘制点就是在DE上了,那。DE上对应的绘制点是如何确定的呢?也是同样的套路,在这条直线上取一点F,要保证比例跟AD的一样,如下:

此时F点就是最终要绘制在曲线上的一个点【注意它只是曲线上的一个点哟】,如下:

曲线上的某个点我们已经知道怎么算出来了,我们由A-C开始启动绘制,则会算出曲线上的N个点,用PATH记录这个点进行绘制,从而y就得到了一条曲线,这条曲线就是所谓的贝塞尔曲线。这里再来回忆一下整个二阶贝塞尔曲线完整的绘制过程:

其中t表示整个曲线的点的次数,盯着那根绿色的那根线看,是不是能感受到比例正好跟P0到P1的一阶贝塞尔走的位置比例一样,截一个静态图说明一下:

但是我看不太懂,其实有一个比较容易理解的计算公式,还是以这个图为例:

想要找到绘制点的话只需要遵守DF:DE= AD:AB= BE:BC,那么此时F点就是绘制点,因为比例是一样的。

其原理跟二阶的一样,看一下图:

了解了一、二、三阶贝塞尔曲线之后,接着再来感受一下更多阶的效果,让你瞬间晕眩:

1、四阶贝塞尔曲线:

2、五阶贝塞尔曲线:

这对于学习贝塞尔曲线来说是一个不错的辅助工具,有兴趣的可以下下来跑一跑。

而我在Android7.0的源码中貌似对于三创的API是这个方法名:

应该是有版本差异,这里就不过多纠结了,反正系统支持最多是3阶。

这里以绘制二阶为例,来体验一下画法。

这里还是基于原来学习UI时搭建的工程新建一个module:

接下来新建一个自定义View,为曲线的绘制搭好环境:

也就是我手指移动的位置就是一个控制点。

对于三阶的贝塞尔曲线,除了控制点之外,还需要有一个开始点和结束点,这里定死一下:

整个代码如下:

这里运行看一下:

既然是四阶,肯定是需要五个点的,一个开始点,一个结束点,还有三个控制点,所以在正式绘制曲线之前,先将准备工作做到位,这块比较简单,直接给出代码了:

代码如下:

运行看一下效果:

当然这个点是随机的,每次运行是不一样的。

好,接下来的核心就是怎么来绘制贝塞尔曲线的问题了,这里则需要使用到一个比较“高深”的算法了,如小标题所示:德卡斯特里奥算法,百度一下它:

在正式了解该算法之前,我们先从贝塞尔曲线绘制特点来分析一下,比如这个三阶贝塞尔曲线:

是不是最终其实就是降阶来进行处理的,如下:

而对于“德卡斯特里奥算法”而言,它的目的就是可以达到降阶的效果,其实也就是通过这个算法,最终能够算出降为一阶的绘制点:

有了绘制点,那么将所有绘制点连接起来,不就成了一个曲线了么,这就是该算法的目的之所在,另外该算法能实现N阶贝塞尔曲线,是一个通用的算法,所以首先先明白该算法的一个目的很重要

关于它的算法逻辑,说实话是有一点难理解的,反正我是在网上找了一圈,貌似说得都有点生涩,如果不理解透,你在编写代码时肯定会懵,不信,我先贴出来之后利用此算法实现贝塞尔曲线的一个代码:

是不是在你不了解此算法的公式之前,这代码是完全理解不了的,仅仅只能把这个方法当一个工具方法来用,但是别人问你怎么实现时,可以丢一句:“代码如此,自己看吧”。

1、先理解如何在一个线段中获得具体比例的点:【这块有点小绕,但是必须理解透】

因为,有一个式子,跟我提前贴的代码中的式子很像呀:

其实两篇思想一样,只是这篇语言组织上详细通俗一点,咱们就根据两位大佬的博客,带着自己的理解来挼一挼:

其中提到了“向量”这个词, 不知各位都对它还记得么,对我来说印象比较深刻,因为之前学了“线性代数”:

那:

那是不是:

所以很显然C就把向量AB分成了u:1-u了。接下来则需要来解释上面标红的一句话了:“整个AB看成是1”,这里回忆一下最开始对于一阶贝塞尔曲线的执行过程:

看到其中的t了么?最大就是1,因为曲线的绘制就是根据算出来的绘制点连线而成,而多少个绘制点则你可以自己来根据这个1进行拆分,可能这边说得有点绕,这里先把之后咱们实现时需要用到的一个代码先提前亮出来吧,这样就比较好理解了:

理解一下,“A到B的向量是B - A”,这个应该容易理解吧,就是指AB之间的距离嘛,然后C点占整个1的百分比是u,那么C点的位置很明显就是u * (B -A)嘛,这样就把C给算出来了呀,但是“考虑到A点的位置”,由于A点的位置不一定是原点,比如发生偏移之类的,那么整个C点的位置还得基于A的位置来算,所以整个式子就变成了“A + u(B - A)”,再根据结合率之类的,最终就可以变化成这个式子了:“(1 - u)*A + u*B”,其中是不是可以发现,只要我将u这个比例值知道了,整个C点的绘制位置就知道了?

2、理解递归的逻辑:

对于一个N阶贝塞尔曲线而言,你最终要绘制的只是最里面1阶贝塞尔曲线,所以光知道了,比如这样的一个五阶贝塞尔曲线的演变过程:

也就是在计算过程中会涉及到N多个点对吧,但是绘制而言其实只需要它就可以了:

很明显这里需要一个递归的过程最终再算出指定t下的贝塞尔曲线所在的那个绘制点对吧, 那递归的思路是啥呢?下面基于图中的这个场景来简单挼一下:

其中的u为0.4,也就是该点是整个贝塞尔曲线40%的位置,说实话,这个递归过程不是那么好描述,其实就是降级的过程,最终降到一阶,其绘制点就给算出来了,这块具体的过程,我打算先把代码实现贴出来之后,再结合程序来进行理解,这样可能更加容易理解一点,所以这里的递归过程先忽略。

接下来直接来实现多阶贝塞尔曲线了,代码其实还是比较亲切的,如下:

a、先将整个绘制分成1000等份,然后一等份一等份的算出绘制点:

而具体算法,目前还未实现:

b、完成绘制点的计算:

整体的思路就是如果当前是1阶了,则直接根据德卡斯特里奥算法来算出绘制点,如果大于1阶的,则递归降级处理,具体的细节这里先不解释,因为下面会根据运行结果再来分析整个程序的执行过程的,这样你就明白了其递归的一个逻辑了。

接下来运行看一下,目前看的是4阶的效果,由于点是随机产生的,多运行几次,看曲线画得完不完美:

嗯,挺完美的~~

为了验证这种方式的通用性,用两个极端的阶数来测试一下,一个是2阶,一个是7阶,先来看一个2阶的吧,咱们把程序写一个数字既可,其它完全不需要动:

运行:

接下来再看一下7阶的,同样改个数字既可:

运行:

完美,可见通过这种算法来实现的贝塞尔曲线可以满足所有阶次。

好!!最后这里还遗留一个问题,那就是整个递归的思路是咋样的呢?对应的代码是:

这里以三阶贝塞尔曲线绘制为例,来debug一下咱们的程序,为了方便分析,这里将随机的点改为定死的点,如下:

先看一下运行的样子:

注意,起始点和结束点的位置,因为关系到待会的逻辑分析涉及到的控制点的控制:

而为了方便分析流程,这里将t定死一个,只分析一个绘制点既可,如下:

目前长这样了:

而为了更加精简,只分析一下坐标点的x的值计算过程既可,因为y值的计算过程是一模一样的,也就是它:

另外,为了让分析代码变得清晰,这里将deCasteljauX调整一下:

是不是这样跟咱们理论所分析的公式就一模一样了:

这样分析递归也好分析一些,不然一行代码有两个递归看着有点晕,一切就绪,接下来进入代码分析阶段。

1、i=3,j=0:

其中i代表是阶数,j代表的是控制点,也就是首先是来计算三阶的这

由于阶数不是1,所以此时会进入递归环节。

2、递归计算A点:float A = deCasteljauX(i - 1, j, t);

【注意】:这里我制造效果时有点顺序问题,应该p0在p3的位置的,由于在写逻辑时已经基于这样的图进行了,这里就说明一下,p3是第一个点,p0是最后一个点【正常p0是第一个点,p3是最后一个点嘛,犯了个细节错误,将错就错了,不过不影响整体的逻辑理解】,这个注意一下!!!

而这个A点的算出,很明显是需要根据降阶操作之后的这俩A,B点来算出,如下:

所以,为了降阶,这里将阶数减一再次递归了:

然后此时进入递归环节:

由于阶数目前还是不等于1,又会执行到这:

算二阶的A:

而此时由于阶数已经降为2了,再递归降一级,就变为1阶了,此时结果就直接可以算出返回了:

此时的A为619.23193,也就是这个点坐标的x值:

算二阶的B:

此时则开始算降阶的B点了:

同样由于阶数已经还是2,再递归降一级,就变为1阶了,此时结果就直接可以算出返回了:

此时的B为361.1466,也就是这个点坐标的x值:

结果得出:

此时再根据德卡斯特里奥算法,此时这个二阶上的点结果x值就出来了:

也就是这个点算出来为482.70563:

这里好好理会一下整个A值的计算过程,很明显的一个降级,也就是不管多少阶,最终都会递归降到1阶,然后再算出其中的A,B点的值,再算出最终的曲线绘制点,当然这个递归不是很好理解的,需要自己边画边挼一下才行。

3、计算B点:float B = deCasteljauX(i - 1, j + 1, t);

理清了A点的计算递归逻辑,这个B点的计算逻辑是一模一样的,同样在分析前,需要明确目标,这句代码的意思是算出它:

而这个B点的算出,很明显是需要根据降阶操作之后的这俩A,B点来算出,如下:

所以,为了降阶,这里将阶数减一再次递归了:

然后注意,此时的j控制点+1了:

这是因为此时B点的算出得根据第二个控制点来:

是不是这两个点得基于p2起步来算出?所以这里的控制点数+1了,这个细节需要好好体会。

然后此时进入递归环节:

由于阶数目前还是不等于1,又会执行到这:

算二阶的A:

而此时由于阶数已经降为2了,再递归降一级,就变为1阶了,此时结果就直接可以算出返回了:

此时的A为361.1466,也就是这个点坐标的x值:

算二阶的B:

此时则开始算降阶的B点了:

同样由于阶数已经还是2,再递归降一级,就变为1阶了,此时结果就直接可以算出返回了:

此时的B为213.16849,也就是这个点坐标的x值:

结果得出:

此时再根据德卡斯特里奥算法,此时这个二阶上的点结果x值就出来了:

也就是这个点算出来为282.86667:

4、根据德卡斯特里奥算法来算出结果:

目前A,B两点已经算出来了,你说要绘制的这个点怎么得出应该就很简单了吧?

这样,绘制点就成功算出:

经过这么完整的一个debug分析,是不是比直接分析代码要容易理解一些?对于递归的程序,如果当你光看代码不好理解的话,建议用debug的方式完整的梳理一遍,这样你就会比较容易理解,不过!!!整体还是比较晕的,这里最后再整理一下,其实递归的目的就是降级,降到1阶,递归的目的就是为了算出1阶的开始点和结束点:

有了这俩点,最终绘制点就可以根据德卡斯特里奥算法来算出了。

最后,咱们将debug时的一些代码给还原,最后再来看个东东,就是关于它的作用:

之前不是说这个数值越大其绘制出来的曲线就越细腻么,为了体现,咱们改为很小,反着看一下,是不是越小,越不细腻,这里先把1000的图贴出来:

然后咱们将其改为10,再对比看一下:

是不是对比非常明显,等份小了,很明显点与点之间的距离大了,然后连线当然就不圆润了啦,通过这个对比应该就明白这个等份的意义了吧?

至此,我们已经学会了N阶贝塞尔曲线的画法了,但是!!!在之后咱们实现的QQ汽泡的效果时只会使用到Android Path API来绘制二阶贝塞尔曲线的,那这么复杂的算法有何意义呢?可以让你对贝塞尔曲线的概念理解得更加深刻呀,如果你只学Android API和二三阶贝塞尔曲线的用法,人家都把实现细节给你封装好了,能知道贝塞尔曲线的精髓么?这篇耗了我业余大概一周多时间梳理吧,收获反正是挺大的,有种茅塞顿开的感觉,如果你有心,建议自己写一篇博客从头至尾的按自己的思路来梳理分享出来,哪怕是网上参考的【但是一定得要带着自己的理解去解读,而不是直接copy】,这样你就能体会到虽说时间成本比较大,但是你的收获也很大,这也是为啥我一直坚持的原因,这样可以让自己摒弃浮躁,脚踏实地的一步步朝前走。

本来计划还要实现一个qq汽泡的效果滴,不过在这个算法上花得篇幅较长,放下次吧。

THE END
0.人文主义的起源(精选5篇)(二)人文精神的演变过程 大约两千五百年前,普罗泰格拉喊出了一句影响西方至今的口号──“人是万物的尺度。”他解释说:一阵风吹来,对于感觉冷的人是冷的,对于感觉不冷的人是不冷的。这个哲学命题的意思是:个人的感觉是判断一切事物的标准。在西方,普罗泰格拉是率先把人放在万物中心位置的思想家。这一光辉思想增jvzquC41yy}/3vnujw4dqv4jcq}fp8773:770qyon
1.2024年葡萄酒流通行业分析报告十、上海卡斯特酒业有限公司 1、企业发展概况 2、企业组织构架 3、企业荣誉分析 4、企业产品分析 5、企业研究和开发 6、企业经营情况分析 7、企业业务及收入 8、企业战略目标分析 第五部分 发展前景展望 第十六章 2024-2030年进口葡萄酒流通行业前景及趋势预测分析 第一节 2024-2030年进口葡萄酒流通市场发展前景 一、jvzquC41yy}/erw0ep532:9/2:5Qw]fqLk{Mk~YqpiNbpp^gHgtYkKfqIcu/j}rn
2.系统管理理论的大师:卡斯特管理前智新浪财经卡斯特和罗森茨韦格认为,除了某些程序化的、可计量的机械式生产组织以外,未来组织的演变趋势,将是一个从稳定机械式结构向适应性有机式结构的运动过程。他们在20世纪六七十年代,就对未来组织的发展趋势做出了如下推断。 组织将在一个动荡的、要求不断革新和调整的环境之中进行活动。 jvzq<84hkpgoen3ukpg/exr0ep5mgjigtunjr8rins€0495932841:832669;@<70unuou
3.科学管理理论的含义汇总十篇[10]弗里蒙特·E·卡斯特,詹姆斯·E·罗森茨韦克。组织与管理[M].北京:中国社会科学出版计,1985. 篇(2) 对西方管理理论发展的各个阶段所形成的流派,研究者有不同的概括。如克劳德·小乔治概括了四个管理流派:科学管理、行为学派、管理过程学派和数量学派。[1]168-182JanesF.Stoner等概括为科学管理学派、古典组织jvzquC41yy}/z~jujw4dqv3ep1nbq€jp16882<3jvor
4.社会学理论基于此,他认为,传统城市社会学并没有“特定的理论对象”,因为它的研究主题,如人文生态学视角下的城市及过程、城市空间演变、移民群体的文化适应等,不具备理论差异性的特点。传统城市社会学也没有“特定真实对象”,它将城市作为研究对象,太宽泛,缺乏“任何明确界限”。按照卡斯特的逻辑,必须在一个系统中抽象出一个jvzq<84uqeopnxl{qn4swl3gfw4dp8xjz{p0hƒxjz1l{uq}nn1i6hk:9:58e2j9h5eh83>9dh::g5n=5934ivv
5.卡斯特《网络社会的崛起》资本主义本身已经历了深刻的再结构过程,其特性是管理上有更大的弹性;公司内部以及与其他公司的关系均分散化与网络化;资本相对于劳动的大幅度增长,使得劳工运动的影响力相应式微;工作关系日趋个体化与多样化;妇女在通常是遭受歧祧的工作条件下,大量地被编纳成为有薪劳动力;国家干预则选择性地解除对市场的管制,并依每jvzquC41dqul0mtwdct/exr1cptpvjykqp5:7>::95=0
6.行为科学管理理论范文当然,行为科学管理理论也存在一定的局限,实际上两种管理方式并非泾渭分明,科学管理不会对人的社会需要毫无关注,而人本管理也难以完全撇开科学的工作程序和有效的组织建设。高校在师德建设过程中应该吸取行为科学理论的合理之处,使之与传统的管理模式有机结合,从而真正发挥其应有的积极效应。jvzquC41yy}/i€~qq0ipo8mcqyko1;85:4=/j}rn
7.〈转〉冯江的书单日记9. [西班牙]曼纽尔•卡斯特,信息时代三部曲: 《网络社会的崛起》 《认同的力量》 《千年终结》 夏铸九译,北京:社会科学文献出版社,2003 10. [美] 巫鸿,《武梁祠——中国古代画像艺术的思想性》,柳扬,岑河译,北京:三联,2006。“开放的艺术史” jvzquC41o0jpwkfp0eun1wtvg1795B6:5:<
8.《网络社会的崛起》曼纽尔·卡斯特著(4页)PAGE 1 PAGE 1 《网络社会的崛起》 曼纽尔·卡斯特著 我在前面的章节里曾经提到,我们的社会是环围着流淌而建构起来的:资本流淌、信息流淌、技术流淌、组织性互动的流淌、影像、声音和象征的流淌。流淌不仅是社会组织里的一个要素而已:流淌是支配了我们的经济、政治与象征生活之过程的表现。果真如此,那么, 我们社会jvzquC41oc~/dxtm33>/exr1jvsm1;5431722;4925628=6252652<80ujzn
9.〈建筑〉《英》曼纽尔·卡斯特:网络社会的崛起.pdf1990年 新职业结构 信息化社会的成熟:21世纪的就业预测 总结:就业结构演变及其对信息化社会之比较分析的意义 有全球劳动力吗? 信息化范式的劳动过程 信息技术对就业的影响:通向无工作社会? 工作与信息分隔:弹性工作者 信息技术与劳资关系的再结构:社会二元论或片断化的社会? 附录AjvzquC41o0hpqt63:0ipo8mvon532:<132831:8993;78?3ujvs
10.17c18世纪欧洲艺术风格演变,探索巴洛克与洛可可,影响现代设计潮流17c18世纪欧洲艺术风格演变,探索巴洛克与洛可可,影响现代设计潮流的过程,实则是人类情感表达形式的螺旋上升。当扎哈·哈迪德建筑中流淌的液态金属遇见18世纪洛可可的石膏卷草纹,当菲利普·斯塔克的榨汁机重现巴洛克雕塑的动势美学,我们终将理解:所有创新的本质,都是对历史的深情回望。 jvzq<84ycr4igkjkogth|qfpi0io1ljkiq{03>4944788