受疫情影响,各大、中、小学校都积极响应国家号召展开在线教育,开设空中课堂,小编也借此机会给大家来一堂工业风的”数学课”,教大家在汽车领域玩转数学。
翻开小本本,我们的数学课就开始啦,今天学习的内容就是贝塞尔曲线。

开始之前,先理解两个概念!
Béziercurve(贝塞尔曲线) 是应用于二维图形应用程序的数学曲线,曲线包含起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状也会发生相应的变化。下面我们通过图像来理解什么是贝塞尔曲线:
• 一阶贝塞尔曲线:只是起点 P0 与终点 P1 之间的线性插值,没有任何控制点,如下图所示:

一阶贝塞尔曲线动态效果
• 二阶贝塞尔曲线:有一个控制点 P1 ,曲线的形状由单个控制点决定,如下图所示:

二阶贝塞尔曲线动态效果
• 三阶贝塞尔曲线:最常用的一种曲线,也是本次课堂中我们将要用到的,有两个控制点,拥有更好的可塑性,如下图所示:

三阶贝塞尔曲线
此外,还存在更高阶的贝塞尔曲线,这里就不展开了,大家有空可以课下研究一下。
停车距离控制系统俗称“倒车雷达”,也叫“泊车辅助装置”,是汽车泊车或者倒车时的安全辅助装置,由超声波传感器(俗称探头)、控制器和显示器(或蜂鸣器)等部分组成。司机在倒车时,可以帮助司机“看见”后视镜里看不见的东西,以声音或者更为直观的显示告知驾驶员周围障碍物的情况,帮助驾驶员扫除了视野死角和视线模糊的缺陷,提高驾驶的安全性。
以上两个概念理解了,那么它们之间有什么关系呢?
别急,下面小编就教大家“在HMI开发设计中如何通过绘制贝塞尔曲线创建倒车雷达模型”。
Step 1 实现雷达距离数据的模拟展示图像
将数个不同方向雷达的读数以圆弧的方式展示出来,圆弧的半径与实际雷达测距成正比,同时各个圆弧之间需要平滑地曲线进行连接,如下图所示:

雷达波形状
Step 2 将实际圆弧与连接线分解开

雷达波形状拆分
可以看出,实际有六条圆弧和五条连接线,每处连接点的切线需要保持平行。我们借助三阶贝塞尔曲线构建连接线,同时圆弧也使用三阶贝塞尔曲线进行拟合。采用这种方式也是考虑到贝塞尔曲线的性质。
ps:贝塞尔曲线的连接性质如下:(额外知识点,帮助理解)
假设给定两条贝塞尔曲线 p(t) 和 q(t) ,相应控制点为 Pi{ i = 1,2,3,,,n} Qj{ j = 1,2,3,,,m}。如下图所示:

连接的两个三阶贝塞尔曲线
要使 p(t) 和 q(t) 达到 G0 * 连续的充分必要条件是:Pn = Q0 ;
要使 p(t) 和 q(t) 达到 G1 * 连续的充分必要条件是:达成 G0 连续的同时 Pn-1 , Q0(Pn) , Q1 这三点共线。
所以,对于上图两条三阶贝塞尔曲线而言,G1连续的条件为 P2 , Q0(P3) , Q1 这三点共线。
\ 几何连续性(geometric continuity),组合曲线在连接处满足一定的约束条件称之为具有n阶的几何连续性,简称为Gn。*
\ G0 连续 :两曲线在结合处位置连续*
\ G1 连续 :两曲线在结合处满足G0 连续的条件下,同时具有共同的切矢量*
Step 3 使用贝塞尔曲线拟合圆弧
由n段三阶贝塞尔曲线拟合圆形时,曲线端点到该端点最近的控制点的最佳距离是(4/3)tan(π/(2n))。此条件下,贝塞尔曲线的中点将落在圆弧上,感兴趣的可以自行证明,三阶贝塞尔曲线的公式如下:


