现在的位置: 首页 > 综合 > 正文

Bezier.贝塞尔曲线

2013年07月01日 ⁄ 综合 ⁄ 共 3171字 ⁄ 字号 评论关闭

转自:http://blog.sina.com.cn/s/blog_5f1852590100dsnw.html

在数学的数值分析领域中,贝塞尔曲线Bézier curve)是电脑图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝塞尔曲面,其中贝塞尔三角是一种特殊的实例。

贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由 Paul de Casteljau于1959年运用 de Casteljau 算法开发,以稳定数值的方法求出贝塞尔曲线

    实例说明

线性贝塞尔曲线

给定点 P0P1,线性贝塞尔曲线只是一条两点之间的直线。这条线由下式给出:

\mathbf{B}(t)=\mathbf{P}_0 + (\mathbf{P}_1-\mathbf{P}_0)t=(1-t)\mathbf{P}_0 + t\mathbf{P}_1 \mbox{ , } t \in [0,1]

且其等同于线性插值.

二次方贝塞尔曲线

二次方贝塞尔曲线的路径由给定点 P0P1P2 的函数 B(t) 追踪:

\mathbf{B}(t) = (1 - t)^{2}\mathbf{P}_0 + 2t(1 - t)\mathbf{P}_1 + t^{2}\mathbf{P}_2 \mbox{ , } t \in [0,1]

TrueType 字型就运用了以贝塞尔样条组成的二次贝塞尔曲线。

三次方贝塞尔曲线

P0P1P2P3 四个点在平面或在三维空间中定义了三次方贝塞尔曲线。曲线起始于 P0 走向 P1,并从 P2 的方向来到 P3。一般不会经过 P1 或 P2;这两个点只是在那里提供方向资讯。 P0 和 P1 之间的间距,决定了曲线在转而趋进 P3 之前,走向 P2 方向的“长度有多长”。

曲线的参数形式为:

\mathbf{B}(t)=\mathbf{P}_0(1-t)^3+3\mathbf{P}_1t(1-t)^2+3\mathbf{P}_2t^2(1-t)+\mathbf{P}_3t^3 \mbox{ , } t \in [0,1]

现代的成象系统,如 PostScript、Asymptote 和 Metafont,运用了以贝塞尔样条组成的三次贝塞尔曲线,用来描绘曲线轮廓。

一般化

n 阶贝塞尔曲线可如下推断。给定点 P0P1、…、Pn,其贝塞尔曲线即

\mathbf{B}(t)=\sum_{i=0}^n {n\choose i}\mathbf{P}_i(1-t)^{n-i}t^i =\mathbf{P}_0(1-t)^n+{n\choose 1}\mathbf{P}_1(1-t)^{n-1}t+\cdots+\mathbf{P}_nt^n \mbox{ , } t \in [0,1]

例如 n = 5

\mathbf{B}(t)=\mathbf{P}_0(1-t)^5+5\mathbf{P}_1t(1-t)^4+10\mathbf{P}_2t^2(1-t)^3+10\mathbf{P}_3t^3(1-t)^2+5\mathbf{P}_4t^4(1-t)+\mathbf{P}_5t^5 \mbox{ , } t \in [0,1]

如上公式可如下递归表达: 用 \mathbf{B}_{\mathbf{P}_0\mathbf{P}_1\ldots\mathbf{P}_n} 表示由点 P0P1、…、Pn 所决定的贝塞尔曲线。则

\mathbf{B}(t) = \mathbf{B}_{\mathbf{P}_0\mathbf{P}_1\ldots\mathbf{P}_n}(t) = (1-t)\mathbf{B}_{\mathbf{P}_0\mathbf{P}_1\ldots\mathbf{P}_{n-1}}(t) + t\mathbf{B}_{\mathbf{P}_1\mathbf{P}_2\ldots\mathbf{P}_n}(t)

用平常话来说,n 阶的贝塞尔曲线,即双 n - 1 阶贝塞尔曲线之间的插值。

术语

一些关于参数曲线的术语,有

\mathbf{B}(t) = \sum_{i=0}^n \mathbf{P}_i\mathbf{b}_{i,n}(t),\quad t\in[0,1]

即多项式

\mathbf{b}_{i,n}(t) = {n\choose i} t^i (1-t)^{n-i},\quad i=0,\ldots n

又称作 n 阶的伯恩斯坦基底多项式,定义 00 = 1。

点 Pi 称作贝塞尔曲线的控制点。多边形以带有线的贝塞尔点连接而成,起始于 P0 并以 Pn 终止,称作贝塞尔多边形(或控制多边形)。贝塞尔多边形的凸包(convex hull)包含有贝塞尔曲线。

注解

  • 开始于 P0 并结束于 Pn 的曲线,即所谓的端点插值法属性。
  • 曲线是直线的充分必要条件是所有的控制点都位在曲线上。同样的,贝塞尔曲线是直线的充分必要条件是控制点共线。
  • 曲线的起始点(结束点)相切于贝塞尔多边形的第一节(最后一节)。
  • 一条曲线可在任意点切割成两条或任意多条子曲线,每一条子曲线仍是贝塞尔曲线。
  • 一些看似简单的曲线(如圆)无法以贝塞尔曲线精确的描述,或分段成贝塞尔曲线(虽然当每个内部控制点对单位圆上的外部控制点水平或垂直的的距离为 4\left(\sqrt{2} -1\right)/3 时,分成四段的贝塞尔曲线,可以小于千分之一的最大半径误差近似于圆)。
  • 位于固定偏移量的曲线(来自给定的贝塞尔曲线),又称作偏移曲线(假平行于原来的曲线,如两条铁轨之间的偏移)无法以贝塞尔曲线精确的形成(某些琐屑实例除外)。无论如何,现存的启发法通常可为实际用途中给出近似值。

