由之前的文章我们可以得到贝塞尔曲线的方程,今天要通过贝塞尔曲线(三次)重新推出控制点。
需求
在得到并对贝塞尔曲线做完处理后,为了让浏览器重新渲染贝塞尔曲线,必须通过贝塞尔曲线重新取得控制点坐标。
准备条件
了解 SVG 的 path 中 C/c 相关指令的用法,还有相对位置等一些概念。最好能提前获得贝塞尔曲线的表达式。
解决方案
假设我们已经得到了贝塞尔曲线的表达式: ¯P3=(1−t)3¯P0+3t(1−t)2¯P1+3t2(1−t)¯P2+t3¯P3
step1
对于 (1) 式,令 t=13,我们得到: ¯P3=(23)3¯P0+(23)2¯P1+3(13)223¯P2+(13)3¯P3
因为 ¯P3、¯P0、¯P3 的坐标是事先已知的,所以可以设 ¯P3−827¯P0−127¯P3 为 ¯B。我们设 ¯P1、¯P2 的坐标分别为 (x1, y1)、(x2, y2),¯B 的坐标为(xb, yb),由 (2) 式可以得到如下方程: 49x1+29x2=xb
49y1+29y2=yb
step2
按照 step1 的思路,令 t=23,可以得到: ¯P3−127¯P0−827¯P3=29¯P1+49¯P2
29y1+49y2=yc
step3
联立 step1 和 step2 的方程组,最终可以吧 ¯P1、¯P2 的坐标求出来。 x1=3xb−32xc
y1=3yb−32yc
x2=3xc−32xb
y2=3yc−32yb
代码实现
1 | /** |
测试结果

右图的脸为原 svg 在浏览器中的展示效果,左图的脸部轮廓白点为根据 svg 的控制点绘制出贝塞尔曲线后,再根据贝塞尔曲线反推的控制点坐标,而左图的脸部曲线则是根据这些控制点绘制出的贝塞尔曲线。从效果上看,两张人脸的轮廓基本很相似。
接下来,我对贝塞尔曲线做了平移、缩放和旋转,看看重新推出的控制点以及贝塞尔曲线的情况:
平移操作

缩放操作

旋转操作

看得出,这些基本的线性变换都不会导致贝塞尔曲线「失真」:-),这是个好消息。
参考
Algorithm for deriving control points of a bezier curve from points along that curve?