• 计算机图形学中的曲线问题——贝塞尔曲线的绘制


    贝塞尔曲线的绘制

    由于 CSDN 的博客修改字数的限制,我们不得不将这一部分放到一个新的博客中。原文详见:

    GGN_2015
    计算机图形学中的曲线问题

    贝塞尔曲线的几何作图法

    在上面介绍儿时的回忆中,我们介绍了对于抛物线绘制的一种方法。如下图所示,我们要先选定三个控制点 A , B , C A, B, C A,B,C,连接 A B AB AB B C BC BC。我们在 A B AB AB 上取一点 D D D,在 B C BC BC 上取一点 E E E 使得:
    A D A B = B E B C = t \frac {AD}{AB}=\frac{BE}{BC}=t ABAD=BCBE=t

    其中 t t t 是一个定义在 [ 0 , 1 ] [0, 1] [0,1] 区间上的数。之后我们再连接 D E DE DE 并在 D E DE DE 上取一点 F F F 使得:
    D F D E = t \frac{DF}{DE}=t DEDF=t
    静态图

    t t t [ 0 , 1 ] [0, 1] [0,1] 之间变化时, F F F 点的轨迹就是一条抛物线(换言之,二次贝塞尔曲线)。当 t t t 变化时,点 F F F 的运动效果如下:

    曲线绘制
    对于三次贝塞尔曲线我们也可以使用同样的方法进行绘制,只不过这次控制点的个数要增加到四个。先取四个控制点 A , B , C , D A, B, C, D A,B,C,D,分别连接 A B AB AB B C BC BC C D CD CD,使用同样的比例 t t t 在这三个线段上各取一点,记为 E , F , G E, F, G E,F,G。连接 E F EF EF F G FG FG,再使用相同的比例 t t t 在这两条线段上分别取一点,记为 J , K J, K J,K。最后,连接 J K JK JK,在线段 J K JK JK 上按照比例 t t t 取一点 M M M。在 t t t 变化的过程中, M M M 点的运动轨迹就是一条三次贝塞尔曲线。

    相同的比例指:
    A E A B = B F B C = C G C D = E J E F = F K F G = J M J K = t \frac{AE}{AB}=\frac{BF}{BC}=\frac{CG}{CD}=\frac{EJ}{EF}=\frac{FK}{FG}=\frac{JM}{JK}=t ABAE=BCBF=CDCG=EFEJ=FGFK=JKJM=t

    三次贝塞尔曲线

    这个关系虽然看起来比较繁琐,但实际上并不复杂。可以看到在这个三次贝塞尔曲线的几何作图法表述中,点 J J J 和点 K K K 各自运动的轨迹就是一条二次的贝塞尔曲线,而点 M M M 的运动轨迹是一条三次贝塞尔曲线,因此,我们可以说三次贝塞尔曲线是对两条二次贝塞尔曲线的“合并”。运动效果如下:

    三次贝塞尔曲线
    J J J 点的运动方程为 f 1 ( t ) , t ∈ [ 0 , 1 ] f_1(t), t\in[0, 1] f1(t),t[0,1] K K K 点的运动方程为 f 2 ( t ) , t ∈ [ 0 , 1 ] f_2(t), t\in[0, 1] f2(t),t[0,1],则 M M M 点的运动方程为 f 3 ( t ) = ( 1 − t ) ⋅ f 1 ( t ) + t ⋅ f 2 ( t ) f_3(t)=(1-t)\cdot f_1(t)+t\cdot f_2(t) f3(t)=(1t)f1(t)+tf2(t) 。这种合并会使得曲线 f 3 f_3 f3 的前半段比较接近 f 1 f_1 f1,后半段比较接近 f 2 f_2 f2。下图中的绿线和蓝线分别是 f 1 f_1 f1 f 2 f_2 f2,红线是 f 3 f_3 f3

    对比
    为了表述方便,我们称:折线 A B C D ABCD ABCD 是红色曲线 f 3 f_3 f3 的控制多边形。

    贝塞尔曲线的分裂法绘制

    根据文章正文中的介绍我们已经得知,如果 A B C D ABCD ABCD 是曲线 f 3 f_3 f3 的控制多边形,那么有:
    f 3 ( t ) = ( 1 − t ) 3 ⋅ A + 3 ( 1 − t ) 2 t ⋅ B + 3 ( 1 − t ) t 2 ⋅ C + t 3 ⋅ D , t ∈ [ 0 , 1 ] f_3(t)=(1-t)^3\cdot A+3(1-t)^2t\cdot B+3(1-t)t^2\cdot C+t^3 \cdot D, t\in[0, 1] f3(t)=(1t)3A+3(1t)2tB+3(1t)t2C+t3D,t[0,1]

    t t t 变化的过程中,我们可以观察到,当 t → 0 t\to 0 t0 时, A E J M AEJM AEJM 四点几乎接近左半段曲线,当 t → 1 t\to 1 t1 时, M K G D MKGD MKGD 几乎接近右半段曲线,而这种性质中似乎暗含着一些不可告人的秘密。正如 A B C D ABCD ABCD 是整段曲线 f 3 f_3 f3 的控制多边形,我们有理由猜测: A E J M AEJM AEJM 是否是 f 3 f_3 f3 M M M 左侧部分的曲线的控制多边形而 M K G D MKGD MKGD f 3 f_3 f3 M M M 右侧部分的控制多边形呢?

    t=1/2
    假设当前 t = 1 2 t=\frac 1 2 t=21,那么我们可以算出 E , J , M E, J, M E,J,M 三点各自的坐标:
    E = ( 1 − t ) ⋅ A + t ⋅ B = A + B 2 F = ( 1 − t ) ⋅ B + t ⋅ C = B + C 2 G = ( 1 − t ) ⋅ C + t ⋅ D = C + D 2 J = ( 1 − t ) ⋅ E + t ⋅ F = A + 2 B + C 4 K = ( 1 − t ) ⋅ F + t ⋅ G = B + 2 C + D 4 M = A + 3 B + 3 C + D 8

    E=(1t)A+tB=A+B2F=(1t)B+tC=B+C2G=(1t)C+tD=C+D2J=(1t)E+tF=A+2B+C4K=(1t)F+tG=B+2C+D4M=A+3B+3C+D8" role="presentation">E=(1t)A+tB=A+B2F=(1t)B+tC=B+C2G=(1t)C+tD=C+D2J=(1t)E+tF=A+2B+C4K=(1t)F+tG=B+2C+D4M=A+3B+3C+D8
    EFGJKM=(1t)A+tB=2A+B=(1t)B+tC=2B+C=(1t)C+tD=2C+D=(1t)E+tF=4A+2B+C=(1t)F+tG=4B+2C+D=8A+3B+3C+D

    我们定义 A E J M AEJM AEJM 四个点确定的三次贝塞尔曲线为 f ( t ) f(t) f(t),则有:
    f ( t ) = ( 1 − t ) 3 ⋅ A + 3 ( 1 − t ) 2 t ⋅ E + 3 ( 1 − t ) t 2 ⋅ J + t 3 ⋅ M , t ∈ [ 0 , 1 ] f(t)=(1-t)^3\cdot A+3(1-t)^2t\cdot E+3(1-t)t^2\cdot J+t^3 \cdot M, t\in[0, 1] f(t)=(1t)3A+3(1t)2tE+3(1t)t2J+t3M,t[0,1]

    我们不妨把上式整理成只含有 A B C D ABCD ABCD 四个点的形式:
    f ( t ) = ( 1 − t ) 3 ⋅ A + 3 ( 1 − t ) 2 t ⋅ A + B 2 + 3 ( 1 − t ) t 2 ⋅ A + 2 B + C 4 + t 3 ⋅ A + 3 B + 3 C + D 8 , t ∈ [ 0 , 1 ] = ( A B C D ) × [ 1 1 2 1 4 1 8 0 1 2 2 4 3 8 0 0 1 4 3 8 0 0 0 1 8 ] × ( ( 1 − t ) 3 3 ( 1 − t ) 2 t 3 ( 1 − t ) t 2 t 3 ) , t ∈ [ 0 , 1 ]

    f(t)=(1t)3A+3(1t)2tA+B2+3(1t)t2A+2B+C4+t3A+3B+3C+D8,t[0,1]=(ABCD)×[1121418012243800143800018]×((1t)33(1t)2t3(1t)t2t3),t[0,1]" role="presentation">f(t)=(1t)3A+3(1t)2tA+B2+3(1t)t2A+2B+C4+t3A+3B+3C+D8,t[0,1]=(ABCD)×[1121418012243800143800018]×((1t)33(1t)2t3(1t)t2t3),t[0,1]
    f(t)=(1t)3A+3(1t)2t2A+B+3(1t)t24A+2B+C+t38A+3B+3C+D,t[0,1]=(ABCD)×1000212100414241081838381×(1t)33(1t)2t3(1t)t2t3,t[0,1]

    接下来这一步需要比较复杂的整理,具体的步骤我们就不做了,简单而言,我们要将上面的三个矩阵中的后两个乘起来:
    f ( t ) = ( A B C D ) × ( ( 1 − t 2 ) 3 3 ( 1 − t 2 ) 2 t 2 3 ( 1 − t 2 ) ( t 2 ) 2 ( t 2 ) 3 ) = f 3 ( t 2 ) , t ∈ [ 0 , 1 ] f(t)=\left(

    ABCD" role="presentation" style="position: relative;">ABCD
    \right)\times \left(
    (1t2)33(1t2)2t23(1t2)(t2)2(t2)3" role="presentation" style="position: relative;">(1t2)33(1t2)2t23(1t2)(t2)2(t2)3
    \right)=f_3(\frac t 2), t\in [0, 1] f(t)=(ABCD)×(12t)33(12t)22t3(12t)(2t)2(2t)3=f3(2t),t[0,1]

    这也就说明了,当 t t t 0 0 0 取到 1 1 1 时, f ( t ) f(t) f(t) 恰好取遍曲线 f 3 f_3 f3 的前一半。因此以 A E J M AEJM AEJM 为控制多边形的贝塞尔曲线恰好为以 A B C D ABCD ABCD 为控制多边形的贝塞尔曲线的前一半;同理,以 M K G D MKGD MKGD 为控制多边形的贝塞尔曲线恰好为以 A B C D ABCD ABCD 为控制多边形的贝塞尔曲线的后一半。

    按照这一原理,我们可以设计一个递归算法来绘制一条贝塞尔曲线:当我们要绘制以 A B C D ABCD ABCD 为控制多边形的贝塞尔曲线时,我们先要计算 B B B 点和 C C C 点到 A D AD AD 的距离,如果 B B B 点和 C C C 点到 A D AD AD 的距离都很近,换言之, A B C D ABCD ABCD 近似共线,我们就不再递归直接将线段 A D AD AD 视为对贝塞尔曲线的近似。如果 B B B C C C 中有一者离线段 A D AD AD 很远,将这个贝塞尔曲线按照上述方法分成 A E J M AEJM AEJM M K G D MKGD MKGD 两部分,并分别递归地进行绘制。

  • 相关阅读:
    Java实现double类型数据取小数点位数
    post更新,put相当于删除重新增一条
    【聊天系统的优化】RPC方式的优化
    亚马逊个人漂浮装置UL 1177测试报告审核申请
    第一位女性商业程序员玛丽库姆斯去世,享年 93 岁
    P8196 [传智杯 #4 决赛] 三元组
    记录ajax的jsonp类型请求
    贪心算法-金条切割问题
    多多表查询优化,逆向思维
    threejs 加载各种格式的3d模型 封装
  • 原文地址:https://blog.csdn.net/GGN_2015/article/details/128165024