使用贝塞尔拟合圆弧时控制点的位置
Step 4 通过形变圆弧获得连接线
因为连接线需要连接两段圆弧;设两段圆弧分别为 p(t) q(t) ,连接线为 r(t),则P3 = R0 ,Q0 =R3 ,R1 与 P2 、P3 共线,R3 与 Q0 、Q1 共线。所以连接线的控制点分别取 P2 关于 P3 的对称点和 Q1 关于 Q0 的对称点。
以连接线的弧度构建基础的圆弧起点终点和控制点;再将对应连接的点与连接处的缩放比例保持一致;连接线左侧两点以 rp (圆弧p的半径)作为缩放倍数,右侧两点以 rq (圆弧q的半径)作为缩放倍数。
Step 5 模拟效果
实践是检验真理的唯一标准,让我们用matplotlib绘制设计的模型,模拟效果如下图所示,红色为圆弧,蓝色为连接线:

matplotlib绘制的雷达波模型
因为Kanzi并没有提供贝塞尔曲线的绘制工具,所以只能通过传入贝塞尔曲线的数据集进行绘制。使用前文中提到的三阶贝塞尔曲线公式,可以实现一个根据 t ∈ [0,1] ,获取贝塞尔曲线不同位置的点坐标的方法。

Step 1 使用贝塞尔曲线拟合圆弧
为了使用贝塞尔曲线拟合圆弧,需要计算贝塞尔曲线的起点终点和控制点;下面提供通过圆弧的弧度计算圆弧起点终点和控制点的方法:

上述代码可以计算出一段给定弧度为sweepangle且半径为1的圆弧,圆弧的圆心为原点,圆弧关于x轴对称;不同起始角度、不同圆心、不同边长的弧线可以通过旋转平移缩放的方式获得。
Step 2 使用圆弧构建连接线
利用上一节中计算出的圆弧的起点终点和控制点,即verts_ { P0, P1 , P2 , P3 }; 将P0 P1 按照邻接的圆弧的半径进行缩放,将P2 P3 按照另一侧的圆弧的半径进行缩放,就可以得到连接两段共圆心的圆弧的连接线了。
Step 3 动态效果展示
外侧的每一段圆弧或连接线与内侧的一段圆弧组成一个模型,使用GraphicsPrimitiveTypeTriangles模式进行绘制。当雷达波的距离发生改变时,改变对应位置的圆弧的半径,从而重新生成变化的模型。下图展示了模型在圆弧半径动态变化时的状态:

动态变化的雷达波模型
Step 4 添加渲染效果
模型创建好了之后,我们可以根据半径的不同给模型充填不同的颜色,增加视觉反馈。例如,当雷达距离越远,扇面的颜色就越绿;当雷达的距离越近,扇面的颜色就越红。连接处的颜色则需要根据两端的扇面的颜色进行渐变充填。
在创建Kanzi Shader Program时,使用kanzi::ShaderProgram::CreateInfo::addUniform()方法给Shader添加UNIFORM变量;这里添加对应模型扇面或连接线两端的半径,以便在shader中根据半径不同改变模型颜色。给模型添加Shader后的效果如下图所示:

颜色在模型运动时动态变化
最后只需要将雷达传感器的数据与模型的扇面半径进行绑定,雷达波的实现就完成了。
今天课程内容有一定深度,需要童鞋们课下好好吸收。此外,大家也可以认真思考一下,如果例题中的雷达波效果不是圆形而是汽车轮廓的圆角矩形,该如何实现呢?欢迎大家在文末留言给出你的答案哟!
更多精彩推荐:
使用Kanzi和Kanzi-Lite 技术开发的HMI设计效果
帧缓存(FrameBuffer)与Kanzi Render Pass
干货 | 如何使用Kanzi Studio插件高效实现Localization多国语言本地化
Here Demo:使用Kanzi实现对地图数据的定制化实时渲染


