包教包会-贝塞尔曲线的绘制原理与应用

包教包会-贝塞尔曲线的绘制原理与应用

大家好,又见面了,我是全栈君。

说来话长,这一切都得从PhotoShop中的钢笔工具开始说起…

声明:本文不含复杂数学公式,学渣放心阅读吧?(我仿佛看到了学渣们留下了激动的泪水)

背景

贝塞尔曲线(Bézier curve)是应用于二维图形应用程序的数学曲线,贝塞尔曲线基于多个点构成。它的应用非常广泛,比如说PS中的钢笔工具所绘画的曲线就是贝塞尔曲线,绘制动画的运动轨迹等等,而最近一次想用到贝塞尔曲线是想做一个 路径动画

简介

在iOS开发中一般通过UIBezierPath来实现贝塞尔曲线的绘制,平时一般使用绘制二阶和三阶贝塞尔曲线的方法。而我们要做的远超二三阶的贝塞尔曲线,本文 iOS Demo在原理上实现了N阶贝塞尔曲线的绘制,未使用任何相关API,纯手动绘制贝塞尔曲线,并且可以拖动滑块浏览贝塞尔曲线的绘制过程。

本文 iOS Demo 实现以下功能:

实现功能 描述
绘制贝塞尔曲线 1、点击空白处设置贝塞尔曲线的点
2、可以设置贝塞尔曲线阶数
3、播放贝塞尔曲线绘制过程
4、拖动滑块,自由查看绘制过程每一个瞬间
简易曲线图表 每两个点之间都是用3阶贝塞尔曲线连接(细节待完善)
过山车 1、在空白处绘制贝塞尔曲线
2、过山车沿着绘制的贝塞尔曲线行驶
3、支持多个连接的贝塞尔曲线路径

Demo示例图

8阶贝塞尔曲线绘制过程

贝塞尔曲线的绘制原理

说到绘制原理,如果贴?这张图,我只能说:什么鬼!!!我看不懂,听不见,你说什么…
路人甲:简单点…说话的方式简单点~

失败案例

首先提供一个可以动态绘制贝塞尔曲线的网站帮助你更好地理解贝塞尔曲线的绘制。

1. 点

贝塞尔曲线点的数量决定了曲线的阶数,一般N个点构成的N-1阶贝塞尔曲线,即3个点为二阶,至少由3个点组成,为什么两个点不行,两个点组成的是直线。按顺序,第一个点为 起点 ,最后一个点为 终点 ,其余点都为 控制点

A起点、B控制点 、C终点以及绘制的贝塞尔曲线

2. 点生线

这里说的线不是贝塞尔曲线,而是各个点按顺序连接起来,形成的直线,如上图ABBC两条线。在这里我们要将整个曲线的绘制量化为从0~1的过程,用progress为当前过程的进度,progress的区间即0~1。每一条线都需要根据progress生成一个点,如下图,一个点从P0移动到P1,这是这条线从0~1的过程。

根据进度点从起点向终点移动

下面是绘制一个二阶贝塞尔曲线过程,先给口诀: 点生线,线生点 ?。由ABC这3个点组成2条线ABBC,2条线根据progress分别生成2个移动的点DE,而DE又连成一条线,始终保持AD:DB=BE:EC

progress为0.3 的连线

移动的线

DE,DE再根据progress生成点F,只剩一个点,无法构成线,即为最终构成贝塞尔曲线的点。红色点为progress0~1过程中点F的移动过程,保持AD:DB=BE:EC=DF:FE

progress为0.3 最终的点

点F的移动过程

3. 绘制贝塞尔曲线

经过上面 点生线,线生点 的过程 ,我们拿到了点F在移动中所有点的,将这些点集合连接起来,即形成了贝塞尔曲线。progress自增越慢,点集合的点越多,曲线就越细致。

绘制二阶贝塞尔曲线过程

4. N阶贝塞尔曲线

稍微了解算法的同学就能发现,其实 点生线,线生点 是一个递归的过程,通过底层的点,一步步推算出最高阶的点。整个推导过程像一个金字塔,底部点的数量最多,每高一阶点的数量就减1,直至最高阶只有1个点。

下面是递归代码:

// 贝塞尔曲线每高一阶  需要递归次数+1
+ (NSArray *)recursionGetsubLevelPointsWithSuperPoints:(NSArray *)points progress:(CGFloat)progress{
    // 得到最终的点 正确结束递归 
    if (points.count == 1) return points;

    NSMutableArray *tempArr = [[NSMutableArray alloc] init];
    for (int i = 0; i < points.count-1; i++) {
        // 第一个点 
        NSValue *preValue = [points objectAtIndex:i];
        CGPoint prePoint = preValue.CGPointValue;
        // 第二个点
        NSValue *lastValue = [points objectAtIndex:i+1];
        CGPoint lastPoint = lastValue.CGPointValue;

        // 两点坐标差
        CGFloat diffX = lastPoint.x-prePoint.x;
        CGFloat diffY = lastPoint.y-prePoint.y;

        // 根据当前progress得出高一阶的点
        CGPoint currentPoint = CGPointMake(prePoint.x+diffX*progress, prePoint.y+diffY*progress);
        [tempArr addObject:[NSValue valueWithCGPoint:currentPoint]];
    }
    // 继续下一次递归过程
    return [self recursionGetsubLevelPointsWithSuperPoints:tempArr progress:progress];
}复制代码