建构贝塞尔曲线

线性曲线

 

线性贝塞尔曲线演示动画,t in [0,1]
线性贝塞尔曲线演示动画,t in [0,1]

 

线性贝塞尔曲线函数中的 t 会经过由 P0 至 P1 的 B(t) 所描述的曲线。例如当 t=0.25 时,B(t) 即一条由点 P0 至 P1 路径的四分之一处。就像由
0 至 1 的连续 tB(t) 描述一条由 P0 至 P1 的直线。

二次曲线

为建构二次贝塞尔曲线,可以中介点 Q0 和 Q1 作为由 0 至 1 的 t

  • 由 P0 至 P1 的连续点 Q0,描述一条线性贝塞尔曲线。
  • 由 P1 至 P2 的连续点 Q1,描述一条线性贝塞尔曲线。
  • 由 Q0 至 Q1 的连续点 B(t),描述一条二次贝塞尔曲线。

二次贝塞尔曲线的结构   二次贝塞尔曲线演示动画,t in [0,1]
二次贝塞尔曲线的结构   二次贝塞尔曲线演示动画,t in [0,1]

高阶曲线

为建构高阶曲线,便需要相应更多的中介点。对于三次曲线,可由线性贝塞尔曲线描述的中介点 Q0Q1Q2,和由二次曲线描述的点 R0R1 所建构:

三次贝塞尔曲线的结构   三次贝塞尔曲线演示动画,t in [0,1]
三次贝塞尔曲线的结构   三次贝塞尔曲线演示动画,t in [0,1]

对于四次曲线,可由线性贝塞尔曲线描述的中介点 Q0Q1Q2Q3,由二次贝塞尔曲线描述的点 R0R1R2,和由三次贝塞尔曲线描述的点 S0S1 所建构:

四次贝塞尔曲线的结构   四次贝塞尔曲线演示动画,t in [0,1]
四次贝塞尔曲线的结构   四次贝塞尔曲线演示动画,t in [0,1]


(还可参阅五阶贝塞尔曲线的构成。)

应用

电脑绘图

贝塞尔曲线被广泛地在计算机图形中用来为平滑曲线建立模型。

二次和三次贝塞尔曲线最为常见

程式范例

下列程式码为一简单的实际运用范例,展示如何使用 C 标出三次方贝塞尔曲线。注意,此处仅简单的计算多项式系数,并读尽一系列由 0 至 1 的 t 值;实践中一般不会这么做,递归求解通常会更快速——以更多的内存为代价,花费较少的处理器时间。不过直接的方法较易于理解并产生相同结果。以下程式码已使运算更为清晰。实践中的最佳化会先计算系数一次,并在实际计算曲线点的循环中反复使用。此处每次都会重新计算,损失了效率,但程式码更清楚易读。

曲线的计算可在曲线阵列上将相连点画上直线——点越多,曲线越平滑。

在部分架构中,下以程式码也可由动态程式设计进行最佳化。举例来说,dt 是一个常数,cx * t 则等同于每次反复就修改一次常数。经反复应用这种最佳化后,循环可被重写为没有任何乘法(虽然这个过程不是稳定数值的)。

typedef struct { float x; float y; } Point2D; Point2D PointOnCubicBezier( Point2D* cp,float t ) { float ax, bx, cx; float ay, by, cy; float tSquared, tCubed; Point2D result; cx = 3.0 * (cp[1].x - cp[0].x); bx = 3.0 * (cp[2].x - cp[1].x) - cx; ax = cp[3].x - cp[0].x - cx - bx; cy = 3.0 * (cp[1].y - cp[0].y); by = 3.0 * (cp[2].y - cp[1].y) - cy; ay = cp[3].y - cp[0].y - cy - by; tSquared = t * t; tCubed = tSquared * t; result.x = (ax * tCubed) + (bx * tSquared) + (cx * t) + cp[0].x; result.y = (ay * tCubed) + (by * tSquared) + (cy * t) + cp[0].yreturn result; } void ComputeBezier(Point2D* cp, int numberOfPoints, Point2D* curve ) { float dt; int i; dt = 1.0 / (numberOfPoints - 1 )for( i = 0; i < numberOfPoints; i++) curve[i] = PointOnCubicBezier( cp, i*dt )}

另一种贝塞尔曲线的应用是在动画中,描述物件的运动路径等等。此处,曲线的 x、y 位置不用来标示曲线,但用来表示图形位置。当用在这种形式时,连续点之间的距离会变的更为重要,且大多不是平均比例。点将会串的更紧密,控制点更接近每一个点,而更为稀疏的控制点会散的更开。如果需要线性运动速度,进一步处理时就需要循所需路径将点平均分散。

有理贝塞尔曲线

有理贝塞尔增加可调节的权重,以提供更近似于随意的形状。分子是加权的伯恩斯坦形式贝塞尔曲线,而分母是加权的伯恩斯坦多项式的总和。

给定 n + 1 控制点 Pi,有理贝塞尔曲线可如下描述:

 \mathbf{B}(t) =\frac{\sum_{i=0}^n b_{i,n}(t) \mathbf{P}_{i}w_i }{\sum_{i=0}^n b_{i,n}(t) w_i }

或简单的

 \mathbf{B}(t) =\frac{\sum_{i=0}^n {n \choose i} t^i (1-t)^{n-i}\mathbf{P}_{i}w_i }{\sum_{i=0}^n {n \choose i} t^i (1-t)^{n-i}w_i }

抱歉!评论已关闭.