贝塞尔曲线
通过以下动画可以很好地理解贝塞尔曲线的构造逻辑:
要直接从图形表示中获取公式,定义两个点之间的线性插值辅助函数就足够了,在该辅助函数中,当参数t从0变为1时,它将返回从a到b的中间值:
注意
- lerp, blend, mix - . .
有了它的帮助,您可以持续找到必要的要点-首先找到
和
然后通过他们找到
如果需要,可以将函数彼此替换并缩短-尽管这不会特别简化计算,但可以将曲线泛化为任意数量的控制点(通过伯恩斯坦多项式)。就我们而言,
轻松增加曲线的阶数-初始点设置不恒定,但是由于在n + 1个其他控制点之间进行插值:
注意
, . .
圆曲线
圆弧
为了以类似方式构造圆弧,有必要确定适当的构造逻辑-类比于用罗盘绘制圆。
最初,我们不知道圆的中心d-它是通过与点a和b处的切线垂直的交点找到的(以下称节点);切线本身是使用c点指定的(以下称为准则)。为了产生任意的圆弧(小于180°),从方向点到节点的距离相同就足够了。
椭圆弧
构造椭圆弧已经更加困难-您需要两个沿不同方向旋转的矢量(此处有更多详细信息)
使用上述找到点d的方法,我们不再能够构建椭圆的任意弧-仅从0°到90°(包括旋转一定角度)。
下弧线虫
设置条件,即矢量在图纸的开始和结尾必须位于一条直线上,在所有其他情况下,我们都得到了下摆线的弧线。这种情况不是偶然的,并且(除了曲线的独特定义之外)还保证了节点处切线的重合。结果,两个向量行进的角路径将不同,但仍加起来为180°。
在以下动画中可以看到曲线形状如何根据引导点的位置而变化:
算法
由于这里我们在二维平面上旋转,因此方便地用复数描述构造这些曲线的数学方法。
1)找到从方向点到节点的切线法线的交点:
(此处的星号表示复杂的共轭)。
2)知道d,我们找到法线的长度
以及它们的和与差
3)我们找到开始构建的单位向量
注意
sign(x).
4)找到每个向量必须通过的角路径
注意
, — . — , . . .
, — , - ; .
. ,
— - .
, — , - ; .
. ,
— - .
5)逐步将t从0更改为1,我们通过公式找到属于曲线的点
圆形花键
就像Bézier曲线一样,这些曲线可以组合以创建分段连续的样条曲线。为了确保锚点的平滑度(对接),锚点必须与两个相邻方向点成一直线。为此,您可以不显式指定锚点,而可以通过方向点的插值来指定。也完全无法完全指定它们,而是完全自动计算-例如,作为参考点之间的平均值:
在右边,为了进行比较,对二阶Bezier曲线使用了相同的方法。
注意事项和细微差别
与贝塞尔曲线不同,此处的曲线并不总是位于连接控制点的线的形状内
此外,当方向点与锚点位于同一条线上时,有一种退化的情况需要单独处理。在这种情况下,曲线退化为一条直线,并且在尝试计算点d时,会被零除。
这些曲线也限制了直线的曲率,因为该算法选择了要遵循的最小路径,并且该曲线的绕角不能超过180°。这导致以下事实:通过分段连续插值,在方向点的某个位置(右侧-贝塞尔曲线的相同点)可能会出现尖角:
结论
所考虑的构造曲线的方法的进一步发展是,涉及构造曲线的向量的数量增加,因此,方向点的数量也增加。但是,与Bezier曲线不同,顺序的增加在此并不明显,需要进行单独的思考。将它们与Bezier曲线组合的各种方法也是可行的-特别是对绘制矢量的圆心进行插值。
构造曲线的方法也不是唯一的方法,其特殊情况是圆弧和椭圆形-至少可以通过平行四边形中的直线相交来构造椭圆(但是,作者在此版本中失败了)。可能还有其他解决方案,包括本文中描述的选项-如果您对此主题有所了解,请在评论中写下。
可以从GitHub下载本文的源代码。