8阶贝塞尔曲线绘制过程:

8阶贝塞尔曲线绘制过程

贝塞尔曲线的应用

光讲原理脱离实践这不是程序员的风格,简单地写了2个贝塞尔曲线的应用,都在本文 iOS Demo 里面,欢迎运行体验。

1. 过山车

通过点击屏幕收集点,将点集合生成贝塞尔曲线,可生成多个相连的贝塞尔曲线。小车按照生成的贝塞尔曲线路径前进。

a. 画路径
通过计算贝塞尔曲线的长度,根据曲线长度分配点的数量,达到点的相对均匀分布,使过山车 匀速前进

画路径

b. 发车
每个点都与前面一个点连线,通过计算得出两点的连线与水平形成的夹角,将角度赋予过山车实现 转向功能

发车

2. 简易曲线图表

a. 直线图表
即最简单的两点连成直线。

直线图表

b. 曲线图表
曲线图表的曲线全部由3阶贝塞尔曲线构成,整个曲线图不含任何棱角。

曲线图表

拓展

PaintCode

推荐一个
iOS画路径神器
PaintCode,画好图形直接生成代码,用钢笔工具画贝塞尔曲线也十分方便。下图为用钢笔工具画一个圆球(貌似不够圆?):

生成代码

总结

为了准备这一篇文章差不多理解了贝塞尔曲线的绘制原理,但是在细节处,比如说真正意义上贝塞尔曲线点的均匀分布还有待完善,求曲线公式也没有去研究,贝塞尔曲线在复杂的动画方向地应用也是大有作为。

参考

贝塞尔曲线开发的艺术
Android:贝塞尔曲线原理分析

个人水平有限,欢迎提出建议。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/108399.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • NTU NUS 申请经历

    NTU NUS 申请经历我的出国历程                ——考研+出国全纪录个人简历:本人,男,1989年出生,东北大学秦皇岛分校06级通信工程专业学生。在校期间曾获得校一等奖学金1次,二等奖学金2次,三等奖学金2次,科技创新奖学金1次,鹏远奖学金1次。曾获得校“东软杯”科技竞赛特等奖,“挑战杯”课外学术作品竞赛省三等奖,并参加过全国大学生数学建模比赛。在校期间多次获得康师傅“再来一瓶”奖励。

    2022年5月3日
    59
  • 数据挖掘的方法有哪些?

    数据挖掘的方法有哪些?数据挖掘的方法有哪些?01数据挖掘方法分类介绍1.预测性——有监督学习2.描述性——无监督学习02数据挖掘方法论1.CRISP-DM方法论2.SEMMA方法论03数据挖掘建模框架的3个原则1.以成本-收益分析为单一分析框架2.以分析主体和客体为视角3.构建全模型生命周期工作模板数据挖掘是一个多学科交叉的产物,涉及统计学、数据库、机器学习、人工智能及模式识别等多种学科,如图1-4所示。01数据挖掘方法分类介绍数据挖掘方法按照来源进行分类显得过于庞杂,而且不便于理解和记忆。按照其目

    2022年6月28日
    20
  • Ace在线代码编辑器使用「建议收藏」

    Ace在线代码编辑器使用「建议收藏」这边文章https://blog.csdn.net/liuxiao723846/article/details/106732401介绍了Ace的使用,本文围绕Ace的api深入介绍其具体功能。官网api使用文档:https://ace.c9.io/#nav=howto1、基本配置:ace有许多的配置项可供选择,通过这些配置项可以打造自己的个性编辑器你可以通过setTheme来设置主题,需要注意的是主题文件要存在,并且需要与ace.js同级,命名规则为theme-主题名.jsedito.

    2022年8月14日
    55
  • 二次与三次B样条曲线c++实现

    二次与三次B样条曲线c++实现B样条曲线构建一条平滑曲线,接近而不通过控制点(首尾点除外)。如图B样条曲线从Bezier曲线演变而来,了解B样条曲线首先得了解Bezier曲线。对于平面上的三个点P0,P1,P2,其坐标分别是(x0,y0)、(x1,y1)、(x2,y2)。二次Bezier曲线用一…

    2022年6月18日
    35
  • ios消息推送

    ios消息推送

    2021年8月19日
    62
  • 软件架构设计—软件架构概述[通俗易懂]

    软件架构设计—软件架构概述[通俗易懂]像学写文章一样,在学会字、词、句之后,就应上升到段落,就应追求文章的“布局谋篇”,这就是架构。通俗地讲,软件架构设计就是软件系统的“布局谋篇”。人们在软件工程实践中,逐步认识到了软件架构的重要性,从而开辟了一个崭新的研究领域。软件架构的研究内容主要涉及软件架构描述、软件架构设计、软件架构风格、软件架构评价和软件架构的形成方法等。软件设计人员学习软件架构知识旨在站在…

    2022年5月7日
    68

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号